FFMPEG 封装格式处理相关内容分为如下几篇文章:
[1]. FFMPEG 封装格式处理 - 简介
[2]. FFMPEG 封装格式处理 - 解复用例程
[3]. FFMPEG 封装格式处理 - 复用例程
[4]. FFMPEG 封装格式处理 - 转封装例程
3. 解复用例程
解复用 (demux), 表示从一路输入中分离出多路流 (视频, 音频, 字幕等).
本例实现, 将输入文件中的视频流和音频流分离出来, 保存为单独的文件, 所保存的文件是不含封装格式的裸流文件.
3.1 源码
源码很短, 用于演示 demux 的用法. 源码中大部分函数返回值的判断均已省略.
- #include <libavformat/avformat.h>
- int main (int argc, char **argv)
- {
- if (argc != 4)
- {
- fprintf(stderr, "usage: %s test.ts test.h264 test.aac\n", argv[0]);
- exit(1);
- }
- const char *input_fname = argv[1];
- const char *output_v_fname = argv[2];
- const char *output_a_fname = argv[3];
- FILE *video_dst_file = fopen(output_v_fname, "wb");
- FILE *audio_dst_file = fopen(output_a_fname, "wb");
- AVFormatContext *fmt_ctx = NULL;
- int ret = avformat_open_input(&fmt_ctx, input_fname, NULL, NULL);
- ret = avformat_find_stream_info(fmt_ctx, NULL);
- int video_idx = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
- int audio_idx = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
- if (video_idx <0 || audio_idx < 0)
- {
- printf("find stream failed: %d %d\n", video_idx, audio_idx);
- return -1;
- }
- av_dump_format(fmt_ctx, 0, input_fname, 0);
- AVPacket pkt;
- av_init_packet(&pkt);
- pkt.data = NULL;
- pkt.size = 0;
- while (av_read_frame(fmt_ctx, &pkt)>= 0)
- {
- if (pkt.stream_index == video_idx)
- {
- ret = fwrite(pkt.data, 1, pkt.size, video_dst_file);
- //printf("vp %x %3"PRId64"%3"PRId64"(size=])\n", pkt.pos, pkt.pts, pkt.dts, ret);
- }
- else if (pkt.stream_index == audio_idx) {
- ret = fwrite(pkt.data, 1, pkt.size, audio_dst_file);
- //printf("ap %x %3"PRId64"%3"PRId64"(size=])\n", pkt.pos, pkt.pts, pkt.dts, ret);
- }
- av_packet_unref(&pkt);
- }
- printf("Demuxing succeeded.\n");
- end:
- avformat_close_input(&fmt_ctx);
- fclose(video_dst_file);
- fclose(audio_dst_file);
- return 0;
- }
3.2 编译
源文件为 demuxing.c, 在 SHELL 中执行如下编译命令:
gcc -o demuxing demuxing.c -lavformat -lavcodec -g
生成可执行文件 demuxing
3.3 验证
测试文件下载:
先看一下测试用资源文件的格式:
- think@opensuse> ffprobe tnshih.flv
- ffprobe version 4.1 Copyright (c) 2007-2018 the FFMPEG developers
- Input #0, flv, from 'tnshih.flv':
- Metadata:
- encoder : Lavf58.20.100
- Duration: 00:00:37.20, start: 0.000000, bitrate: 1182 kb/s
- Stream #0:0: Video: h264 (High), yuv420p(progressive), 800x450, 25 fps, 25 tbr, 1k tbn, 50 tbc
- Stream #0:1: Audio: aac (LC), 44100 Hz, stereo, fltp
可以看到视频文件'tnshih.flv'封装格式为 flv, 包含一路 h264 编码的视频流和一路 aac 编码的音频流.
运行如下命令进行测试:
./demuxing tnshih.flv tnshih_flv.h264 tnshih_flv.aac
使用 ffplay 播放视频文件 thshih_flv.h264 及音频文件 tnshih_flv.aac, 均无法播放. 使用 ffprobe 检测发现这两个文件异常.
原因参考雷霄骅博士的文章:
- "使用 FFMPEG 类库分离出多媒体文件中的 H.264 码流"
- "最简单的基于 FFmpeg 的封装格式处理: 视音频分离器简化版"
本节代码仅关注最简单的解复用功能, FLV,MP4 等特定容器中分离出来的 h264 视频流和 aac 音频流无法播放.
那换一种封装格式测一下, 利用 FFMPEG 转码命令将 flv 封装格式转换为 mpegts 封装格式:
测试:
FFMPEG -i tnshih.flv -map 0 -c copy tnshih.ts
运行如下命令进行测试:
./demuxing tnshih.ts tnshih_ts.h264 tnshih_ts.aac
使用 ffplay 播放视频文件 thshih_ts.h264 及音频文件 tnshih_ts.aac, 播放正常. 使用 ffprobe 检测发现这两个文件正常.
来源: https://www.cnblogs.com/leisure_chn/p/10506642.html