首页 > IT业界 > 国内 > 正文

FFmpeg从入门到精通:SEI那些事(2)
2018-02-09 15:09        我要评论()
字号:T|T
  SEI例子
 
  从video.js <https://github.com/videojs/video.js>的示例中下载oceans.mp4 <http://vjs.zencdn.net/v/oceans.mp4>并提取出H.264码流如下:
\" src=
  bitstream from oceans.mp4
 
  NAL header
 
  起始码(暗红底色)"0x00000001"分割出来的比特流即是NAL unit,起始码紧跟的第一个字节(墨绿底色)是NAL header。上图“NAL header”一共出现了四个数值:
 
  ·"0x06",此时NRI为"00B",NAL unit type为SEI类型。
 
  ·“0x67”,此时NRI为“11B”,NAL unit type为SPS类型。
 
  ·“0x68”,此时NRI为“11B”,NAL unit type为PPS类型。
 
  ·“0x65”,此时NRI为“11B”,NAL unit type为IDR图像。
 
  SEI payload type
 
  "0x06"后一个字节为“0x05”(淡黄底色)是SEI payload type,即表征SEI payload分析遵循user_data_unregistered()语法。
 
  SEI payload size
 
  “0x05”后一个字节为“0x2F”(淡蓝底色)是SEI payload size,此时整个payload是47个字节。
 
  SEI payload uuid
 
  "0x2F"随后的16个字节即为uuid,此时uuid为
 
  dc45e9bd-e6d9-48b7-962c-d820d923eeef
 
  SEI payload content
 
  由于payload size是47个字节,除去16字节的uuid,剩下31个字节的content。由于content是字符串,所以有结束符"0x00",有效的30个字符内容是:
 
  Zencoder Video Encoding System
 
  rbsp trailing bits
 
  47个payload字节后的"0x80"(灰底色)即是rbsp trailing bits,在user_data_unregistered()里面都是按字节写入的,所以此时的NAL unit结尾写入的字节一定是0x80。
 
  SEI的生成
 
  生成SEI的方式很多,大致可以有:
 
  1.对已有码流做filter,插入SEI NAL
 
  2.视频编码时生成SEI
 
  3.容器层写入时插入SEI
 
  以下代码示例来自于FFmpeg origin/master 分支。
 
  bsf
 
  BitStream Filter(码流过滤)的缩写为bsf,它的作用是,在不做码流解码的前提下,对已经编码后的比特流做特定的修改、调整。
 
  bsf h264_metadata的调用
 
  使用ffmpeg工具时,可以使用比特流过滤器。基本的filter调用格式如下:
 
  ffmpeg -i INPUT -c:v copy -bsf:v filter1[=opt1=str1:opt2=str2][,filter2] OUTPUT
 
  从上文提到的mp4文件中提取出h.264码流oceans.h264,可以使用 h264_metadata比特流过滤器添加SEI。下面示例命令添加了类型为未注册的用户数据的SEI,其中uuid为"086f3693-b7b3-4f2c-9653-21492feee5b8",payload内容为"hello":
 
  ./ffmpeg  -I oceans.h264 -c:v copy -bsf:v h264_metadata=sei_user_data='086f3693-b7b3-4f2c-9653-21492feee5b8+hello' oceans.sei.h264
 
  其中oceans.h264已经有一个SEI和28个SPS。输出的oceans.sei.h264码流中,共有28个SEI,其中第一个与输入保持一致,剩下27个为新插入的SEI。
 
  bsf h264_metadata的代码分析
 
  具体代码位于:libavcodec/h264_metadata_bsf.c中。
 
  // 函数int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out)
 
  if (ctx->sei_user_data && (has_sps || !ctx->sei_first_au)) {
 
  H264RawSEI *sei;
 
  H264RawSEIPayload *payload;
 
  H264RawSEIUserDataUnregistered *udu;
 
  int sei_pos, sei_new;
 
  ctx->sei_first_au = 1;
 
  for (i = 0; i < au->nb_units; i++) {
 
  if (au->units[i].type == H264_NAL_SEI ||
 
  au->units[i].type == H264_NAL_SLICE ||
 
  au->units[i].type == H264_NAL_IDR_SLICE)
 
  break;
 
  }
 
  sei_pos = i;
 
  if (sei_pos < au->nb_units &&
 
  au->units[sei_pos].type == H264_NAL_SEI) {
 
  sei_new = 0;
 
  sei = au->units[sei_pos].content;
 
  } else {
 
  sei_new = 1;
 
  sei = &ctx->sei_nal;
 
  memset(sei, 0, sizeof(*sei));
 
  }
 
  }
 
  以上代码是h264_metadata添加SEI的判断逻辑,当指定了sei_user_data时,满足以下条件之一即可以处理:
 
  ·读取的access units是第一个au;
 
  ·当前au包含sps;
 
  满足插入SEI逻辑后,具体处理过程中:
 
  ·如果发现第一个NAL已经是SEI,则该au不做插入SEI处理;
 
  ·如果au包含了IDR帧或者非IDR未分区的帧,则在其前面插入SEI信息。
 
  基于以上代码,oceans.sei.h264码流中新插入27个新的SEI 符合处理逻辑。

联系电话:13811959286

IT频道纠错邮箱:erjuner@163.com

责任编辑:新闻中心

我要评论

已有位网友参与评论

网站地图

牛华网

华军下载 | 牛华网 | 盒子 | pcsoft | 论坛

实用工具

关于我们 | 新闻投稿 | 软件发布 | 版权声明 | 意见建议 | 网站地图 | 友情连接 | RSS订阅 | 总编信箱 | 诚聘英才 | 联系我们

苏ICP备11016551号-2  苏公网安备 32132202000111号 本站特聘法律顾问:于国富律师

Copyright (C) 1997-2018 newhua.com 江苏奥蓝德软件有限公司 版权所有