#include <stdio.h>
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#ifdef __cplusplus
};
#endif
int main()
{
//文件格式上下文
AVFormatContext *pFormatCtx;
int i = 0, videoindex;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame, *pFrameYUV;
unsigned char *out_buffer;
AVPacket *packet;
int y_size;
int ret, got_picture;
struct SwsContext *img_convert_ctx;
char filepath[] = "/home/mmm/视频/阳光电影www.ygdy8.com.寄生虫.BD.1080p.韩语中字.mkv";
FILE *fp_yuv = fopen("output.yuv", "wb+");
av_register_all();
avformat_network_init();
pFormatCtx = avformat_alloc_context();
if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0)
{
printf("Couldn't open input stream.\n");
return -1;
}
//读取一部分视音频数据并且获得一些相关的信息
if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
{
printf("Couldn't find stream information.\n");
return -1;
}
//查找视频编码索引
videoindex = -1;
for (i = 0; i < pFormatCtx->nb_streams; i++)
{
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoindex = i;
break;
}
}
if (videoindex == -1)
{
printf("Didn't find a video stream.\n");
return -1;
}
//编解码上下文
pCodecCtx = pFormatCtx->streams[videoindex]->codec;
//查找解码器
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == nullptr)
{
printf("Codec not found.\n");
return -1;
}
//打开解码器
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
{
printf("Could not open codec.\n");
return -1;
}
//申请AVFrame,用于原始视频
pFrame = av_frame_alloc();
//申请AVFrame,用于yuv视频
pFrameYUV = av_frame_alloc();
//分配内存,用于图像格式转换
out_buffer = (unsigned char *)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);
packet = (AVPacket *)av_malloc(sizeof(AVPacket));
//Output Info-----------------------------
printf("--------------- File Information ----------------\n");
//手工调试函数,输出tbn、tbc、tbr、PAR、DAR的含义
av_dump_format(pFormatCtx, 0, filepath, 0);
printf("-------------------------------------------------\n");
//申请转换上下文
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);
//读取数据
while (av_read_frame(pFormatCtx, packet) >= 0)
{
if (packet->stream_index == videoindex)
{
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
if (ret < 0)
{
printf("Decode Error.\n");
return -1;
}
if (got_picture >= 1)
{
//成功解码一帧
sws_scale(img_convert_ctx, (const unsigned char* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
pFrameYUV->data, pFrameYUV->linesize);//转换图像格式
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
printf("Succeed to decode 1 frame!\n");
}
else
{
//未解码到一帧,可能时结尾B帧或延迟帧,在后面做flush decoder处理
}
}
av_free_packet(packet);
}
//flush decoder
//FIX: Flush Frames remained in Codec
while (true)
{
if (!(pCodec->capabilities & CODEC_CAP_DELAY))
return 0;
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
if (ret < 0)
{
break;
}
if (!got_picture)
{
break;
}
sws_scale(img_convert_ctx, (const unsigned char* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
pFrameYUV->data, pFrameYUV->linesize);
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
printf("Flush Decoder: Succeed to decode 1 frame!\n");
}
sws_freeContext(img_convert_ctx);
av_frame_free(&pFrameYUV);
av_frame_free(&pFrame);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
fclose(fp_yuv);
return 0;
}
build-qt_ffmpeg-Desktop_Qt_5_12_6_GCC_64bit-Debug/qt_ffmpeg 被光抓走的人.mp4...
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '被光抓走的人.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.29.100
Duration: 02:11:00.07, start: 0.000000, bitrate: 1603 kb/s Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1920x1040, 1472 kb/s, 24 fps, 24 tbr, 90k tbn, 48 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 124 kb/s (default)
Metadata:
handler_name : SoundHandler
--------------- File Information ----------------
-------------------------------------------------
Succeed to decode 1 frame!
Succeed to decode 1 frame!
Succeed to decode 1 frame!
Succeed to decode 1 frame!
Succeed to decode 1 frame!
Succeed to decode 1 frame!
Succeed to decode 1 frame!
Succeed to decode 1 frame!
Desktop_Qt_5_12_6_GCC_64bit-Debug/qt_ffmpeg 被光抓走的人.mp4...
Input #0, matroska,webm, from '/home/mmm/视频/Mile.22.2018.1080p.WEB-DL.DD5.1.H264-FGT.mkv':
Metadata:
title : Mile.22.2018.1080p.WEB-DL.DD5.1.H264-FGT
encoder : libebml v1.3.6 + libmatroska v1.4.9
creation_time : 2018-10-30T05:12:55.000000Z
Duration: 01:34:39.89, start: 0.000000, bitrate: 4921 kb/s
Chapter #0:0: start 0.000000, end 976.643000
Metadata:
title : Chapter 01
Chapter #0:1: start 976.643000, end 1516.057000 Metadata:
title : Chapter 02
Chapter #0:2: start 1516.057000, end 2193.692000
Metadata:
title : Chapter 03
Chapter #0:3: start 2193.692000, end 2787.869000
Metadata:
title : Chapter 04
Chapter #0:4: start 2787.869000, end 3554.135000
Metadata:
title : Chapter 05
Chapter #0:5: start 3554.135000, end 4059.890000
Metadata:
title : Chapter 06
Chapter #0:6: start 4059.890000, end 4702.908000
Metadata:
title : Chapter 07
Chapter #0:7: start 4702.908000, end 5234.814000
Metadata:
title : Chapter 08
Chapter #0:8: start 5234.814000, end 5679.889000
Metadata:
title : Chapter 09
Stream #0:0(eng): Video: h264 (High), yuv420p(tv, bt709, progressive), 1920x800 [SAR 1:1 DAR 12:5], 23.98 fps, 23.98 tbr, 1k tbn, 47.95 tbc (default)
Metadata:
title : Mile.22.2018.1080p.WEB-DL.DD5.1.H264-FGT
BPS-eng : 4535970
DURATION-eng : 01:34:39.847000000
NUMBER_OF_FRAMES-eng: 136180
NUMBER_OF_BYTES-eng: 3220452265
_STATISTICS_WRITING_APP-eng: mkvmerge v28.1.0 ('Morning Child') 64-bit
_STATISTICS_WRITING_DATE_UTC-eng: 2018-10-30 05:12:55
_STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Stream #0:1(eng): Audio: ac3, 48000 Hz, 5.1(side), fltp, 384 kb/s (default)
Metadata:
title : Mile.22.2018.1080p.WEB-DL.DD5.1.H264-FGT
BPS-eng : 384000
DURATION-eng : 01:34:39.872000000
NUMBER_OF_FRAMES-eng: 177496
NUMBER_OF_BYTES-eng: 272633856
_STATISTICS_WRITING_APP-eng: mkvmerge v28.1.0 ('Morning Child') 64-bit
_STATISTICS_WRITING_DATE_UTC-eng: 2018-10-30 05:12:55
_STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Stream #0:2: Video: mjpeg, yuvj444p(pc, bt470bg/unknown/unknown), 120x176, 90k tbr, 90k tbn, 90k tbc
Metadata:
filename : small_cover.jpg
mimetype : image/jpeg
Stream #0:3: Video: mjpeg, yuvj444p(pc, bt470bg/unknown/unknown), 213x120, 90k tbr, 90k tbn, 90k tbc
Metadata:
filename : small_cover_land.jpg
mimetype : image/jpeg
Stream #0:4: Video: mjpeg, yuvj444p(pc, bt470bg/unknown/unknown), 600x882, 90k tbr, 90k tbn, 90k tbc
Metadata:
filename : cover.jpg
mimetype : image/jpeg
Stream #0:5: Video: mjpeg, yuvj444p(pc, bt470bg/unknown/unknown), 1067x600, 90k tbr, 90k tbn, 90k tbc
Metadata:
filename : cover_land.jpg
mimetype : image/jpeg