Those SEIs refer to the currently active SPS. However, since the SEI
NALUs precede the coded picture data in the bitstream, the active SPS is
in general not known when we are decoding the SEI.
Therefore, store the content of the picture timing SEIs and actually
parse it when the active SPS is known.
---
libavcodec/h264_parser.c | 9 ++++++
libavcodec/h264_sei.c | 74 +++++++++++++++++++++++++++++++-----------------
libavcodec/h264_sei.h | 10 +++++++
libavcodec/h264_slice.c | 10 +++++++
4 files changed, 77 insertions(+), 26 deletions(-)
diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c
index 22153bd..44a846e 100644
--- a/libavcodec/h264_parser.c
+++ b/libavcodec/h264_parser.c
@@ -402,6 +402,15 @@ static inline int parse_nal_units(AVCodecParserContext *s,
}
}
+ if (p->sei.picture_timing.present) {
+ ret =
ff_h264_sei_process_picture_timing(&p->sei.picture_timing,
+ sps, avctx);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Error processing the picture
timing SEI\n");
+ p->sei.picture_timing.present = 0;
+ }
+ }
+
if (sps->pic_struct_present_flag && p->sei.picture_timing.present)
{
switch (p->sei.picture_timing.pic_struct) {
case SEI_PIC_STRUCT_TOP_FIELD:
diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c
index 2e52227..9bbec1b 100644
--- a/libavcodec/h264_sei.c
+++ b/libavcodec/h264_sei.c
@@ -31,6 +31,7 @@
#include "h264_ps.h"
#include "h264_sei.h"
#include "internal.h"
+#include "put_bits.h"
static const uint8_t sei_num_clock_ts_table[9] = {
1, 1, 1, 2, 2, 3, 3, 2, 3
@@ -54,21 +55,22 @@ void ff_h264_sei_uninit(H264SEIContext *h)
av_freep(&h->a53_caption.a53_caption);
}
-static int decode_picture_timing(H264SEIPictureTiming *h, GetBitContext *gb,
- const SPS *sps, void *logctx)
+int ff_h264_sei_process_picture_timing(H264SEIPictureTiming *h, const SPS *sps,
+ void *logctx)
{
- if (!sps)
- return AVERROR_INVALIDDATA;
+ GetBitContext gb;
+
+ init_get_bits(&gb, h->payload, sizeof(h->payload));
if (sps->nal_hrd_parameters_present_flag ||
sps->vcl_hrd_parameters_present_flag) {
- h->cpb_removal_delay = get_bits(gb, sps->cpb_removal_delay_length);
- h->dpb_output_delay = get_bits(gb, sps->dpb_output_delay_length);
+ h->cpb_removal_delay = get_bits(&gb, sps->cpb_removal_delay_length);
+ h->dpb_output_delay = get_bits(&gb, sps->dpb_output_delay_length);
}
if (sps->pic_struct_present_flag) {
unsigned int i, num_clock_ts;
- h->pic_struct = get_bits(gb, 4);
+ h->pic_struct = get_bits(&gb, 4);
h->ct_type = 0;
if (h->pic_struct > SEI_PIC_STRUCT_FRAME_TRIPLING)
@@ -77,32 +79,32 @@ static int decode_picture_timing(H264SEIPictureTiming *h,
GetBitContext *gb,
num_clock_ts = sei_num_clock_ts_table[h->pic_struct];
for (i = 0; i < num_clock_ts; i++) {
- if (get_bits(gb, 1)) { /* clock_timestamp_flag */
+ if (get_bits(&gb, 1)) { /* clock_timestamp_flag */
unsigned int full_timestamp_flag;
- h->ct_type |= 1 << get_bits(gb, 2);
- skip_bits(gb, 1); /* nuit_field_based_flag */
- skip_bits(gb, 5); /* counting_type */
- full_timestamp_flag = get_bits(gb, 1);
- skip_bits(gb, 1); /* discontinuity_flag */
- skip_bits(gb, 1); /* cnt_dropped_flag */
- skip_bits(gb, 8); /* n_frames */
+ h->ct_type |= 1 << get_bits(&gb, 2);
+ skip_bits(&gb, 1); /* nuit_field_based_flag */
+ skip_bits(&gb, 5); /* counting_type */
+ full_timestamp_flag = get_bits(&gb, 1);
+ skip_bits(&gb, 1); /* discontinuity_flag */
+ skip_bits(&gb, 1); /* cnt_dropped_flag */
+ skip_bits(&gb, 8); /* n_frames */
if (full_timestamp_flag) {
- skip_bits(gb, 6); /* seconds_value 0..59 */
- skip_bits(gb, 6); /* minutes_value 0..59 */
- skip_bits(gb, 5); /* hours_value 0..23 */
+ skip_bits(&gb, 6); /* seconds_value 0..59 */
+ skip_bits(&gb, 6); /* minutes_value 0..59 */
+ skip_bits(&gb, 5); /* hours_value 0..23 */
} else {
- if (get_bits(gb, 1)) { /* seconds_flag */
- skip_bits(gb, 6); /* seconds_value range 0..59
*/
- if (get_bits(gb, 1)) { /* minutes_flag */
- skip_bits(gb, 6); /* minutes_value 0..59 */
- if (get_bits(gb, 1)) /* hours_flag */
- skip_bits(gb, 5); /* hours_value 0..23 */
+ if (get_bits(&gb, 1)) { /* seconds_flag */
+ skip_bits(&gb, 6); /* seconds_value range
0..59 */
+ if (get_bits(&gb, 1)) { /* minutes_flag */
+ skip_bits(&gb, 6); /* minutes_value 0..59 */
+ if (get_bits(&gb, 1)) /* hours_flag */
+ skip_bits(&gb, 5); /* hours_value 0..23 */
}
}
}
if (sps->time_offset_length > 0)
- skip_bits(gb,
+ skip_bits(&gb,
sps->time_offset_length); /* time_offset */
}
}
@@ -111,6 +113,26 @@ static int decode_picture_timing(H264SEIPictureTiming *h,
GetBitContext *gb,
h->ct_type, h->pic_struct);
}
+ return 0;
+}
+
+static int decode_picture_timing(H264SEIPictureTiming *h, GetBitContext *gb,
+ void *logctx)
+{
+ PutBitContext pb;
+ int n;
+
+ init_put_bits(&pb, h->payload, sizeof(h->payload));
+
+ while (get_bits_left(gb) >= 32)
+ put_bits(&pb, 32, get_bits_long(gb, 32));
+
+ n = get_bits_left(gb);
+ if (n)
+ put_bits(&pb, n, get_bits_long(gb, n));
+
+ flush_put_bits(&pb);
+
h->present = 1;
return 0;
}
@@ -381,7 +403,7 @@ int ff_h264_sei_decode(H264SEIContext *h, GetBitContext *gb,
switch (type) {
case SEI_TYPE_PIC_TIMING: // Picture timing SEI
- ret = decode_picture_timing(&h->picture_timing, &gb_payload,
ps->sps, logctx);
+ ret = decode_picture_timing(&h->picture_timing, &gb_payload,
logctx);
break;
case SEI_TYPE_USER_DATA_REGISTERED:
ret = decode_registered_user_data(h, &gb_payload, logctx, size);
diff --git a/libavcodec/h264_sei.h b/libavcodec/h264_sei.h
index 8815aa3..37987db 100644
--- a/libavcodec/h264_sei.h
+++ b/libavcodec/h264_sei.h
@@ -20,6 +20,7 @@
#define AVCODEC_H264_SEI_H
#include "get_bits.h"
+#include "h264_ps.h"
/**
* SEI message types
@@ -51,6 +52,9 @@ typedef enum {
typedef struct H264SEIPictureTiming {
int present;
+
+ uint8_t payload[32];
+
SEI_PicStructType pic_struct;
/**
@@ -135,4 +139,10 @@ int ff_h264_sei_decode(H264SEIContext *h, GetBitContext
*gb,
*/
void ff_h264_sei_uninit(H264SEIContext *h);
+/**
+ * Parse the contents of a picture timing message given an active SPS.
+ */
+int ff_h264_sei_process_picture_timing(H264SEIPictureTiming *h, const SPS *sps,
+ void *logctx);
+
#endif /* AVCODEC_H264_SEI_H */
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index 427cbe6..19f5d37 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -1003,6 +1003,16 @@ static int h264_export_frame_props(H264Context *h)
/* Signal interlacing information externally. */
/* Prioritize picture timing SEI information over used
* decoding process if it exists. */
+ if (h->sei.picture_timing.present) {
+ int ret = ff_h264_sei_process_picture_timing(&h->sei.picture_timing,
sps,
+ h->avctx);
+ if (ret < 0) {
+ av_log(h->avctx, AV_LOG_ERROR, "Error processing a picture timing
SEI\n");
+ if (h->avctx->err_recognition & AV_EF_EXPLODE)
+ return ret;
+ h->sei.picture_timing.present = 0;
+ }
+ }
if (sps->pic_struct_present_flag && h->sei.picture_timing.present) {
H264SEIPictureTiming *pt = &h->sei.picture_timing;
--
2.0.0
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel