#include <windows.h>
#include <stdlib.h>
#ifndef _WINGDI_
#define _WINGDI_
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;
#endif
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libavutil/frame.h>
#include <libavutil/mem.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libavutil/avutil.h>
#include <libavutil/pixfmt.h>
void save2BmpFile(AVFrame *pFrameRGB, int width, int height, int index, int bpp)
{
char buf[5] = { 0 };
BITMAPFILEHEADER bmpheader;
BITMAPINFOHEADER bmpinfo;
FILE *fp;
char filename[20] = "E:\\test";
_itoa(index, buf, 10);
strcat(filename, buf);
strcat(filename, ".bmp");
printf("SaveAsBMP filename %s \n", filename);
if ((fp = fopen(filename, "wb+")) == NULL)
{
printf("open file failed!\n");
return;
}
bmpheader.bfType = 0x4d42;
bmpheader.bfReserved1 = 0;
bmpheader.bfReserved2 = 0;
bmpheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmpheader.bfSize = bmpheader.bfOffBits + width*height*bpp / 8;
bmpinfo.biSize = sizeof(BITMAPINFOHEADER);
bmpinfo.biWidth = width;
bmpinfo.biHeight = height;
bmpinfo.biPlanes = 1;
bmpinfo.biBitCount = bpp;
bmpinfo.biCompression = BI_RGB;
bmpinfo.biSizeImage = (width*bpp + 31) / 32 * 4 * height;
bmpinfo.biXPelsPerMeter = 100;
bmpinfo.biYPelsPerMeter = 100;
bmpinfo.biClrUsed = 0;
bmpinfo.biClrImportant = 0;
fwrite(&bmpheader, sizeof(bmpheader), 1, fp);
fwrite(&bmpinfo, sizeof(bmpinfo), 1, fp);
fwrite(pFrameRGB->data[0], width*height*bpp / 8, 1, fp);
fclose(fp);
}
int main(int argc, char **argv)
{
avcodec_register_all();
av_register_all();
avformat_network_init();
int PictureSize;
int frameFinished;
uint8_t *buf;
//输出支持解封装格式
printf("====== av_input_format =====\n");
AVInputFormat *fmt = NULL;
while ((fmt = av_iformat_next(fmt))) {
printf("name : %s\n", fmt->name);
printf("long_name : %s\n", fmt->long_name);
printf("\n");
}
printf("==============================\n");
AVFormatContext *pAVFormatCtx = NULL;
pAVFormatCtx = avformat_alloc_context();
char* filepath = "E:/video/love.avi";
if (argc == 2) {
filepath = argv[1];
printf("filepath %s \n", filepath);
system("pause");
}
//打开文件
char errorBuf[1024];
int retOpenFile = avformat_open_input(&pAVFormatCtx, filepath, NULL, NULL);
if (0 != retOpenFile) {
av_strerror(retOpenFile, errorBuf, sizeof(errorBuf));
printf("Couldn't open file %s: %d(%s)\n", filepath, retOpenFile, errorBuf);
return -1;
}
//输出文件信息
printf("------------- File Information ------------------\n");
av_dump_format(pAVFormatCtx, 0, filepath, 0);
printf("-------------------------------------------------\n");
//音视频分离
int retFindStream = avformat_find_stream_info(pAVFormatCtx, NULL);
if (0 != retFindStream) {
av_strerror(retFindStream, errorBuf, sizeof(errorBuf));
printf("Couldn't find stream %s: %d(%s)\n", filepath, retFindStream, errorBuf);
return -1;
}
int videoStreamIndex = -1;
for (int i = 0; i < pAVFormatCtx->nb_streams; i++) {
AVStream *stream = pAVFormatCtx->streams[i];
AVCodecParameters *codeParam = stream->codecpar;
if (AVMEDIA_TYPE_VIDEO == codeParam->codec_type) {
videoStreamIndex = i;
break;
}
}
if (-1 == videoStreamIndex) {
printf("Didn't find a video stream.\n");
return -1;
}
//视频流信息
AVStream *videoStream = pAVFormatCtx->streams[videoStreamIndex];
AVCodecParameters *codeParam = videoStream->codecpar;
AVCodecContext *pAVCodeCtx = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context(pAVCodeCtx, codeParam);
if (0 == pAVCodeCtx) {
printf("Couldn't create AVCodecContext\n");
return -1;
}
//查找视频解码器
AVCodecID videoCodeId = codeParam->codec_id;
AVCodec *videoDeCode = avcodec_find_decoder(videoCodeId);
if (videoDeCode == NULL) {
printf("Codec not found.\n");
return -1;
}
//打开视频解码器
int retOpenVideoDecode = avcodec_open2(pAVCodeCtx, videoDeCode, NULL);
if (retOpenVideoDecode != 0) {
av_strerror(retOpenVideoDecode, errorBuf, sizeof(errorBuf));
printf("open decode Error. %s\n", errorBuf);
return -1;
}
AVPacket *avPacket = av_packet_alloc();
AVFrame *avVideoFrame = av_frame_alloc();
AVFrame *pFrameBGR = av_frame_alloc();
PictureSize = avpicture_get_size(AV_PIX_FMT_BGR24, pAVCodeCtx->width, pAVCodeCtx->height);
buf = (uint8_t * )av_malloc(PictureSize);
avpicture_fill((AVPicture *)pFrameBGR, buf, AV_PIX_FMT_BGR24, pAVCodeCtx->width, pAVCodeCtx->height);
// 获取图像处理上下文
SwsContext *pSwsCtx = sws_getContext(pAVCodeCtx->width, pAVCodeCtx->height,
pAVCodeCtx->pix_fmt, pAVCodeCtx->width, pAVCodeCtx->height, AV_PIX_FMT_BGR24,
SWS_BILINEAR, NULL, NULL, NULL);
bool bFirstFrame = false;
int ret = 0;
int i = 0;
while( ret >= 0 ) {
//从原始数据读取一帧
ret = av_read_frame(pAVFormatCtx, avPacket);
if (avPacket->stream_index == videoStreamIndex) {
//送往解码器
int retPackt = avcodec_send_packet(pAVCodeCtx, avPacket);
if (retPackt < 0) {
av_strerror(retPackt, errorBuf, sizeof(errorBuf));
printf("packet Error. %s\n", errorBuf);
continue;
}
//从解码器获取一帧
int retDcode = avcodec_receive_frame(pAVCodeCtx, avVideoFrame);
if (retDcode < 0) {
av_strerror(retDcode, errorBuf, sizeof(errorBuf));
printf("Decode Error. %s\n", errorBuf);
continue;
}
else {
printf("Decode OK. VideoFrame index %d channels %d width %d height %d\n", i, avVideoFrame->channels, avVideoFrame->width, avVideoFrame->height);
bFirstFrame = true;
if ( i == 40 ) {
//反转图像
/* */
avVideoFrame->data[0] += avVideoFrame->linesize[0] * (pAVCodeCtx->height - 1);
avVideoFrame->linesize[0] *= -1;
avVideoFrame->data[1] += avVideoFrame->linesize[1] * (pAVCodeCtx->height / 2 - 1);
avVideoFrame->linesize[1] *= -1;
avVideoFrame->data[2] += avVideoFrame->linesize[2] * (pAVCodeCtx->height / 2 - 1);
avVideoFrame->linesize[2] *= -1;
//int it = img_convert((AVPicture*)pFrameRGB, PIX_FMT_BGR24, (AVPicture*)avVideoFrame, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
sws_scale(pSwsCtx, avVideoFrame->data, avVideoFrame->linesize, 0, pAVCodeCtx->height, pFrameBGR->data, pFrameBGR->linesize);
save2BmpFile(pFrameBGR, pAVCodeCtx->width, pAVCodeCtx->height, i, 24);
}
i = i + 1;
//break;
}
}
}
if (bFirstFrame) {
//todo 图像处理
}
//资源释放
sws_freeContext(pSwsCtx);
av_free(pFrameBGR);
av_frame_free(&avVideoFrame);
av_packet_free(&avPacket);
avcodec_close(pAVCodeCtx);
avformat_close_input(&pAVFormatCtx);
avformat_network_deinit();
printf("hello world");
system("pause");
return 0;
}
#ifdef __cplusplus
}
#endif