[英]How to read sei unregistered user data from ffmpeg in H264?
First, I set the user_data to video by bsf.首先,我通过 bsf 将 user_data 设置为 video。 For example,
例如,
ffmpeg -i dump.flv -c:v copy -bsf:v h264_metadata=sei_user_data='086f3693-b7b3-4f2c-9653-21492feee5b8+hello' dump_sei.flv
Ant then I use the api to read sei unregistered_user_data by ffmpeg after h264 encode, but I didn't get it. 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);
}
}
The version of ffmpeg is v4.4. ffmpeg的版本是v4.4。
A great treasure where you can find your answers to all your questions about SEI is h264_sei.c file. h264_sei.c 文件是一个伟大的宝藏,您可以在其中找到有关 SEI 的所有问题的答案。 (that exist in libavcodec folder)
(存在于 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.