索引地址:系列教程索引地址
上一篇:FFmpeg5开发入门教程04:输出视频信息
FFmpeg使用较多的就是解码视频了,我们先进行正常的解码流程。
解码流程图为:

测试代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
| #include <stdio.h> #include <stdlib.h> #include "libavcodec/avcodec.h" #include "libavfilter/avfilter.h" #include "libavformat/avformat.h" #include "libavutil/avutil.h" #include "libavutil/ffversion.h" #include "libswresample/swresample.h" #include "libswscale/swscale.h" #include "libpostproc/postprocess.h"
int main() { char filePath[] = "beat.mp4"; int videoStreamIndex = -1; int ret=0;
AVFormatContext *fmtCtx=NULL; AVPacket *pkt =NULL; AVCodecContext *codecCtx=NULL; AVCodecParameters *avCodecPara=NULL; const AVCodec *codec=NULL;
do{ fmtCtx = avformat_alloc_context(); if ((ret=avformat_open_input(&fmtCtx, filePath, NULL, NULL)) != 0) { printf("cannot open video file\n"); break; }
if ((ret=avformat_find_stream_info(fmtCtx, NULL)) < 0) { printf("cannot retrive video info\n"); break; }
for (unsigned int i = 0; i < fmtCtx->nb_streams; i++) { if (fmtCtx->streams[ i ]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { videoStreamIndex = i; break; } }
if (videoStreamIndex == -1) { printf("cannot find video stream\n"); break; }
av_dump_format(fmtCtx, 0, filePath, 0);
avCodecPara = fmtCtx->streams[ videoStreamIndex ]->codecpar; codec = avcodec_find_decoder(avCodecPara->codec_id); if (codec == NULL) { printf("cannot find decoder\n"); break; } codecCtx = avcodec_alloc_context3(codec); avcodec_parameters_to_context(codecCtx, avCodecPara); if (codecCtx == NULL) { printf("Cannot alloc context."); break; }
if ((ret=avcodec_open2(codecCtx, codec, NULL)) < 0) { printf("cannot open decoder\n"); break; }
int i = 0; pkt = av_packet_alloc(); av_new_packet(pkt, codecCtx->width * codecCtx->height);
while (av_read_frame(fmtCtx, pkt) >= 0) { if(pkt->stream_index==videoStreamIndex){ i++; } av_packet_unref(pkt); } printf("There are %d frames int total.\n", i); }while(0); av_packet_free(&pkt); avcodec_close(codecCtx); avformat_close_input(&fmtCtx); avformat_free_context(fmtCtx);
return ret; }
|
编译执行,输出为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| Input Metadata: major_brand : isom minor_version : 1 compatible_brands: isomavc1 creation_time : 2015-06-06T14:14:34.000000Z Duration: 00:06:32.89, start: 0.000000, bitrate: 1923 kb/s Stream Metadata: creation_time : 2015-06-06T14:14:34.000000Z Stream Metadata: creation_time : 2015-06-06T14:14:29.000000Z There are 9420 frames int total.%
|
根据输出,在视频流里面统计每一帧,共计9420帧。
视频共计6分32秒,帧率为24帧/秒,那么视频的视频帧数为:(6 * 60 + 32.89 ) * 23.98 = 9421.5022 。考虑到执行误差,两者非常接近,没有太大的错误。
代码开发要模块化,我们将部分流程合并,按照谷歌编码规范,一个函数最多40行,保持简洁。
但是开发才刚开始,并没有太多代码。
既然流程没有错,那么我们进行解码视频数据看看。
GitHub项目地址(源代码):ffmpeg_beginner中的5.video_decode_flow
下一篇我们将解码视频前5帧并保存为图片。
下一篇:FFmpeg5开发入门教程06:保存视频帧