博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
FFmpeg封装格式处理2-解复用例程
阅读量:6989 次
发布时间:2019-06-27

本文共 2963 字,大约阅读时间需要 9 分钟。

本文为作者原创,转载请注明出处:

FFmpeg封装格式处理相关内容分为如下几篇文章:

[1].
[2].
[3].
[4].

3. 解复用例程

解复用(demux),表示从一路输入中分离出多路流(视频、音频、字幕等)。

本例实现,将输入文件中的视频流和音频流分离出来,保存为单独的文件,所保存的文件是不含封装格式的裸流文件。

demuxing

3.1 源码

源码很短,用于演示demux的用法。源码中大部分函数返回值的判断均已省略。

#include 
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=%5d)\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=%5d)\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 developersInput #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检测发现这两个文件异常。

原因参考雷霄骅博士的文章:
“”
“”

本节代码仅关注最简单的解复用功能,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

你可能感兴趣的文章
.NET Core中基类可以反射子类的成员
查看>>
iOS开发之OC与swift开发混编教程,代理的相互调用,block的实现。OC调用Swift中的代理, OC调用Swift中的Block 闭包...
查看>>
神经网络优化(四) - 全连接网络实战(输入手写数字输出识别结果)
查看>>
《重构-改善既有代码的设计》 代码的坏味道(一)
查看>>
RS交叉表自动汇总后百分比列显示错误之解决方案
查看>>
iOS 关于僵尸对象和僵尸指针的那些事儿
查看>>
心悸案
查看>>
MyEclipse设置像visual studio一样的智能提示
查看>>
76. Minimum Window Substring
查看>>
linux挂载根文件系统过程
查看>>
ORA-00600: internal error code, arguments: [kcblasm_1], [103], [], [], [], [], [], []
查看>>
漫游Kafka实战篇之搭建Kafka运行环境(2)
查看>>
基础知识《九》---网络编程
查看>>
美图秀秀滤镜之对比度
查看>>
Leetcode_num3_Same Tree
查看>>
5、JavaScript进阶篇②——函数、事件、内置对象
查看>>
shell 脚本执行日志通用模块
查看>>
C#操作xml SelectNodes,SelectSingleNode总是返回NULL 与 xPath 介绍
查看>>
Unity中Mesh分解与边缘高亮加上深度检测
查看>>
Java提高篇——静态代码块、构造代码块、构造函数以及Java类初始化顺序
查看>>