关键步骤
int rgbsize = avpicture_get_size(PIX_FMT_RGB24, pVCodecCtx->width, pVCodecCtx->height);avpicture_alloc((AVPicture *)&rgbFrame, PIX_FMT_RGB24, pVCodecCtx->width, pVCodecCtx->height);SwsContext *img_convert_ctx = sws_getContext(pVCodecCtx->width, pVCodecCtx->height, AV_PIX_FMT_YUV420P, pVCodecCtx->width, pVCodecCtx->height, PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL);sws_scale(img_convert_ctx, (uint8_t const* const *)Frame.data, Frame.linesize, 0, pVCodecCtx->height, rgbFrame.data, rgbFrame.linesize);
avpicture_get_size 算出某格式和分辨率下一帧图像的数据大小
avpicture_fill 将自己分配的内存绑定到AVFrame帧的data数据区
avpicture_alloc 为AVFrame帧的data分配内存,不用自己分配
sws_getContext 创建从一种格式到另一种格式的转换上下文
sws_scale 转换
以上的每一个函数都没有对AFrame的linesize进行有效处理,使用data的内存大小要用avpicture_get_size算出
Code
#define _CRT_SECURE_NO_WARNINGS
#include extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavdevice/avdevice.h"
}#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avdevice.lib")
#pragma comment(lib, "avfilter.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "postproc.lib")
#pragma comment(lib, "swresample.lib")
#pragma comment(lib, "swscale.lib")#define INPUT "in.flv"
#define OUTVIDEO "video.yuv"
#define OUTAUDIO "audio.pcm"
#define OUTRGB "video.rgb"int main()
{int res &#61; 0;int videoStream &#61; -1;int audioStream &#61; -1;char errBuf[BUFSIZ] &#61; { 0 };FILE* fp_video &#61; fopen(OUTVIDEO, "wb&#43;");FILE* fp_audio &#61; fopen(OUTAUDIO, "wb&#43;");FILE* fp_rgb &#61; fopen(OUTRGB, "wb&#43;");av_register_all();printf("FFmpeg&#39;s version is: %d\n", avcodec_version());AVFormatContext* pFormatCtx &#61; NULL;if ((res &#61; avformat_open_input(&pFormatCtx, INPUT, NULL, NULL)) <0){av_strerror(res, errBuf, sizeof(errBuf));printf("%s\n", errBuf);return -1;}avformat_find_stream_info(pFormatCtx, NULL);av_dump_format(pFormatCtx, 0, NULL, 0); for (int i &#61; 0; i nb_streams; &#43;&#43;i){if (pFormatCtx->streams[i]->codec->codec_type &#61;&#61; AVMEDIA_TYPE_VIDEO)videoStream &#61; i;else if (pFormatCtx->streams[i]->codec->codec_type &#61;&#61; AVMEDIA_TYPE_AUDIO)audioStream &#61; i;}if (videoStream &#61;&#61; -1){printf("Didn&#39;t find a video stream.\n");return -1;}if (audioStream &#61;&#61; -1){printf("Didn&#39;t find a audio stream.\n");return -1;}AVCodecContext* pVCodecCtx &#61; pFormatCtx->streams[videoStream]->codec;AVCodec* pVCodec &#61; avcodec_find_decoder(pVCodecCtx->codec_id);if (pVCodec &#61;&#61; NULL){printf("Video Codec not found.\n");return -1;}AVCodecContext* pACodecCtx &#61; pFormatCtx->streams[audioStream]->codec;AVCodec* pACodec &#61; avcodec_find_decoder(pACodecCtx->codec_id);if (pACodec &#61;&#61; NULL){printf("Audio Codec not found.\n");return -1;}if (avcodec_open2(pVCodecCtx, pVCodec, NULL) <0){printf("Could not open Video codec.\n");return -1;}if (avcodec_open2(pACodecCtx, pACodec, NULL) <0){printf("Could not open Audio codec.\n");return -1;}AVFrame Frame &#61; { 0 };AVFrame rgbFrame;AVPacket packet;int got_picture;int rgbsize &#61; avpicture_get_size(PIX_FMT_RGB24, pVCodecCtx->width, pVCodecCtx->height);avpicture_alloc((AVPicture *)&rgbFrame, PIX_FMT_RGB24, pVCodecCtx->width, pVCodecCtx->height);SwsContext *img_convert_ctx &#61; sws_getContext(pVCodecCtx->width, pVCodecCtx->height, AV_PIX_FMT_YUV420P, pVCodecCtx->width, pVCodecCtx->height, PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL);while (1){if (av_read_frame(pFormatCtx, &packet) <0){break; }if (packet.stream_index &#61;&#61; videoStream){if (avcodec_decode_video2(pVCodecCtx, &Frame, &got_picture, &packet) <0){printf("decode Video error.\n");return -1;}if (got_picture){if (Frame.format &#61;&#61; PIX_FMT_YUV420P){fwrite(Frame.data[0], Frame.linesize[0] * Frame.height, 1, fp_video);fwrite(Frame.data[1], Frame.linesize[1] * Frame.height / 2, 1, fp_video);fwrite(Frame.data[2], Frame.linesize[2] * Frame.height / 2, 1, fp_video);sws_scale(img_convert_ctx, (uint8_t const* const *)Frame.data, Frame.linesize, 0, pVCodecCtx->height, rgbFrame.data, rgbFrame.linesize);fwrite(rgbFrame.data[0], rgbsize, 1, fp_rgb);}}}else if (packet.stream_index &#61;&#61; audioStream){if (avcodec_decode_audio4(pACodecCtx, &Frame, &got_picture, &packet) <0){printf("decode Audio error.\n");return -1;}if (got_picture){if (Frame.format &#61;&#61; AV_SAMPLE_FMT_S16P){for (int i &#61; 0; i 0]; i &#43;&#61; 2){for (int j &#61; 0; j 2, 1, fp_audio);}}else if (Frame.format &#61;&#61; AV_SAMPLE_FMT_FLTP){for (int i &#61; 0; i 0]; i &#43;&#61; 4){for (int j &#61; 0; j 4, 1, fp_audio);}}}}av_free_packet(&packet);}fclose(fp_video);fclose(fp_audio);fclose(fp_rgb);avpicture_free((AVPicture*)&rgbFrame);avcodec_close(pVCodecCtx);avcodec_close(pACodecCtx);avformat_close_input(&pFormatCtx);return 0;
}
Github
https://github.com/gongluck/FFmpegTest.git