[FFmpeg-devel] [PATCHv3] avcodec: Add support for Closed Caption export in h264
Kieran Kunhya
kierank at ob-encoder.com
Thu Jul 2 21:18:13 CEST 2015
---
libavcodec/h264.c | 11 +++++++++++
libavcodec/h264.h | 2 ++
libavcodec/h264_sei.c | 35 ++++++++++++++++++++++++++++++++++-
3 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index 1cbd4cb..1569ec8 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -609,6 +609,8 @@ static int h264_init_context(AVCodecContext *avctx, H264Context *h)
h->prev_frame_num = -1;
h->sei_fpa.frame_packing_arrangement_cancel_flag = -1;
h->has_afd = 0;
+ h->a53_caption_size = 0;
+ h->a53_caption = NULL;
h->next_outputed_poc = INT_MIN;
for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++)
@@ -879,6 +881,15 @@ static void decode_postinit(H264Context *h, int setup_finished)
}
}
+ if (h->a53_caption) {
+ AVFrameSideData *sd =
+ av_frame_new_side_data(cur->f, AV_FRAME_DATA_A53_CC, h->a53_caption_size);
+ if (sd)
+ memcpy(sd->data, h->a53_caption, h->a53_caption_size);
+ av_freep(&h->a53_caption);
+ h->a53_caption_size = 0;
+ }
+
cur->mmco_reset = h->mmco_reset;
h->mmco_reset = 0;
diff --git a/libavcodec/h264.h b/libavcodec/h264.h
index 7565e03..3aef49f 100644
--- a/libavcodec/h264.h
+++ b/libavcodec/h264.h
@@ -784,6 +784,8 @@ typedef struct H264Context {
uint8_t afd;
int has_afd;
+ int a53_caption_size;
+ uint8_t *a53_caption;
// Timestamp stuff
int sei_buffering_period_present; ///< Buffering period SEI flag
diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c
index b6ec5c7..5c6fcc0 100644
--- a/libavcodec/h264_sei.c
+++ b/libavcodec/h264_sei.c
@@ -111,7 +111,7 @@ static int decode_picture_timing(H264Context *h)
static int decode_user_data_itu_t_t35(H264Context *h, int size)
{
uint32_t user_identifier;
- int dtg_active_format;
+ int dtg_active_format, cc_count, user_data_type_code;
if (size < 7)
return -1;
@@ -143,6 +143,39 @@ FF_ENABLE_DEPRECATION_WARNINGS
skip_bits(&h->gb, 6);
}
break;
+ case 0x47413934: // "GA94" closed captions
+ if (size < 3)
+ return AVERROR(EINVAL);
+ user_data_type_code = get_bits(&h->gb, 8);
+ if (user_data_type_code == 0x3) {
+ skip_bits(&h->gb, 1);
+ if (get_bits(&h->gb, 1)) {
+ skip_bits(&h->gb, 1);
+ cc_count = get_bits(&h->gb, 5);
+ skip_bits(&h->gb, 8);
+ size -= 2;
+ if (cc_count && size >= cc_count*3) {
+ int i;
+ uint8_t *tmp;
+ if ((int64_t)h->a53_caption_size + (int64_t)cc_count*3 > INT_MAX)
+ return AVERROR(EINVAL);
+
+ // Allow merging of the cc data from two fields
+ tmp = av_realloc(h->a53_caption, h->a53_caption_size + cc_count*3);
+ if (!tmp)
+ return AVERROR(ENOMEM);
+ h->a53_caption = tmp;
+ for (i = 0; i < cc_count; i++) {
+ h->a53_caption[h->a53_caption_size++] = get_bits(&h->gb, 8);
+ h->a53_caption[h->a53_caption_size++] = get_bits(&h->gb, 8);
+ h->a53_caption[h->a53_caption_size++] = get_bits(&h->gb, 8);
+ }
+
+ skip_bits(&h->gb, 8);
+ }
+ }
+ }
+ break;
default:
skip_bits(&h->gb, size * 8);
break;
--
1.9.1
More information about the ffmpeg-devel
mailing list