微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何从 H264 中的 ffmpeg 读取 sei 未注册的用户数据?

如何解决如何从 H264 中的 ffmpeg 读取 sei 未注册的用户数据?

首先,我通过 bsf 将 user_data 设置为 video。例如,

ffmpeg  -i dump.flv -c:v copy -bsf:v h264_Metadata=sei_user_data='086f3693-b7b3-4f2c-9653-21492feee5b8+hello' dump_sei.flv

Ant然后我用api在h264编码后通过ffmpeg读取sei unregistered_user_data,但是我没有得到。


// avcodec_send_packet
// avcodec_receive_frame
// ...

H264Context *h = m_pVidDecodeCtx->priv_data;
H264SEIContext sei = h->sei;
H264SEIUnregistered unregistered = sei.unregistered;
if (unregistered.buf_ref != NULL)
{
  AVBufferRef *buf = *(unregistered.buf_ref);
  if (buf != NULL && buf->buffer != NULL)
  {
     printf("sei data: %s\n",buf->buffer);
  }
}

ffmpeg 的版本是 v4.4。

解决方法

h264_sei.c 文件是您可以找到有关 SEI 的所有问题的答案的重要宝藏。 (存在于 libavcodec 文件夹中)

      static int decode_registered_user_data_afd(H264SEIAFD *h,GetBitContext *gb,int size)
  {
      int flag;
  
      if (size-- < 1)
          return AVERROR_INVALIDDATA;
      skip_bits(gb,1);               // 0
      flag = get_bits(gb,1);         // active_format_flag
      skip_bits(gb,6);               // reserved
  
      if (flag) {
          if (size-- < 1)
              return AVERROR_INVALIDDATA;
          skip_bits(gb,4);           // reserved
          h->active_format_description = get_bits(gb,4);
          h->present                   = 1;
      }
  
      return 0;
  }
  
  static int decode_registered_user_data_closed_caption(H264SEIA53Caption *h,void *logctx,int size)
  {
      if (size < 3)
          return AVERROR(EINVAL);
  
      return ff_parse_a53_cc(&h->buf_ref,gb->buffer + get_bits_count(gb) / 8,size);
  }
  
  static int decode_registered_user_data(H264SEIContext *h,int size)
  {
      int country_code,provider_code;
  
      if (size < 3)
          return AVERROR_INVALIDDATA;
      size -= 3;
  
      country_code = get_bits(gb,8); // itu_t_t35_country_code
      if (country_code == 0xFF) {
          if (size < 1)
              return AVERROR_INVALIDDATA;
  
          skip_bits(gb,8);           // itu_t_t35_country_code_extension_byte
          size--;
      }
  
      if (country_code != 0xB5) { // usa_country_code
          av_log(logctx,AV_LOG_VERBOSE,"Unsupported User Data Registered ITU-T T35 SEI message (country_code = %d)\n",country_code);
          return 0;
      }
  
      /* itu_t_t35_payload_byte follows */
      provider_code = get_bits(gb,16);
  
      switch (provider_code) {
      case 0x31: { // atsc_provider_code
          uint32_t user_identifier;
  
          if (size < 4)
              return AVERROR_INVALIDDATA;
          size -= 4;
  
          user_identifier = get_bits_long(gb,32);
          switch (user_identifier) {
          case MKBETAG('D','T','G','1'):       // afd_data
              return decode_registered_user_data_afd(&h->afd,gb,size);
          case MKBETAG('G','A','9','4'):       // closed captions
              return decode_registered_user_data_closed_caption(&h->a53_caption,logctx,size);
          default:
              av_log(logctx,"Unsupported User Data Registered ITU-T T35 SEI message (atsc user_identifier = 0x%04x)\n",user_identifier);
              break;
          }
          break;
      }
      default:
          av_log(logctx,"Unsupported User Data Registered ITU-T T35 SEI message (provider_code = %d)\n",provider_code);
          break;
      }
  
      return 0;
  }
  
  static int decode_unregistered_user_data(H264SEIUnregistered *h,int size)
  {
      uint8_t *user_data;
      int e,build,i;
      AVBufferRef *buf_ref,**tmp;
  
      if (size < 16 || size >= INT_MAX - 1)
          return AVERROR_INVALIDDATA;
  
      tmp = av_realloc_array(h->buf_ref,h->nb_buf_ref + 1,sizeof(*h->buf_ref));
      if (!tmp)
          return AVERROR(ENOMEM);
      h->buf_ref = tmp;
  
      buf_ref = av_buffer_alloc(size + 1);
      if (!buf_ref)
          return AVERROR(ENOMEM);
      user_data = buf_ref->data;
  
      for (i = 0; i < size; i++)
          user_data[i] = get_bits(gb,8);
  
      user_data[i] = 0;
      buf_ref->size = size;
      h->buf_ref[h->nb_buf_ref++] = buf_ref;
  
      e = sscanf(user_data + 16,"x264 - core %d",&build);
      if (e == 1 && build > 0)
          h->x264_build = build;
      if (e == 1 && build == 1 && !strncmp(user_data+16,"x264 - core 0000",16))
          h->x264_build = 67;
  
      return 0;
  }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。