繁体   English   中英

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

[英]How to read sei unregistered user data from ffmpeg in H264?

首先,我通过 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,
                                                       GetBitContext *gb, 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, GetBitContext *gb,
                                         void *logctx, 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, gb,
                                                                logctx, size);
          default:
              av_log(logctx, AV_LOG_VERBOSE,
                     "Unsupported User Data Registered ITU-T T35 SEI message (atsc user_identifier = 0x%04x)\n",
                     user_identifier);
              break;
          }
          break;
      }
      default:
          av_log(logctx, AV_LOG_VERBOSE,
                 "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, GetBitContext *gb,
                                           void *logctx, 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;
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM