From patchwork Tue Jun 6 21:06:20 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: John P Poet X-Patchwork-Id: 3860 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.10.2 with SMTP id 2csp2045679vsk; Tue, 6 Jun 2017 14:13:44 -0700 (PDT) X-Received: by 10.223.129.230 with SMTP id 93mr19361716wra.57.1496783624104; Tue, 06 Jun 2017 14:13:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1496783624; cv=none; d=google.com; s=arc-20160816; b=RczQNJVd6QAeWDSaN67N+FugkQjUY0fEmnB5+HWtbT8qnu0hlPasSV0IN0YWYfvqYz mjSoYL+GkHgd6K+ILW4viN/fvE768ef9+P7gQfOi9BEXsYAc5wPDRZ7Lh5zwyZVumKmm JS0zDj6Q8EuPByi1V71poU17hLdFYYSjPbG6rR1WDbWTCoQon3a1YtTXAJEQXNrxofpv E2slVkoh2iLS4LpYaDIvaBThfTj9movPCzksCt6IUgyBdPh7DvDn1Gg52hbDjkDPUDiv Z8Wi3BVliqlXb+4aDbL4gmZgskxNebDKugdq2jZOYhFzFE5b30TtMnEXy8IHduSYzjpP nDPw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:message-id:date:to:from :dkim-signature:delivered-to:arc-authentication-results; bh=gPWbRfyrG4ZlmxRbuj0MNr/3O6rwG9ipyYPqNOGG+qY=; b=qFRyPc2FTz7WQFeWbF2/WJXtyyfZ9pLkpGZG8gs98fCFOdvrGd/CFlrTcukFW9ANPI aEsDk5JGRCvXTehBuOAQQrZ0ohMbLgGuK1XxZqL8JsKW5x9Yszbgqdbx9GdY+5aDSIAp sZbEEF49+xF9QGKKU4JMxkmShgmFS6jh700N0g+Nm1ALetmg61VE5j2XxI0Hg4KpFkXg ajLJON0Yvum7ZulMlUU33T9QgwG10rib/bnG4shNnrwkmMq6pjW/UOL4REseejNffJSa gUX8+6ty4nLQzeeRYw0miiKCqw2m7KvtDfOC4D++k2yEgbfRWHFou75YFc4eSdNlCPFb A+GQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id g25si21054074wrc.311.2017.06.06.14.13.43; Tue, 06 Jun 2017 14:13:44 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 23826689E1E; Wed, 7 Jun 2017 00:13:33 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-it0-f50.google.com (mail-it0-f50.google.com [209.85.214.50]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2C83C689D69 for ; Wed, 7 Jun 2017 00:13:26 +0300 (EEST) Received: by mail-it0-f50.google.com with SMTP id x129so12796238ite.0 for ; Tue, 06 Jun 2017 14:13:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=r8SGSEkKptl/U5z0vAH/lPO3JqQ1xaMSCjTtrIF6LcE=; b=nLVAi+uJJEwgzVXNZuQiq1lyAyxrVqk4GlyADETnAZ8Gk1xTF4i+baRXWSqaoRF5YI bsMgMjeA6Nh8oom+62yX/d7qiUQimqbsk34BK5urWMt5hGm7AWCkf7p0hDLgVa0gI29I Fu+OiK5GMOKgVHgxbYt4jHBD80U+lTZOmIfi3tLQPS/ZNXF8e6DtpEOK1e8gU0fO3N7A 09Bz2mE1JVFxqfm+A8xl2W65rhM9ws3VXUDPxwOU/Dw5kGEfgwXmGqIVKkCPx/K/BQU5 qJQpF1WqPEivcJoE5Mp49C9j4e8FBkNa5ZAZASN34hxBjtrOr2pGz2Pz8O+cJcgRiVM2 svkQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=r8SGSEkKptl/U5z0vAH/lPO3JqQ1xaMSCjTtrIF6LcE=; b=AKcU90QsnV67SmUgb9cai7FNGoIKx2lXT/uJMnObOgP6d+fHGhvLNbPhHquDnAPjwk QWeiJS16J2Zl/M3v9Bj8b3PJDOHFhX4QYCUZHpyJV70B9A+Jk4DrflLGHlzKM4ScnEjC 2IW7+SGVqbIppPIKcbGqZ6XurIrJFk6CPMzV5/jJEqMJn2ZMKEdFxf2MjXJhqlX/Uzvt /T/+xSZV04Abf5ns3sgdwX5lT9BEzD7CayON0dWQ72FaTy20/MHGLfC+wZQ+AuWV6JCM +gBIz0fgch743rk060JcB8UsvRSyXDCAew+7dIwA2Hk3rRTzFchYKKdhhC2hzfSM2Zle VZBQ== X-Gm-Message-State: AODbwcDPFOfsk1mRes4QQeVFDkiQyFgir2Carp6W1ONmiut9G10ZwgQI QRJvQVgOpKveWg== X-Received: by 10.107.160.143 with SMTP id j137mr32774623ioe.20.1496783184413; Tue, 06 Jun 2017 14:06:24 -0700 (PDT) Received: from cobalt.localdomain (75-173-118-168.albq.qwest.net. [75.173.118.168]) by smtp.gmail.com with ESMTPSA id 66sm6169058iol.0.2017.06.06.14.06.23 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 06 Jun 2017 14:06:23 -0700 (PDT) From: John Poet X-Google-Original-From: John Poet To: jppoet@gmail.com, ffmpeg-devel@ffmpeg.org Date: Tue, 6 Jun 2017 15:06:20 -0600 Message-Id: <1496783180-6128-1-git-send-email-jppoet@digital-nirvana.com> X-Mailer: git-send-email 2.7.5 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] Add A53 Closed Captions to MPEG header if they are available. X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: John Poet Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" 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