通過調試,最終下面的代碼,在VS2013版本上已經調試通過,並且也能從mp4或者其他文件格式轉成yuv的格式。所以備忘錄收藏下:
#include <iostream>
using namespace std;
#ifdef __cplusplus
extern "C"{
#endif
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/pixfmt.h"
#include "libavutil/imgutils.h"
int main(int argc, char** argv)
{
av_register_all();
avformat_network_init();
AVFormatContext *pFormatCtx;
int ret = 0;
char filepath[] = "D:\\G\\project\\01_31_1\\Debug\\1.mp4";
pFormatCtx = avformat_alloc_context();
if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0)
{
cout << "Couldn't not open input stream." << endl;
return -1;
}
av_dump_format(pFormatCtx, 0, filepath, 0);
do
{
if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
{
cout << "Couldn't not find stream info." << endl;
break;
}
int videoIndex = -1;
unsigned int i = 0;
for (; i < pFormatCtx->nb_streams; i++)
{
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoIndex = i;
break;
}
}
if (videoIndex == -1)
{
cout << "can't find a video stream." << endl;
break;
}
AVCodecContext *pCodecCtx;
pCodecCtx = pFormatCtx->streams[videoIndex]->codec;
AVCodec *pCodec = NULL;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
cout << "codec_id:" << pCodecCtx->codec_id << endl;
if (NULL == pCodec)
{
cout << "Fail to find decoder" << endl;
break;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
{
cout << "Fail to avcodec_open2 " << endl;
break;
}
do
{
AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));
AVFrame *pFrame = av_frame_alloc();
AVFrame *pFrameYUV = av_frame_alloc();
int got_picture = 0;
struct SwsContext *img_convert_ctx;
av_dump_format(pFormatCtx, 0, filepath, 0);
uint8_t *out_buffer;
out_buffer = (uint8_t *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1));
av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1);
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
if (NULL == img_convert_ctx)
{
cout << "img_convert_ctx is wrong!" << endl;
break;
}
cout << pCodecCtx->width << "-----" << pCodecCtx->height << endl;
FILE *fp_yuv = NULL;
fopen_s(&fp_yuv, "output.yuv", "wb+");
while (av_read_frame(pFormatCtx, packet) >= 0)
{
if (packet->stream_index == videoIndex)
{
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
if (ret < 0)
{
cout << "decode error.\n";
break;
}
if (got_picture)
{
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0,
pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
// 420
//cout << "123" << endl;
#if 1
int y_size = pCodecCtx->width*pCodecCtx->height;
fwrite(pFrameYUV->data[0], 1, y_size, fp_yuv); //Y
fwrite(pFrameYUV->data[1], 1, y_size / 4, fp_yuv); //U
fwrite(pFrameYUV->data[2], 1, y_size / 4, fp_yuv); //V
#endif
}
}
av_packet_unref(packet);
}
av_frame_unref(pFrameYUV);
av_frame_unref(pFrame);
cout << "=====>" << endl;
} while (0);
avcodec_close(pCodecCtx);
} while (0);
avformat_close_input(&pFormatCtx);
getchar();
return 0;
}
#ifdef __cplusplus
}
#endif