本文介绍利用ffmpeg-3.1.5编写最简单的视频解码的代码。
对于使用ffmpeg进行解码的代码在网上已经有很多,例如最经典的雷博的代码:http://blog.youkuaiyun.com/leixiaohua1020/article/details/47068015
由于新版本的ffmpeg中的函数和旧版本的函数有较大区别,因此本文列出了利用最新版的ffmpeg编写视频解码的代码。
本代码只能解码视频,音频部分还没有加入代码中。
本代码实现的功能是将封装好的视频解码为YUV格式的视频。
#include <stdio.h>
extern "C"
{
#include "include\libavcodec\avcodec.h"
#include "include\libavformat\avformat.h"
#include "include\libavutil\imgutils.h"
};
#define __STDC_CONSTANT_MACROS
int _tmain(int argc, _TCHAR* argv[])
{
//printf("%s", avcodec_configuration());
AVFormatContext *formatctx;
AVCodec *codec;
AVCodecContext *codecctx = NULL;
AVFrame *frame;
AVFrame *frameYUV;
AVPacket avpkt;
AVPacket *pavpkt = &avpkt;
//init
av_register_all();
avformat_network_init();
formatctx = avformat_alloc_context();
//输入文件路径
char *fileName = "Titanic.ts";
if (avformat_open_input(&formatctx,fileName,NULL,NULL)!=0)
{
printf("could not open input stream.\n");
return -1;
}
if (avformat_find_stream_info(formatctx, NULL) < 0)
{
printf("could not find stream information.\n");
return -1;
}
//output file
FILE *outputfile = nullptr;
char *outputfilename = "output.yuv";
fopen_s(&outputfile, outputfilename, "wb");
//find videoindex
int videoindex = av_find_best_stream(formatctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
if (videoindex < 0)
{
printf("could not find a video stream.\n");
return -1;
}
//find the decoder
codecctx = avcodec_alloc_context3(NULL);
if (codecctx == NULL)
{
printf("could not allocate AVCodecContext.\n");
return -1;
}
avcodec_parameters_to_context(codecctx, formatctx->streams[videoindex]->codecpar);
codec = avcodec_find_decoder(codecctx->codec_id);
if (codec == NULL)
{
printf("codec not found.\n");
return -1;
}
//open the decoder
if (avcodec_open2(codecctx, codec, NULL) < 0)
{
printf("could not open codec.\n");
return -1;
}
//output information
printf("---------------- File Information --------------\n");
av_dump_format(formatctx, videoindex, fileName, 0);
printf("------------------------------------------------\n");
//pre decode
av_init_packet(&avpkt);
frame = av_frame_alloc();
frameYUV = av_frame_alloc();
int video_dst_bufsize = av_image_alloc((uint8_t**)frameYUV->data, frameYUV->linesize, codecctx->width, codecctx->height, codecctx->pix_fmt, 1);
printf("decode video file %s to %s\n", fileName, outputfile);
//decode
int frame_count = 0;
while (av_read_frame(formatctx,pavpkt)>=0)
{
if (pavpkt->stream_index == videoindex)
{
if (avcodec_send_packet(codecctx, pavpkt) != 0){
printf("input AVPacket to decoder failed!\n");
return -1;
}
while (0 == avcodec_receive_frame(codecctx, frame)){
av_image_copy((uint8_t **)frameYUV->data,frameYUV->linesize,(const uint8_t **)frame->data,frame->linesize,codecctx->pix_fmt,codecctx->width,codecctx->height);
fwrite(frameYUV->data[0], 1, video_dst_bufsize, outputfile);
printf("decoded frame index: %d\n", frame_count);
frame_count++;
}
}
av_packet_unref(pavpkt);
}
fclose(outputfile);
av_frame_free(&frame);
av_frame_free(&frameYUV);
avcodec_close(codecctx);
avformat_close_input(&formatctx);
return 0;
}