ff_mpeg1_encode_picture_header: Add support for AV_FRAME_DATA_A53_CC frame: Add av_frame_get_side_data_at() to allow retrival of multiple side data of the same type. --- libavcodec/mpeg12enc.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ libavutil/frame.c | 8 ++++++++ libavutil/frame.h | 38 +++++++++++++++++++++++++++++++++++- 3 files changed, 97 insertions(+), 1 deletion(-)
diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index f45598a..01fda83 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -543,6 +543,58 @@ void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) } } + /* MPEG closed caption user data is limited to 31 3-byte "closed + * caption constructs" per user data block. There can be serveral + * such user data blocks per frame. + */ + for (int i = 0;; ++i) { + side_data = av_frame_get_side_data_at(s->current_picture_ptr->f, i); + if (!side_data) + break; + + if (side_data->type == AV_FRAME_DATA_A53_CC) { + avpriv_align_put_bits(&s->pb); + put_header(s, USER_START_CODE); + + /* ATSC user data identifier for CC or BAR data */ + put_bits(&s->pb, 8, 'G'); + put_bits(&s->pb, 8, 'A'); + put_bits(&s->pb, 8, '9'); + put_bits(&s->pb, 8, '4'); + + /* MPEG CC data type code */ + put_bits(&s->pb, 8, 0x03); + + /* cc_data() { + * reserved (1 bits) ’1’ + * process_cc_data_flag (1 bits) bslbf + * additional_data_flag (1 bits) bslbf + * cc_count (5 bits) uimsbf + * reserved (8 bits) ‘1111 1111’ + * for (i=0 ; i < cc_count ; ++i) { + * marker_bits (5 bits) ‘1111 1’ + * cc_valid (1 bits) bslbf + * cc_type (2 bits) bslbf + * cc_data_1 (8 bits) bslbf + * cc_data_2 (8 bits) bslbf + * } + * marker_bits (8 bits) ‘1111 1111’ + * if (additional_data_flag) { + * while (nextbits() != ‘0000 0000 0000 0000 0000 0001’) { + * additional_cc_data + * } + * } + * } + */ + for(int j = 0; j < side_data->size; ++j) { + put_bits(&s->pb, 8, side_data->data[j]); + } + + /* Marker bits */ + put_bits(&s->pb, 8, 0xFF); + } + } + s->mb_y = 0; ff_mpeg1_encode_slice_header(s); } diff --git a/libavutil/frame.c b/libavutil/frame.c index 24d5d5f..8912f52 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -688,6 +688,14 @@ AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, return NULL; } +AVFrameSideData *av_frame_get_side_data_at(const AVFrame *frame, int idx) +{ + if (idx < frame->nb_side_data) + return frame->side_data[idx]; + + return NULL; +} + static int frame_copy_video(AVFrame *dst, const AVFrame *src) { const uint8_t *src_data[4]; diff --git a/libavutil/frame.h b/libavutil/frame.h index 26261d7..5503106 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -52,8 +52,39 @@ enum AVFrameSideDataType { AV_FRAME_DATA_PANSCAN, /** * ATSC A53 Part 4 Closed Captions. - * A53 CC bitstream is stored as uint8_t in AVFrameSideData.data. + * A53 CC bitstream (cc_data) is stored as uint8_t in AVFrameSideData.data. * The number of bytes of CC data is AVFrameSideData.size. + * + * Data format: + * + * bslbf -- Bit string, left bit first, where “left” is the order in + * which bit strings are written in the Standard. Bit strings are + * written as a string of 1s and 0s within single quote marks, + * e.g. ‘1000 0001’. Blanks within a bit string are for ease of + * reading and have no significance + * + * uimsbf -- Unsigned integer, most significant bit first. + * + * cc_data() { + * reserved (1 bits) ’1’ + * process_cc_data_flag (1 bits) bslbf + * additional_data_flag (1 bits) bslbf + * cc_count (5 bits) uimsbf + * reserved (8 bits) ‘1111 1111’ + * for (i=0 ; i < cc_count ; ++i) { + * marker_bits (5 bits) ‘1111 1’ + * cc_valid (1 bits) bslbf + * cc_type (2 bits) bslbf + * cc_data_1 (8 bits) bslbf + * cc_data_2 (8 bits) bslbf + * } + * marker_bits (8 bits) ‘1111 1111’ + * if (additional_data_flag) { + * while (nextbits() != ‘0000 0000 0000 0000 0000 0001’) { + * additional_cc_data + * } + * } + * } */ AV_FRAME_DATA_A53_CC, /** @@ -759,6 +790,11 @@ AVFrameSideData *av_frame_new_side_data(AVFrame *frame, */ AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type); +/** + * @return a pointer to the side data at the given index on success, + * NULL if the index is out-of-bounds. + */ +AVFrameSideData *av_frame_get_side_data_at(const AVFrame *frame, int idx); /** * If side data of the supplied type exists in the frame, free it and remove it -- 2.1.4 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel