---
libavcodec/avcodec.h | 5 ++++
libavcodec/mpeg12dec.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
libavutil/frame.h | 4 ++++
3 files changed, 73 insertions(+)
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 4ce6d61..9e7d968 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -845,6 +845,11 @@ typedef struct AVPanScan{
int16_t position[3][2];
}AVPanScan;
+typedef struct AVClosedCaption {
+ int count;
+ uint8_t data[1];
+} AVClosedCaption;
+
#if FF_API_QSCALE_TYPE
#define FF_QSCALE_TYPE_MPEG1 0
#define FF_QSCALE_TYPE_MPEG2 1
diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index 0e11dda..19a91a1 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -44,6 +44,7 @@ typedef struct Mpeg1Context {
int mpeg_enc_ctx_allocated; /* true if decoding context allocated */
int repeat_field; /* true if we must repeat the field */
AVPanScan pan_scan; /**< some temporary storage for the
panscan */
+ AVClosedCaption *caption;
int slice_count;
int save_aspect_info;
int save_width, save_height, save_progressive_seq;
@@ -1529,6 +1530,15 @@ static int mpeg_field_start(MpegEncContext *s, const
uint8_t *buf, int buf_size)
return AVERROR(ENOMEM);
memcpy(pan_scan->data, &s1->pan_scan, sizeof(s1->pan_scan));
+ if (s1->caption != NULL) {
+ int size = sizeof(AVClosedCaption) + s1->caption->count * 3;
+ AVFrameSideData *sd = av_frame_new_side_data(
+ &s->current_picture_ptr->f, AV_FRAME_DATA_CC, size);
+ if (sd != NULL) {
+ memcpy(sd->data, s1->caption, size);
+ }
+ av_freep(&s1->caption);
+ }
if (HAVE_THREADS && (avctx->active_thread_type & FF_THREAD_FRAME))
ff_thread_finish_setup(avctx);
} else { // second field
@@ -2038,6 +2048,57 @@ static int vcr2_init_sequence(AVCodecContext *avctx)
}
+static int mpeg_decode_cc(AVCodecContext *avctx, const uint8_t *p, int
buf_size)
+{
+ Mpeg1Context *s1 = avctx->priv_data;
+
+ if (buf_size >= 6 &&
+ p[0] == 'G' && p[1] == 'A' && p[2] == '9' && p[3] == '4' && p[4] == 3)
{
+ /* extract A53 Part 4 CC data */
+ int cc_count = p[5] & 0x1f;
+ if (cc_count > 0 && buf_size >= 7 + cc_count * 3) {
+ s1->caption = av_malloc(sizeof(AVClosedCaption) + cc_count * 3);
+ if (s1->caption != NULL) {
+ s1->caption->count = cc_count;
+ memcpy(s1->caption->data, p + 7, cc_count * 3);
+ }
+ }
+ return 1;
+ } else if (buf_size >= 11 &&
+ p[0] == 'C' && p[1] == 'C' && p[2] == 0x01 && p[3] == 0xf8) {
+ /* extract DVD CC data */
+ int cc_count = 0;
+ int i;
+ // There is a caption count field in the data, but it is often
+ // incorect. So count the number of captions present.
+ for (i = 5; i + 6 <= buf_size && ((p[i] & 0xfe) == 0xfe); i += 6) {
+ cc_count++;
+ }
+ // Transform the DVD format into A53 Part 4 format
+ if (cc_count > 0) {
+ s1->caption = av_malloc(sizeof(AVClosedCaption) + cc_count * 6);
+ if (s1->caption != NULL) {
+ uint8_t field1 = !!(p[4] & 0x80);
+ uint8_t *cap = s1->caption->data;
+ p += 5;
+ s1->caption->count = cc_count * 2;
+ for (i = 0; i < cc_count; i++) {
+ cap[0] = (p[0] == 0xff && field1) ? 0xfc : 0xfd;
+ cap[1] = p[1];
+ cap[2] = p[2];
+ cap[3] = (p[3] == 0xff && !field1) ? 0xfc : 0xfd;
+ cap[4] = p[4];
+ cap[5] = p[5];
+ cap += 6;
+ p += 6;
+ }
+ }
+ }
+ return 1;
+ }
+ return 0;
+}
+
static void mpeg_decode_user_data(AVCodecContext *avctx,
const uint8_t *p, int buf_size)
{
@@ -2057,6 +2118,8 @@ static void mpeg_decode_user_data(AVCodecContext *avctx,
return;
avctx->dtg_active_format = p[0] & 0x0f;
}
+ } else if (mpeg_decode_cc(avctx, p, buf_size)) {
+ return;
}
}
@@ -2402,6 +2465,7 @@ static av_cold int mpeg_decode_end(AVCodecContext *avctx)
if (s->mpeg_enc_ctx_allocated)
ff_MPV_common_end(&s->mpeg_enc_ctx);
+ av_freep(&s->caption);
return 0;
}
diff --git a/libavutil/frame.h b/libavutil/frame.h
index 449a6b7..5d963ef 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -35,6 +35,10 @@ enum AVFrameSideDataType {
* The data is the AVPanScan struct defined in libavcodec.
*/
AV_FRAME_DATA_PANSCAN,
+ /**
+ * CC data is in the AVClosedCaption struct defined in libavcodec.
+ */
+ AV_FRAME_DATA_CC,
};
typedef struct AVFrameSideData {
--
1.8.3.1
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel