From patchwork Sun Dec 5 19:41:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Soft Works X-Patchwork-Id: 32025 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a6b:cd86:0:0:0:0:0 with SMTP id d128csp3628327iog; Sun, 5 Dec 2021 11:42:51 -0800 (PST) X-Google-Smtp-Source: ABdhPJzWFciCM8kKiQlmsA7WL05SQ18RgZAc51EtWUnu/Jn5Xbp2Lohu/ODTZCdmL9QIeR2v4Wgg X-Received: by 2002:a50:9514:: with SMTP id u20mr47026237eda.117.1638733371660; Sun, 05 Dec 2021 11:42:51 -0800 (PST) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id y22si17175311edc.590.2021.12.05.11.42.51; Sun, 05 Dec 2021 11:42:51 -0800 (PST) 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=@hotmail.com header.s=selector1 header.b=vFEgJJKv; arc=fail (body hash mismatch); 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=hotmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 821FF68AF7B; Sun, 5 Dec 2021 21:41:50 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from NAM10-DM6-obe.outbound.protection.outlook.com (mail-dm6nam10olkn2076.outbound.protection.outlook.com [40.92.41.76]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 08B5168AF21 for ; Sun, 5 Dec 2021 21:41:41 +0200 (EET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=fbtqWnLcGhLlnR5By4GgWWVKARJn/hZwobASg1RXPW8BtaC0cXVLJYKhLrp2C8T2D49XqgBVzSw0RJCs4DATo8xhM/CaX2BT0dBe39Vsd6N2cRNuGfQDChVKPoae1Ues3j112HSHNzOzLaSGJlc0/crXVAuWBcebmbf1/UyZyRx4JwSmjpzNEeg6A3z/LJCJrHuNBlq5n+p2HhJJ7XzpEUh8EYDgY7L/WMmtcLQX70NHfVdK4ZZ5uXqvVKXZCa2IfQHTSMHZYWHHfu0ZpXLSZT/jx3roU7SU/SBbtRnF8+B7NOLdNrZTemSKPfHzX+9IMIZ5CfbEruxkI7dFqood4g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=mPmutJfhcmf6SFLm/CvIM3h6N2/yej5FEkav/KOwn0Y=; b=nlzp/cyF06HGpTYxU3CUJZoGaSn4eh0E+XimxkeZiu+vRrmvKUB3N38qz4QAgiuqS6iLIIN0v2CmiMxgyGPSVxkNMLvKhILFOUsIJrbTyuZBxfe1DJqFPytCM93PtuT1U8TPbOSlbuRE8C6S1TO1GJDUz6khu4Kj3b9W9uz5zN0GwoaqaySnmFVAgj7KPsGj8oXIxbCphR1hU9c/z5fSd0YPQblQAadllyp8TFZxBthr84gioGVanmJgQUhIfG3rLDojTHxUPfNsAl8IFKo94yfj/1mW5tj5MqlOdlTmFMXjkRsMkKfj8KYFc+yaLyQEhL4E1Sj6xDC0y3ep62NbLg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=hotmail.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=mPmutJfhcmf6SFLm/CvIM3h6N2/yej5FEkav/KOwn0Y=; b=vFEgJJKvxXrvE6mIUaa/bq22y6aAgjfwBX/e9MKpfuwBTdPeMPZDQjQoL+B/f2Q7Dd726nj8XCAliirpva3ja7l1ma2sYxPrVezN9HdCo0wiWS3T/QkWFVl5ZeeA2eLBXRk1eBm38d38jut+te49NKoz3mys8bkQwFbwAJ4PWEe62TRJlNDZmVvU6O9J4BtemHGZIRlASAmx3/IKVP89GNL8fTpTHgR1gh7KVYkoJr0bbBH81BMaFM89H+KFrENqsrqpTzWaozLm4q8Ny/bs5RdW3BHZVli5srOjuqT+/YCmNp/X3wIee5Spm3FEKDreRQHgcOHpWHtukMi4h0z+Ow== Received: from DM8P223MB0365.NAMP223.PROD.OUTLOOK.COM (2603:10b6:8:b::20) by DM8P223MB0381.NAMP223.PROD.OUTLOOK.COM (2603:10b6:8:5::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4755.21; Sun, 5 Dec 2021 19:41:27 +0000 Received: from DM8P223MB0365.NAMP223.PROD.OUTLOOK.COM ([fe80::9c8d:fc63:9488:9775]) by DM8P223MB0365.NAMP223.PROD.OUTLOOK.COM ([fe80::9c8d:fc63:9488:9775%8]) with mapi id 15.20.4755.021; Sun, 5 Dec 2021 19:41:27 +0000 From: Soft Works To: "ffmpeg-devel@ffmpeg.org" Thread-Topic: [PATCH v21 03/20] avcodec/subtitles: Introduce new frame-based subtitle decoding API Thread-Index: AQHX6hAYCgLbTsgBDEyPcQX9Jh2Iew== Date: Sun, 5 Dec 2021 19:41:27 +0000 Message-ID: References: <1bdaf4de8cf369e4a28e7a5d8be2870ea5e34b39.1638733198.git.softworkz@hotmail.com> <9fdc2f3e9bedd2ade341e81095496866d786488b.1638733198.git.softworkz@hotmail.com> In-Reply-To: <9fdc2f3e9bedd2ade341e81095496866d786488b.1638733198.git.softworkz@hotmail.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-messagesentrepresentingtype: 1 x-tmn: [QDNGwSZEP9jRpNzo+DIOwcuW4cQw39ipAjLsB7Qkbuk1ODyjdWmMWOc6vJE/AnVF] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 0fa46d67-58aa-4646-80ef-08d9b8273a9f x-ms-traffictypediagnostic: DM8P223MB0381: x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: H9+cwtmI0LbVLDwjakCK0uXO2jC4X0RWf5BxG9NuWdhaFpWvGBunLnw2oTUEuKkUbbaiwNflPjy+t/g0aQr2SyiDEXPS3+DNTGmnYFq5rvrkmd3tUYGp/Qev03KGfSFpLzaqhXatax1UWZUb5LAfe7NjJHfHccckoSgn2/jYdgx82DqxPO+Dh1/Xl3UhF4vrGf8Y1+AMZab3R7RaEBQMpW/mT3Kb5Vud0SdaFoJUs3C2ebLO+t0PY4grQEI9hNh6Am7x27Rp+VdfIbLufML/AI5s2x37Z6q7kwZSDBnEZ+HdEC/u99QYH04fyyWtEjovCA/pi2sXHJ+3xvqkiLJnTOCH6an7yGzC5t3yHyLlet7ieuItmaMs/oohb/U173kLhtOB0UUd/RFhprs9RPbxLTR7W9YOsiTawt/rP8Ku0QSc5vpSKSIP7/dSBwMcg9DOKh5Zhv0o+nOs3FebqWaw8HRzCNPa7TnJWg9jHQvIWYZR7b59Z6Nonhxicfosh6xl5fa/dI6hoDkQ3G/J5mUXvSXd5/pESOW8ATmArLOuTqI9xODpEXweA8bXyCWyQhUsDO9sVbDxvrCcvb05X88xvA== x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?utf-8?q?vjcFMI5a1YR149zWTPZGYYSsgOms?= =?utf-8?q?lltkqG/DNWn3EH8yLtyiTTPD/elzg+AcfbGvXEVdURPXwWvNJz/D9NZlBTyk5KM/o?= =?utf-8?q?46iTnfZ+kHo9qjKU/S88T1djC+rclmY4lGSH1bSEIG3TmzWmeJk70FuTobGNGmkEQ?= =?utf-8?q?hJsP2dzd50Jm6iNxRNyJjWk01e7iQz7x3laUb/oe8RQNBXkG2Vyeuj6Mudg0AJH1W?= =?utf-8?q?9++yyogvbpYUCl1tb2ey+rr3DLYTVMBJ/GOEedUzKDEzwobc1PjQHJvSeOkOwmTf7?= =?utf-8?q?XBv02S0Y8thOvAO2oiR2KlqFte36F/IvcyxVMcIOxsH8sdP39pCYwBwpmFBxpsTys?= =?utf-8?q?xT/PHIc/AHt5jZuGoP+5YXe+fEFnHroBpq0XqEz+NH6dMim+qxGPfvJXbUA8zrS1C?= =?utf-8?q?NVeYbsfdeaHHgwT0HT2p8UyC49wtlBg0Bp4SUtMVYwBeQb9dbYCoqhFfEkoGAhteI?= =?utf-8?q?t89w7OQ5LCGymJMzCNO4yVPJnfxw/Y/B4QB4Gksx5W2NBhnWo6VOn4ot9rduWjat6?= =?utf-8?q?lqdMOTcO3E3oTaYzjKJJV0orjWSC+kzsJAaRhamlWssIHDa71kdMLDBQVVFWe5FRP?= =?utf-8?q?j37uSKsB20DfW+iWF1hBO1pi5upz9SIS6GCFYTuwy37BQIAi/S9PqsUnkid2JJ1Ti?= =?utf-8?q?twmY7PUuO5otA0JWJp51yOqp0W+nPr5gMzG1V2CVHYDm/VlMarKJ4JHR0O1jNDViT?= =?utf-8?q?rfyLqIWZ9egUijjCaQzTqRRQh/4qs5mWxP1luw0AZzq3MvVbzpS1nPAaRwams1pVZ?= =?utf-8?q?VR+vxc8FTjj+Zy9StRX7QKDTR5G+TsECGCCWac54yO530AdCT30OtHcDe5ffBdvWE?= =?utf-8?q?ZusvnO//pa6JvFri4RNbASna9GuaPo0ax99VGOJUmLEb+5IDIvyrcxYLI0kHMkohE?= =?utf-8?q?tcdNNrHIWauGJd9DUolaIjE/WhGGiTSiRPeHSCYszCl9vY/BlzTQdj4WXQ0mlFHNg?= =?utf-8?q?hG889OEFEtYJdvER59JRgV7mq4wk3iKoDe9psNOrBdg=3D=3D?= MIME-Version: 1.0 X-OriginatorOrg: sct-15-20-4755-11-msonline-outlook-1ff67.templateTenant X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: DM8P223MB0365.NAMP223.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-CrossTenant-Network-Message-Id: 0fa46d67-58aa-4646-80ef-08d9b8273a9f X-MS-Exchange-CrossTenant-originalarrivaltime: 05 Dec 2021 19:41:27.5984 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-rms-persistedconsumerorg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM8P223MB0381 Subject: [FFmpeg-devel] [PATCH v21 03/20] avcodec/subtitles: Introduce new frame-based subtitle decoding API X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: HjO8pGpmCx06 - Add avcodec_decode_subtitle3 which takes subtitle frames, serving as compatibility shim to legacy subtitle decoding - Add additional methods for conversion between old and new API Signed-off-by: softworkz --- doc/APIchanges | 7 ++ libavcodec/avcodec.h | 8 +- libavcodec/codec_desc.c | 11 +++ libavcodec/codec_desc.h | 8 ++ libavcodec/decode.c | 54 ++++++++++-- libavcodec/internal.h | 16 ++++ libavcodec/utils.c | 182 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 277 insertions(+), 9 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 8c63ea0311..49f1a28f71 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,13 @@ libavutil: 2021-04-27 API changes, most recent first: +2021-12-05 - xxxxxxxxxx - lavc 60.1.100 - codec_desc.h + Add avcodec_descriptor_get_subtitle_format() + +2021-12-05 - xxxxxxxxxx - lavc 60.1.100 - avcodec.h + Deprecate avsubtitle_free() + Deprecate avcodec_decode_subtitle2(), use regular decode api now + 2021-12-05 - xxxxxxxxxx - lavu 58.1.100 - frame.h Add AVMediaType field to AVFrame Add Fields for carrying subtitle data to AVFrame diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index b05c12e47e..3e734d3003 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1675,7 +1675,7 @@ typedef struct AVCodecContext { /** * Header containing style information for text subtitles. - * For SUBTITLE_ASS subtitle type, it should contain the whole ASS + * For AV_SUBTITLE_FMT_ASS subtitle type, it should contain the whole ASS * [Script Info] and [V4+ Styles] section, plus the [Events] line and * the Format line following. It shouldn't include any Dialogue line. * - encoding: Set/allocated/freed by user (before avcodec_open2()) @@ -2417,7 +2417,10 @@ int avcodec_close(AVCodecContext *avctx); * Free all allocated data in the given subtitle struct. * * @param sub AVSubtitle to free. + * + * @deprecated Use the regular frame based encode and decode APIs instead. */ +attribute_deprecated void avsubtitle_free(AVSubtitle *sub); /** @@ -2510,7 +2513,10 @@ enum AVChromaLocation avcodec_chroma_pos_to_enum(int xpos, int ypos); * must be freed with avsubtitle_free if *got_sub_ptr is set. * @param[in,out] got_sub_ptr Zero if no subtitle could be decompressed, otherwise, it is nonzero. * @param[in] avpkt The input AVPacket containing the input buffer. + * + * @deprecated Use the new decode API (avcodec_send_packet, avcodec_receive_frame) instead. */ +attribute_deprecated int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, int *got_sub_ptr, AVPacket *avpkt); diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 0974ee03de..e48e4532ba 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -3548,3 +3548,14 @@ enum AVMediaType avcodec_get_type(enum AVCodecID codec_id) const AVCodecDescriptor *desc = avcodec_descriptor_get(codec_id); return desc ? desc->type : AVMEDIA_TYPE_UNKNOWN; } + +enum AVSubtitleType avcodec_descriptor_get_subtitle_format(const AVCodecDescriptor *codec_descriptor) +{ + if(codec_descriptor->props & AV_CODEC_PROP_BITMAP_SUB) + return AV_SUBTITLE_FMT_BITMAP; + + if(codec_descriptor->props & AV_CODEC_PROP_TEXT_SUB) + return AV_SUBTITLE_FMT_ASS; + + return AV_SUBTITLE_FMT_UNKNOWN; +} diff --git a/libavcodec/codec_desc.h b/libavcodec/codec_desc.h index 126b52df47..ba68d24e0e 100644 --- a/libavcodec/codec_desc.h +++ b/libavcodec/codec_desc.h @@ -121,6 +121,14 @@ const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev); */ const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name); +/** + * Return subtitle format from a codec descriptor + * + * @param codec_descriptor codec descriptor + * @return the subtitle type (e.g. bitmap, text) + */ +enum AVSubtitleType avcodec_descriptor_get_subtitle_format(const AVCodecDescriptor *codec_descriptor); + /** * @} */ diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 52bf5dcd33..ac267f0df6 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -576,6 +576,37 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) return ret; } +static int decode_subtitle2_priv(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, AVPacket *avpkt); + +static int decode_subtitle_shim(AVCodecContext *avctx, AVFrame *frame, AVPacket *avpkt) +{ + int ret, got_sub_ptr = 0; + AVSubtitle subtitle = { 0 }; + + if (frame->buf[0]) + return AVERROR(EAGAIN); + + av_frame_unref(frame); + + ret = decode_subtitle2_priv(avctx, &subtitle, &got_sub_ptr, avpkt); + + if (ret >= 0 && got_sub_ptr) { + frame->type = AVMEDIA_TYPE_SUBTITLE; + frame->format = subtitle.format; + ret = av_frame_get_buffer2(frame, 0); + + if (ret >= 0) + ret = ff_frame_put_subtitle(frame, &subtitle); + + frame->pkt_dts = avpkt->dts; + } + + avsubtitle_free(&subtitle); + + return ret; +} + int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt) { AVCodecInternal *avci = avctx->internal; @@ -590,6 +621,9 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke if (avpkt && !avpkt->size && avpkt->data) return AVERROR(EINVAL); + if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) + return decode_subtitle_shim(avctx, avci->buffer_frame, avpkt); + av_packet_unref(avci->buffer_pkt); if (avpkt && (avpkt->data || avpkt->side_data_elems)) { ret = av_packet_ref(avci->buffer_pkt, avpkt); @@ -651,7 +685,9 @@ int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *fr if (avci->buffer_frame->buf[0]) { av_frame_move_ref(frame, avci->buffer_frame); - } else { + } else if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) + return AVERROR(EAGAIN); + else { ret = decode_receive_frame_internal(avctx, frame); if (ret < 0) return ret; @@ -802,9 +838,8 @@ static int utf8_check(const uint8_t *str) return 1; } -int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, - int *got_sub_ptr, - AVPacket *avpkt) +static int decode_subtitle2_priv(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, AVPacket *avpkt) { int ret = 0; @@ -844,10 +879,7 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, avctx->pkt_timebase, ms); } - if (avctx->codec_descriptor->props & AV_CODEC_PROP_BITMAP_SUB) - sub->format = 0; - else if (avctx->codec_descriptor->props & AV_CODEC_PROP_TEXT_SUB) - sub->format = 1; + sub->format = avcodec_descriptor_get_subtitle_format(avctx->codec_descriptor); for (unsigned i = 0; i < sub->num_rects; i++) { if (avctx->sub_charenc_mode != FF_SUB_CHARENC_MODE_IGNORE && @@ -871,6 +903,12 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, return ret; } +int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, AVPacket *avpkt) +{ + return decode_subtitle2_priv(avctx, sub, got_sub_ptr, avpkt); +} + enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *avctx, const enum AVPixelFormat *fmt) { diff --git a/libavcodec/internal.h b/libavcodec/internal.h index a62f8dbd4e..10443ed2d1 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -363,6 +363,22 @@ int ff_int_from_list_or_default(void *ctx, const char * val_name, int val, void ff_dvdsub_parse_palette(uint32_t *palette, const char *p); +/** + * Copies subtitle data from AVSubtitle to AVFrame. + * + * @deprecated This is a compatibility method for interoperability with + * the legacy subtitle API. + */ +int ff_frame_put_subtitle(AVFrame* frame, const AVSubtitle* sub); + +/** + * Copies subtitle data from AVFrame to AVSubtitle. + * + * @deprecated This is a compatibility method for interoperability with + * the legacy subtitle API. + */ +int ff_frame_get_subtitle(AVSubtitle* sub, AVFrame* frame); + #if defined(_WIN32) && CONFIG_SHARED && !defined(BUILDING_avcodec) # define av_export_avcodec __declspec(dllimport) #else diff --git a/libavcodec/utils.c b/libavcodec/utils.c index a91a54b0dc..613c580c19 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -824,6 +824,188 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes) return FFMAX(0, duration); } +static int subtitle_area2rect(AVSubtitleRect *dst, const AVSubtitleArea *src) +{ + dst->x = src->x; + dst->y = src->y; + dst->w = src->w; + dst->h = src->h; + dst->nb_colors = src->nb_colors; + dst->type = src->type; + dst->flags = src->flags; + + switch (dst->type) { + case AV_SUBTITLE_FMT_BITMAP: + + if (src->h > 0 && src->w > 0 && src->buf[0]) { + uint32_t *pal; + AVBufferRef *buf = src->buf[0]; + dst->data[0] = av_mallocz(buf->size); + memcpy(dst->data[0], buf->data, buf->size); + dst->linesize[0] = src->linesize[0]; + + dst->data[1] = av_mallocz(256 * 4); + pal = (uint32_t *)dst->data[1]; + + for (unsigned i = 0; i < 256; i++) { + pal[i] = src->pal[i]; + } + } + + break; + case AV_SUBTITLE_FMT_TEXT: + + if (src->text) + dst->text = av_strdup(src->text); + else + dst->text = av_strdup(""); + + if (!dst->text) + return AVERROR(ENOMEM); + + break; + case AV_SUBTITLE_FMT_ASS: + + if (src->ass) + dst->ass = av_strdup(src->ass); + else + dst->ass = av_strdup(""); + + if (!dst->ass) + return AVERROR(ENOMEM); + + break; + default: + + av_log(NULL, AV_LOG_ERROR, "Subtitle rect has invalid format: %d", dst->type); + return AVERROR(EINVAL); + } + + return 0; +} + +static int subtitle_rect2area(AVSubtitleArea *dst, const AVSubtitleRect *src) +{ + dst->x = src->x; + dst->y = src->y; + dst->w = src->w; + dst->h = src->h; + dst->nb_colors = src->nb_colors; + dst->type = src->type; + dst->flags = src->flags; + + switch (dst->type) { + case AV_SUBTITLE_FMT_BITMAP: + + if (src->h > 0 && src->w > 0 && src->data[0]) { + AVBufferRef *buf = av_buffer_allocz(src->h * src->linesize[0]); + memcpy(buf->data, src->data[0], buf->size); + + dst->buf[0] = buf; + dst->linesize[0] = src->linesize[0]; + } + + if (src->data[1]) { + uint32_t *pal = (uint32_t *)src->data[1]; + + for (unsigned i = 0; i < 256; i++) { + dst->pal[i] = pal[i]; + } + } + + break; + case AV_SUBTITLE_FMT_TEXT: + + if (src->text) { + dst->text = av_strdup(src->text); + if (!dst->text) + return AVERROR(ENOMEM); + } + + break; + case AV_SUBTITLE_FMT_ASS: + + if (src->ass) { + dst->ass = av_strdup(src->ass); + if (!dst->ass) + return AVERROR(ENOMEM); + } + + break; + default: + + av_log(NULL, AV_LOG_ERROR, "Subtitle area has invalid format: %d", dst->type); + return AVERROR(EINVAL); + } + + return 0; +} + +/** + * Copies subtitle data from AVSubtitle (deprecated) to AVFrame + * + * @note This is a compatibility method for conversion to the legacy API + */ +int ff_frame_put_subtitle(AVFrame *frame, const AVSubtitle *sub) +{ + frame->format = sub->format; + frame->subtitle_start_time = sub->start_display_time; + frame->subtitle_end_time = sub->end_display_time; + frame->subtitle_pts = sub->pts; + + if (sub->num_rects) { + frame->subtitle_areas = av_malloc_array(sub->num_rects, sizeof(AVSubtitleArea*)); + if (!frame->subtitle_areas) + return AVERROR(ENOMEM); + + for (unsigned i = 0; i < sub->num_rects; i++) { + int ret; + frame->subtitle_areas[i] = av_mallocz(sizeof(AVSubtitleArea)); + if (!frame->subtitle_areas[i]) + return AVERROR(ENOMEM); + ret = subtitle_rect2area(frame->subtitle_areas[i], sub->rects[i]); + if (ret < 0) { + frame->num_subtitle_areas = i; + return ret; + } + } + } + + frame->num_subtitle_areas = sub->num_rects; + return 0; +} + +/** + * Copies subtitle data from AVFrame to AVSubtitle (deprecated) + * + * @note This is a compatibility method for conversion to the legacy API + */ +int ff_frame_get_subtitle(AVSubtitle *sub, AVFrame *frame) +{ + sub->start_display_time = frame->subtitle_start_time; + sub->end_display_time = frame->subtitle_end_time; + sub->pts = frame->subtitle_pts; + + if (frame->num_subtitle_areas) { + sub->rects = av_malloc_array(frame->num_subtitle_areas, sizeof(AVSubtitleRect*)); + if (!sub->rects) + return AVERROR(ENOMEM); + + for (unsigned i = 0; i < frame->num_subtitle_areas; i++) { + int ret; + sub->rects[i] = av_mallocz(sizeof(AVSubtitleRect)); + ret = subtitle_area2rect(sub->rects[i], frame->subtitle_areas[i]); + if (ret < 0) { + sub->num_rects = i; + return ret; + } + } + } + + sub->num_rects = frame->num_subtitle_areas; + return 0; +} + int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes) { int duration = get_audio_frame_duration(par->codec_id, par->sample_rate,