(转)MP4文件两种格式AVC1和H264的区别及利用FFMPEG demux为h264码流事项
出自:http://www.mworkbox.com/wp/work/314.html
2013-05-04
MP4的视频H264封装有2种格式:h264和avc1,对于这个细节,很容易被忽略。笔者也是在改编LIVE555流媒体时,增加mp4文件类型支持时遇到了该问题。
(一)首先,从原理上了解一下这2种格式的区别:
AVC1 描述:H.264 bitstream without start codes.一般通过ffmpeg转码生成的视频,是不带起始码0×00000001的。
H264 描述:H.264 bitstream with start codes.一般对于一下HDVD等电影的压制格式,是带有起始码0×00000001的。
来源文档:http://msdn.microsoft.com/zh-cn/library/dd757808(v=vs.85).aspx
(二)其次,通过VLC播放器,可以查看到具体的格式。打开视频后,通过菜单【工具】/【编解码信息】可以查看到【编解码器】具体格式,举例如下,编解码器信息:
编码: H264 – MPEG-4 AVC (part 10) (avc1)
编码: H264 – MPEG-4 AVC (part 10) (h264)
(三)最后,分享一下ffmpeg demux MP4文件后,转换视频流为live555可直接使用的h264 ES流的经验和方法:
针对(avc1),av_read_frame后,取前四个字节为长度,把前四字节直接替换为0×00,0×00,0×00,0×01即可,但注意每个frame可以有多个NAUL:
AVPacket* packet = &pkt;
av_init_packet(packet);
av_read_frame(ctx, packet);
if(packet->stream_index == 0)
{//is video stream
const char start_code[4] = { 0, 0, 0, 1 };
if(is_avc_ || memcmp(start_code, packet->data, 4) != 0)
{//is avc1 code, have no start code of H264
int len = 0;
uint8_t *p = packet->data;
is_avc_ = True;
do
{//add start_code for each NAL, one frame may have multi NALs.
len = ntohl(*((long*)p));
memcpy(p, start_code, 4);
p += 4;
p += len;
if(p >= packet->data + packet->size)
{
break;
}
} while (1);
}
}
对于另外一种格式,(h264), 则直接对每个packet调用av_bitstream_filter_filter处理每个packet即可:
if(pkt->stream_index == 0)
{//is video stream
AVBitStreamFilterContext* bsfc = bsfc_;
int a;
while (bsfc) {
AVPacket new_pkt = *pkt;
a = av_bitstream_filter_filter(bsfc, encode_ctx_, NULL,
&new_pkt.data, &new_pkt.size,
pkt->data, pkt->size,
pkt->flags & AV_PKT_FLAG_KEY);
if(a == 0 && new_pkt.data != pkt->data && new_pkt.destruct) {
uint8_t *t = (uint8_t*)(new_pkt.size + FF_INPUT_BUFFER_PADDING_SIZE); //the new should be a subset of the old so cannot overflow
if(t) {
memcpy(t, new_pkt.data, new_pkt.size);
memset(t + new_pkt.size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
new_pkt.data = t;
a = 1;
} else
a = AVERROR(ENOMEM);
}
if (a > 0 && pkt->data != new_pkt.data) {
av_free_packet(pkt);
new_pkt.destruct = av_destruct_packet;
} else if (a < 0) {
envir() << "!!!!!!!!!!av_bitstream_filter_filter failed" << ",res=" << a << "\n";
}
*pkt = new_pkt;
bsfc = bsfc->next;
}
}
(转)MP4文件两种格式AVC1和H264的区别及利用FFMPEG demux为h264码流事项的更多相关文章
- Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式
Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式 目录 Pycharm使用技巧(转载) Python第一天 安装 shell 文件 Py ...
- apache用户认证、域名跳转、Apache访问日志(两种格式)
1.apache 设置,用户访问时 目录或文件的认证: 对目录的认证: <Directory /var/www/222> //指定认证的目录AllowOverride AuthConfig ...
- CTF-源码泄露-PHP备份文件的两种格式
参考大佬文章: https://www.cnblogs.com/yunqian2017/p/11515443.html https://blog.csdn.net/xy_sunny/article/d ...
- CASE WHEN的两种格式
CASE WHEN的两种格式 1.简单Case函数 CASE sex WHEN '1' THEN '男' WHEN '2' THEN '女' ELSE '其他' END 2.Case搜索函数 CASE ...
- Java 解析Excel(xls、xlsx两种格式)
Java 解析Excel(xls.xlsx两种格式) 一.环境 JDK 1.8 二.JAR 1.commons-collections4-4.1.jar 2.poi-3.9-20121203.jar ...
- 返回Json和XML两种格式
由于项目需要,同一接口支持根据参数不同返回XML和Json两种格式的数据,在网上看了很多大多是加后缀的方式来实现返回不同格式数据的,后来看了一篇http://www.importnew.com/276 ...
- Android 两种注册、发送广播的区别
前言:前面文章记录了Service的使用,这次来记录另一个四个组件之一的BroadcastReceiver.主要介绍两种发送和注册广播的区别. BroadcastReceiver广播接收者用于接收系统 ...
- 【Swfit】Swift与OC两种语法写单例的区别
Swift与OC两种语法写单例的区别 例如写一个NetworkTools的单例 (1)OC写单例 + (instancetype)sharedNetworkTools { static id inst ...
- C# 用Serializer.ToXml()方法转换成两种格式的XML
常见XML格式两种: 这种是属性的格式,实体的Model属性上面加上这个特性 [XmlAttribute] <AAA aa="/> 这种是标签的格式,实体的Model属性上面加上 ...
随机推荐
- dovecot--查询未读邮件个数
最近负责的邮箱系统项目中有一个这样的需求:提供一个接口给业务层,可以通过邮箱查询到该用户的未读邮件个数. 之前的方案是通过查看用户目录下.INBOX/new目录中的文件个数,但是这个方法不准确,当有用 ...
- MSTP故障处理手册
H3C核心交换机常见故障定位手册.pdf MSTP故障处理手册.pdf 目 录 1 MSTP故障处理 1.1 广播风暴故障处理 1.1.1 故障描述 1.1.2 故障处理流程 1.1.3 故障处理步骤 ...
- Pythonic版二分查找
[本文出自天外归云的博客园] 前提:升序数组,待查元素在数组中. 二分查找:就是一个递归函数c.待查元素a,当前数组中位数b,如果b=a则返回b的索引,b>a则在b左侧的子数组中调用函数c,否则 ...
- django源码解析之 BooleanField (三)
def __init__(self, *args, **kwargs): kwargs['blank'] = True if 'default' not in kwargs and not kwarg ...
- 消息队列RabbitMQ基础知识详解
一: 什么是MQ? MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序或者模块对模块的通信方法.MQ是消费-生产者模型的一个典型的代表,一端往消息队列中不断写入消息,而另 ...
- iOSCollectioView滚动到指定section的方法
CollectioView滚动到指定section的方法 项目中的需求:collectionView顶部有一个scrollView组成的标签,点击标签,让collectionView滚动到指定的行 ...
- mysql hive sql 进阶
场景: 说明.1.上面的数据是经过规整的数据,step是连续的,这个可以通过row_number实现.连续是必要的一个条件因为在计算第二个查询条件时依赖这个顺序,如果step不是数字字段可以截取然后转 ...
- git拉取远程分支
查看本地所有分支列表: git branch -a 查看远程所有分支列表: git branch -r 拉取远程分支(使用该方式会在本地新建分支x,但是不会自动切换到该本地分支x,需要手动checko ...
- 线程的几种状态转换<转>
线程在一定条件下,状态会发生变化.线程一共有以下几种状态: 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法. ...
- OpenWRT中的按键和灯的GPIO控制实现_转
本文转自:OpenWRT中的按键和灯的GPIO控制实现 基于BarrierBreaker版本,基于AR9331 AP121 Demo单板 来进行描述 1.灯 A.在mach-ap121.c中,定义了灯 ...