FFmpeg封装格式处理 (2)

再看一下mpegts封装格式定义,AVInputFormat用于定义输入封装格式,AVOutputFormat用于定义输出封装格式。mpegts输入封装格式中并未指定文件扩展名,而mpegts输出封装格式中则指定了文件扩展名为"ts,m2t,m2ts,mts"。

AVInputFormat ff_mpegts_demuxer = { .name = "mpegts", .long_name = NULL_IF_CONFIG_SMALL("MPEG-TS (MPEG-2 Transport Stream)"), .priv_data_size = sizeof(MpegTSContext), .read_probe = mpegts_probe, .read_header = mpegts_read_header, .read_packet = mpegts_read_packet, .read_close = mpegts_read_close, .read_timestamp = mpegts_get_dts, .flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT, .priv_class = &mpegts_class, }; AVOutputFormat ff_mpegts_muxer = { .name = "mpegts", .long_name = NULL_IF_CONFIG_SMALL("MPEG-TS (MPEG-2 Transport Stream)"), .mime_type = "video/MP2T", .extensions = "ts,m2t,m2ts,mts", .priv_data_size = sizeof(MpegTSWrite), .audio_codec = AV_CODEC_ID_MP2, .video_codec = AV_CODEC_ID_MPEG2VIDEO, .init = mpegts_init, .write_packet = mpegts_write_packet, .write_trailer = mpegts_write_end, .deinit = mpegts_deinit, .check_bitstream = mpegts_check_bitstream, .flags = AVFMT_ALLOW_FLUSH | AVFMT_VARIABLE_FPS | AVFMT_NODIMENSIONS, .priv_class = &mpegts_muxer_class, }; 1.2.4 文件扩展名与封装格式

在FFmpeg命令行中,输入文件扩展名是错的也没有关系,因为FFmpeg会读取一小段文件来探测出真正的封装格式;但是如果未显式的指定输出封装格式,就只能通过输出文件扩展名来确定封装格式,就必须确保扩展名是正确的。

做几个实验,来研究一下FFmpeg中文件扩展名与封装格式的关系:

测试文件下载:tnhaoxc.flv

文件信息如下:

think@opensuse> ffprobe tnhaoxc.flv ffprobe version 4.1 Copyright (c) 2007-2018 the FFmpeg developers Input #0, flv, from 'tnhaoxc.flv': Metadata: encoder : Lavf58.20.100 Duration: 00:02:13.68, start: 0.000000, bitrate: 838 kb/s Stream #0:0: Video: h264 (High), yuv420p(progressive), 784x480, 25 fps, 25 tbr, 1k tbn, 50 tbc Stream #0:1: Audio: aac (LC), 44100 Hz, stereo, fltp

实验1:将flv封装格式转换为mpegts封装格式
使用转封装指令将flv封装格式转换为mpegts封装格式,在SHELL中依次运行如下两条命令:

ffmpeg -i tnhaoxc.flv -map 0 -c copy tnhaoxc.ts ffmpeg -i tnhaoxc.flv -map 0 -c copy tnhaoxc.m2t

生成tnhaoxc.ts和tnhaoxc.m2t文件,比较一下两文件有无不同:

diff tnhaoxc.ts tnhaoxc.m2t

命令行无输出,表示两文件内容无任何不同。即两文件仅是扩展名不同,封装格式都是mpegts,文件内容并无任何不同。

实验2:为输出文件指定错误的扩展名
我们指定一个错误的扩展名再试一下(误把封装格式名称当作文件扩展名):

ffmpeg -i tnhaoxc.flv -map 0 -c copy tnhaoxc.mpegts

命令行输出如下错误信息:

ffmpeg version 4.1 Copyright (c) 2000-2018 the FFmpeg developers Input #0, flv, from 'tnhaoxc.flv': Metadata: encoder : Lavf58.20.100 Duration: 00:02:13.68, start: 0.000000, bitrate: 838 kb/s Stream #0:0: Video: h264 (High), yuv420p(progressive), 784x480, 25 fps, 25 tbr, 1k tbn, 50 tbc Stream #0:1: Audio: aac (LC), 44100 Hz, stereo, fltp [NULL @ 0x1d62e80] Unable to find a suitable output format for 'tnhaoxc.mpegts' tnhaoxc.mpegts: Invalid argument

提示无法确定输出格式。FFmpeg无法根据此扩展名确定输出文件的封装格式。

实验3:为输出文件指定错误的扩展名但显示指定封装格式
我们通过-f mpegts选项显式指定封装格式为mpegts,命令执行成功:

ffmpeg -i tnhaoxc.flv -map 0 -c copy -f mpegts tnhaoxc.mpegts

看一下文件内容是否正确:

diff tnhaoxc.mpegts tnhaoxc.ts

发现tnhaoxc.mpegts和tnhaoxc.ts文件内容完全一样,虽然tnhaoxc.mpegts有错误的文件扩展名,仍然得到了我们期望的封装格式。

不知道什么命令可以查到封装格式对应的扩展名。可以在FFmpeg工程源码中搜索封装格式名称,如搜索“mpegts”,可以看到其扩展名为“ts,m2t,m2ts,mts”。

2. API介绍

最主要的API有如下几个。FFmpeg中将编码帧及未编码帧均称作frame,本文为方便,将编码帧称作packet,未编码帧称作frame。

2.1 avformat_open_input() /** * Open an input stream and read the header. The codecs are not opened. * The stream must be closed with avformat_close_input(). * * @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context). * May be a pointer to NULL, in which case an AVFormatContext is allocated by this * function and written into ps. * Note that a user-supplied AVFormatContext will be freed on failure. * @param url URL of the stream to open. * @param fmt If non-NULL, this parameter forces a specific input format. * Otherwise the format is autodetected. * @param options A dictionary filled with AVFormatContext and demuxer-private options. * On return this parameter will be destroyed and replaced with a dict containing * options that were not found. May be NULL. * * @return 0 on success, a negative AVERROR on failure. * * @note If you want to use custom IO, preallocate the format context and set its pb field. */ int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyjjjg.html