FFmpeg封装格式处理2-解复用例程
时间:2022-06-19
本文章向大家介绍FFmpeg封装格式处理2-解复用例程,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
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.aacn", 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 %dn", 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 验证
测试文件下载:tnshih.flv
先看一下测试用资源文件的格式:
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检测发现这两个文件正常。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- php+jQuery ajax实现的实时刷新显示数据功能示例
- yii2.0框架使用 beforeAction 防非法登陆的方法分析
- PHP使用 Imagick 扩展实现图片合成,圆角处理功能示例
- php项目中类的自动加载实例讲解
- Yii框架参数配置文件params用法实例分析
- 使用Kotlin实现文字渐变TextView的代码
- thinkPHP5框架路由常用知识点汇总
- PHP实现一个限制实例化次数的类示例
- AndroidStudio中重载方法@Override的使用详解
- mysqli扩展无法在PHP7下升级问题的解决
- PHP通过文件保存和更新信息的方法分析
- PHP中将一个字符串部分字符用星号*替代隐藏的实现代码
- PHP创建XML的方法示例【基于DOMDocument类及SimpleXMLElement类】
- android之json数据过长打印不全问题的解决
- PHP实现时间日期友好显示实现代码