hevc_mp4toannexb_bsf.c/h264_mp4toannexb_bsf.c
本文主要分析mp4封装的h265/h264,copy转hls,红色为自己添加的注释。
动态添加此filter
for (i = 0; i < nb_output_streams; i++) {
ost = output_streams[i];
if(ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ost->st->codec->codec_id == AV_CODEC_ID_H264)
{
AVBitStreamFilterContext * avFilter = av_bitstream_filter_init("h264_mp4toannexb");
ost->bitstream_filters = avFilter;
}else if(ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ost->st->codec->codec_id == AV_CODEC_ID_HEVC)
{
AVBitStreamFilterContext * avFilter = av_bitstream_filter_init("hevc_mp4toannexb");
ost->bitstream_filters = avFilter;
}
}
hevc->hls
如果不加 -bsf:v hevc_mp4toannex,就会报如下错误:
原因如下:
check_hevc_startcode会发现没有00000001字段。
相关代码有:hevc_mp4toannexb_bsf.c
前缀(vps,sps,pps)例子如下:
typedef structHEVCBSFContext {
uint8_t length_size;
int extradata_parsed;
}HEVCBSFContext;
static inthevc_extradata_to_annexb(AVBSFContext *ctx)
{
GetByteContext gb;
int length_size, num_arrays, i, j;
int ret = 0;
uint8_t *new_extradata = NULL;
size_t new_extradata_size = 0;
bytestream2_init(&gb,ctx->par_in->extradata, ctx->par_in->extradata_size);
bytestream2_skip(&gb, 21);
//跳过21个字节
length_size =(bytestream2_get_byte(&gb) & 3) + 1;
//第22个字节(0x03)后两位加上1。
num_arrays = bytestream2_get_byte(&gb);
//第23个字节(0x03)
for (i = 0; i < num_arrays; i++) {
int type =bytestream2_get_byte(&gb) & 0x3f;
//对应0x20,0x21,0x22
int cnt = bytestream2_get_be16(&gb);
//对应0x00 0x01, 0x00 0x01, 0x00 0x01,
if (!(type == NAL_VPS || type ==NAL_SPS || type == NAL_PPS ||
type == NAL_SEI_PREFIX || type ==NAL_SEI_SUFFIX || type == 0)) {
av_log(ctx, AV_LOG_ERROR,"Invalid NAL unit type in extradata: %d\n",
type);
ret = AVERROR_INVALIDDATA;
goto fail;
}
for (j = 0; j < cnt; j++) {
int nalu_len =bytestream2_get_be16(&gb);
//对应0x00 0x17(0x40~0x59),0x00 0x27(0x42~0x40),0x00 0x07(0x44~0x20)
if (4 +AV_INPUT_BUFFER_PADDING_SIZE + nalu_len > SIZE_MAX - new_extradata_size) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
ret =av_reallocp(&new_extradata, new_extradata_size + nalu_len + 4 +AV_INPUT_BUFFER_PADDING_SIZE);
if (ret < 0)
goto fail;
AV_WB32(new_extradata +new_extradata_size, 1);
// addthe startcode,也就是00 00 00 01
bytestream2_get_buffer(&gb,new_extradata + new_extradata_size + 4, nalu_len);
new_extradata_size += 4 + nalu_len;
memset(new_extradata + new_extradata_size,0, AV_INPUT_BUFFER_PADDING_SIZE);
}
}
av_freep(&ctx->par_out->extradata);
ctx->par_out->extradata = new_extradata;
ctx->par_out->extradata_size =new_extradata_size;
//得到新的字符串,长度。
if (!new_extradata_size)
av_log(ctx, AV_LOG_WARNING, "Noparameter sets in the extradata\n");
return length_size;
fail:
av_freep(&new_extradata);
return ret;
}
static inthevc_mp4toannexb_init(AVBSFContext *ctx)
{
...
}
//对于每一帧,都会进入hevc_mp4toannexb_filter函数,如下:
static inthevc_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)
{
HEVCBSFContext *s = ctx->priv_data;
AVPacket *in;
GetByteContext gb;
int got_irap = 0;
int i, ret = 0;
ret = ff_bsf_get_packet(ctx, &in);
if (ret < 0)
return ret;
if (!s->extradata_parsed) {
av_packet_move_ref(out, in);
av_packet_free(&in);
return 0;
}
bytestream2_init(&gb, in->data,in->size);
while (bytestream2_get_bytes_left(&gb)){
uint32_t nalu_size = 0;
int nalu_type;
int is_irap, add_extradata, extra_size,prev_size;
for (i = 0; i < s->length_size;i++)
nalu_size = (nalu_size << 8)| bytestream2_get_byte(&gb);
//前4位表示数据大小。
nalu_type =(bytestream2_peek_byte(&gb) >> 1) & 0x3f;
//对应0x26
/* prepend extradata to IRAP frames */
is_irap = nalu_type >= 16 &&nalu_type <= 23;
//帧类型在16到23之间,都会被强插入vps等前缀。
add_extradata = is_irap &&!got_irap;
extra_size = add_extradata *ctx->par_out->extradata_size;
got_irap |= is_irap;
if (SIZE_MAX - nalu_size < 4 ||
SIZE_MAX - 4 - nalu_size <extra_size) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
prev_size = out->size;
ret = av_grow_packet(out, 4 + nalu_size+ extra_size);
if (ret < 0)
goto fail;
if (add_extradata)
memcpy(out->data + prev_size,ctx->par_out->extradata, extra_size);
//插入vps等前缀。
AV_WB32(out->data + prev_size +extra_size, 1);
// add thestartcode,也就是00 00 00 01
bytestream2_get_buffer(&gb,out->data + prev_size + 4 + extra_size, nalu_size);
//拷贝帧数据。
}
ret = av_packet_copy_props(out, in);
if (ret < 0)
goto fail;
fail:
if (ret < 0)
av_packet_unref(out);
av_packet_free(&in);
return ret;
}
...
h264->hls
解析mp4的块,得到sps,pps总数据,在h264_mp4toannexb_filter中去除头,得到sps,pps(只做一次),然后在每个关键帧前插sps,pps数据。
hevc_mp4toannexb_bsf.c/h264_mp4toannexb_bsf.c相关推荐
- WebRTC-集成qsv硬解码实现
1.Window下QSV硬解码配置 在libavcodec/codec_list.c下添加 &ff_h264_qsv_decoder, 在ffmpeg_generate.gni下加入 &quo ...
- FFmpeg源代码简单分析:configure
===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...
- H264 帧、pps 、sps
H264帧 对于H.264而言,每帧的界定符为00 00 00 01 或者00 00 01. 例如下面是一个H264的文件片段 00 00 00 01 67 42 C0 28 DA 01 E0 08 ...
- FFmpeg封装格式处理:视音频复用器(muxer)不同格式中数据有无bsf的差异-- Filter bitstream_filter实现格式转换:h264_mp4toannexb
视音频复用器:从输入文件中挑出需要的视频/音频流,再合并放到一个文件中 不同封装格式中的数据存放方式不同,其差异需要一个av_bitstream_filter_filter(AVBitStreamFi ...
- Android多媒体开发(2)————使用Android NKD编译原版FFmpeg
/******************************************************************************************** * auth ...
- Win7下利用MinGW和Android NDK编译ffmpeg0.10(neon优化)
不久之前萌生了移植ffmpeg到android平台上的冲动,然后就开始搞.网上搜了个遍,着实费了不少工夫.因此把成果列出来供同道中人参考. 本文主要参考了Scott Wong 兄的在 Windows ...
- win 7下ffmpeg平台和Android联合编译ndk rc7和ffmpeg harmony(最后还是改为r5)
恩..前面弄好了ndk和cgwin之后开始进行FFmepeg的搭建..前面的图都没了啊啊 参考http://www.cnblogs.com/scottwong/archive/2011/06/26/2 ...
- 阿里云服务器编译ffmpeg
1.在usr文件夹中创建jason文件夹 cd /usr :进入usr文件夹 mkdir jason: 创建jason文件夹 2.上传ffmpeg文件到阿里云 3.解压ffmpeg压缩包 4.编译.s ...
- 应用角度理解H264码流
应用角度理解H264码流 前言 1.NAL 2.SPS.PPS 2.1 SPS 2.2 PPS 3.Slice&MB 3.1.Slice 3.2.MB 4.RTP负载 5.AUD 6.文献 前 ...
最新文章
- 今天终于搞懂了:为什么 Java 的 main 方法必须是 public static void?
- 数据结构之【数组和广义表】复习题
- Python列表List
- 踩内存是什么意思啊_面试|搬了这么久的砖,居然还不知道什么“踩内存”
- Java中如何引用文档对象模型_在JAVA中使用文档对象模型DOM经验小结
- 前端学习(3059):vue+element今日头条管理-优化文章状态
- LeetCode算法入门- Remove Duplicates from Sorted Array -day21
- mongoTemplate.aggregate() 聚合查询,关联查询
- linux音频声卡 pulseaudio服务
- 毕业设计——如何画系统功能结构图?
- 在修改redis配置文件的情况下启动redis需指定配置文件
- Django3.0入门教程【四】:Django常用命令
- 1079:计算分数加减表达式的值
- 英语的计算机求职回信,2020年计算机英文求职信范文模板
- Git, Gitlab使用文档
- 南京信息工程大学计算机与科学专业,2019南京信息工程大学专业排名
- 十五、圣礼是蒙恩的凭藉
- 基于协同过滤算法的电影推荐系统设计(二) - ALS算法详解
- 计算机三级数据库技术 第14章 数据仓库与数据挖掘
- javaScript和html的区别与联系
热门文章
- 当一个查询语句同时出现了where,group by,having,order by的时候,执行顺序和编写顺序
- 预失真算法matlab实现,2013-全国研究生数学建模B题-seleh模型预失真MATLAB仿真代码...
- java中EQ、NE、GT、GE、LT、LE分别代表含义
- 百度谷歌必应搜狗知乎 可切换搜索框的实现
- nfs服务共享目录的创建
- 常见的嵌入式微处理器(Micro Processor Unit,MPU)
- php显示照片墙,照片墙(css动态效果)
- 实习时候的亚子==(四)
- Linux 视频剪辑与录音
- SYN6288中文语音合成 程序