如何解决如何从 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 举报,一经查实,本站将立刻删除。