[FFmpeg-cvslog] h264: Add support for Closed Caption export

Kieran Kunhya git at videolan.org
Fri Jul 17 14:39:43 CEST 2015


ffmpeg | branch: master | Kieran Kunhya <kierank at ob-encoder.com> | Wed Jul  8 23:17:44 2015 +0100| [b0017579b6e8de3d0d13dcfe0a4dd848dc6baa37] | committer: Vittorio Giovara

h264: Add support for Closed Caption export

Signed-off-by: Vittorio Giovara <vittorio.giovara at gmail.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=b0017579b6e8de3d0d13dcfe0a4dd848dc6baa37
---

 libavcodec/h264.c     |   12 ++++++++++++
 libavcodec/h264.h     |    2 ++
 libavcodec/h264_sei.c |   45 ++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index 6925a8a..a225f5b 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -832,6 +832,18 @@ static void decode_postinit(H264Context *h, int setup_finished)
         h->sei_reguserdata_afd_present = 0;
     }
 
+    if (h->a53_caption) {
+        AVFrameSideData *sd = av_frame_new_side_data(cur->f,
+                                                     AV_FRAME_DATA_A53_CC,
+                                                     h->a53_caption_size);
+        if (!sd)
+            return;
+
+        memcpy(sd->data, h->a53_caption, h->a53_caption_size);
+        av_freep(&h->a53_caption);
+        h->a53_caption_size = 0;
+    }
+
     // FIXME do something with unavailable reference frames
 
     /* Sort B-frames into display order */
diff --git a/libavcodec/h264.h b/libavcodec/h264.h
index 49bd464..bf8b07e 100644
--- a/libavcodec/h264.h
+++ b/libavcodec/h264.h
@@ -680,6 +680,8 @@ typedef struct H264Context {
      */
     int sei_reguserdata_afd_present;
     uint8_t active_format_description;
+    int a53_caption_size;
+    uint8_t *a53_caption;
 
     /**
      * Bit set of clock types for fields/frames in picture timing SEI message.
diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c
index fe85ef1..1f3844b 100644
--- a/libavcodec/h264_sei.c
+++ b/libavcodec/h264_sei.c
@@ -43,6 +43,9 @@ void ff_h264_reset_sei(H264Context *h)
     h->sei_frame_packing_present    =  0;
     h->sei_display_orientation_present = 0;
     h->sei_reguserdata_afd_present  =  0;
+
+    h->a53_caption_size = 0;
+    av_freep(&h->a53_caption);
 }
 
 static int decode_picture_timing(H264Context *h)
@@ -107,7 +110,7 @@ static int decode_registered_user_data(H264Context *h, int size)
 {
     uint32_t country_code;
     uint32_t user_identifier;
-    int flag;
+    int flag, user_data_type_code, cc_count;
 
     if (size < 7)
         return AVERROR_INVALIDDATA;
@@ -140,6 +143,46 @@ static int decode_registered_user_data(H264Context *h, int size)
                 h->sei_reguserdata_afd_present = 1;
             }
             break;
+        case MKBETAG('G', 'A', '9', '4'):       // 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);           // reserved
+
+                flag = get_bits(&h->gb, 1);     // process_cc_data_flag
+                if (flag) {
+                    skip_bits(&h->gb, 1);       // zero bit
+                    cc_count = get_bits(&h->gb, 5);
+                    skip_bits(&h->gb, 8);       // reserved
+                    size -= 2;
+
+                    if (cc_count && size >= cc_count * 3) {
+                        int i, ret;
+                        int new_size = (int64_t) h->a53_caption_size +
+                                       (int64_t) cc_count * 3;
+
+                        if (new_size > INT_MAX)
+                            return AVERROR(EINVAL);
+
+                        /* Allow merging of the cc data from two fields. */
+                        ret = av_reallocp(&h->a53_caption,
+                                          h->a53_caption_size + cc_count * 3);
+                        if (ret < 0)
+                            return ret;
+
+                        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);   // marker_bits
+                    }
+                }
+            }
+            break;
         default:
             skip_bits(&h->gb, size * 8);
             break;



More information about the ffmpeg-cvslog mailing list