From patchwork Wed Mar 6 07:19:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marth64 X-Patchwork-Id: 46831 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:d90e:b0:19e:cdac:8cce with SMTP id jd14csp224861pzb; Tue, 5 Mar 2024 23:21:06 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCUye/md5oxQuuPk7qz6na3rWuaGHnoMEceZm/fJ6A1gJ5ANol6AcmSgtcFRYSHgceLUfKYXFRE0v4yD5TG1pahEIe9pUK4btJot/Q== X-Google-Smtp-Source: AGHT+IEhoLWu7YWP4Qdz9Nfe7R0extvv3BknrQ9D53RwtI0SzUY49RBO1oLUISBvPvyC89fJkgI5 X-Received: by 2002:a05:6402:202e:b0:565:9ac6:a9e5 with SMTP id ay14-20020a056402202e00b005659ac6a9e5mr11171784edb.21.1709709666313; Tue, 05 Mar 2024 23:21:06 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1709709666; cv=none; d=google.com; s=arc-20160816; b=C2BYdfD50gB8TmVinOEz44iBgKtXcp+kXVSFzcM0VkHVVDtqIWpKNbcHOWqb2EJ9Qr sN1OUO9yh+Uci6/Z/tiGlpAkAJRmyRaC40mVRHhCTLxtg+Rz0xqsQX23RDOuymi3LJAB T03WzLvdVJ9NzwOCwfZ3DBH1c0qHPKRd9E/W2byWuxWULI5x6x39Xm5eBtnjUgAtb2JH ENZMVRFVJXZf+4ci+M5uleoDMYtDHsBeur59+qLwGYhV4OIdLS9tFSb4yrIKNoy7b2GP eGvwIqHSblyJXhBHocWL61rWmyfnrN1hnG9m/DnEepyWAISeWkz16rIfEatJaHrRdCY5 jTAg== 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; bh=EsCV0A5ldytxzOqgts7LNUmdLaFv3FWO06hhTq0tcGw=; fh=PlWMzmI9LD2qGS7ipLrQl8z0iaQTLQLHzoGuXcBzpCg=; b=cdhBT6HcTkbkPc5hVsPArshqFS7+IhB1HzU78DZl9tD4g6EM2JKEyNtAGQ+WjQA//7 lqK4j24WnOD3p0RzsLid5XHIh9c2e4jeeG7y/P7q+YQnI1iRDoN8Qh963VbJd+Y1vykn 10FNXeuvoaD2ymqqTHBdmqat2aeBiSD7IVqzfiFN69qDUBafM2xlcKkFU8+buWczmv71 /xUsyeoSt2k2TPv9RRSxDtcM4+1BbSDgSW/qUq8L75QLQ/lt6l/uni+cMwi/yIyRrF4w bkx1pV5BrBlGXS/f42tQMUxJdOiRdlFTD5Jc0id/9fJrTEyk0Mg6v1KmaxhYSLfYPPhP c1VA==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@proxyid.net header.s=google header.b=Ccgx89nr; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id q17-20020a056402519100b00565ff637724si5820756edd.91.2024.03.05.23.21.05; Tue, 05 Mar 2024 23:21:06 -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=@proxyid.net header.s=google header.b=Ccgx89nr; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 4A01F68CB6E; Wed, 6 Mar 2024 09:20:52 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-oi1-f228.google.com (mail-oi1-f228.google.com [209.85.167.228]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 3879468C3D2 for ; Wed, 6 Mar 2024 09:20:44 +0200 (EET) Received: by mail-oi1-f228.google.com with SMTP id 5614622812f47-3c1a2f7e1d2so3844371b6e.1 for ; Tue, 05 Mar 2024 23:20:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=proxyid.net; s=google; t=1709709641; x=1710314441; darn=ffmpeg.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=Po6QVK/XJr7QJip7nB+sDc8m8J2YAegAFAv4kjgJhrM=; b=Ccgx89nrad6kcJgp+pGFS36EL4qwefn2EE7zSMUZcJUFY1fXKcUWUi2GCdQdC7SRlg xkr1AAPnD6wpl+XtcykleX4XbhbZhBw1RTrS7cTy+8bVFeszBHRw1i1sHw5fEchg6PRs 9V8VKeC1O91skkBxmxk5SyJhh7P/I8mjBu8hxkyM031XN/iTAfBZHL1iIQD6eLJTfLY7 R2vCTmr5oJKloLPfVkLh5K2UTYgsviG04gNiEy0s6pq+fLEmI9p/odzFdKmjtVs676gL 4Y3e+WBJAWfCrtF+K7Bzm1CWquxvbb2Ipb97bwJZ+3IJDpioSAOCc+RYwTQ0uTQP0xT9 hdWA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709709641; x=1710314441; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Po6QVK/XJr7QJip7nB+sDc8m8J2YAegAFAv4kjgJhrM=; b=Ju9t7nwijrueN4ptlCFnOnJgGedUWvQJtHskYQkX275mrdbJDkVxnl+xren7AITDU6 4K2YbYRmTlCGwspYYbzJM/SG05zKoFVxnIgrd6FKY0mZHya2iCj9piktdDKkQ1CEBmiX zxL5Xk8MbsK3t/GDOmtkpicCFz6wNrt1AmGDcGd1Ynbhnqm9CwqwqwhzmyL+l/oLLTqi QtgDoj1t7ivy9uqchaOMFbuu9HvfY64yP8tBfd9i1DQokQvXN6+jIk+319otwx+bY+Qr uq52WEr0q4cSBDWlKQWrTG45fRqo1Gl82Wfz7+wU40q9oWj1SyVQHd328rLazUQqX7fA vW+Q== X-Gm-Message-State: AOJu0YyaRiZrzz9IInW0h/7jiiXqfIeHuahig9+zPDs9zn69fOGhVFrn iOPcEe3UNinq5e9rx9eBfiiRE2uAfruRAbqkZrfHmvdQqCprDwRWI0HbRFkXg8TzMh7IDQMjPT4 tU+PNSZ9o/4Q/lGhCRLeJWg7uCyySNzNiuFiCVOFW X-Received: by 2002:aca:f01:0:b0:3c1:dbd5:fc39 with SMTP id 1-20020aca0f01000000b003c1dbd5fc39mr4005601oip.31.1709709641418; Tue, 05 Mar 2024 23:20:41 -0800 (PST) Received: from wsx-cc1-001.. (c-76-141-249-38.hsd1.il.comcast.net. [76.141.249.38]) by smtp-relay.gmail.com with ESMTPS id s5-20020a63ff45000000b005dc846d791csm553686pgk.14.2024.03.05.23.20.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 23:20:41 -0800 (PST) X-Relaying-Domain: proxyid.net From: Marth64 To: ffmpeg-devel@ffmpeg.org Date: Wed, 6 Mar 2024 01:19:11 -0600 Message-Id: <20240306071913.2735832-1-marth64@proxyid.net> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/3] avformat/dvdvideodec: add CLUT utilities and subtitle palette support 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 Cc: Marth64 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: AT7SxZTUJtU4 Since last iteration: removes unused variable in dvdclut.c Signed-off-by: Marth64 --- doc/demuxers.texi | 5 +++ libavformat/Makefile | 2 +- libavformat/dvdclut.c | 75 +++++++++++++++++++++++++++++++++++++++ libavformat/dvdclut.h | 37 +++++++++++++++++++ libavformat/dvdvideodec.c | 15 ++++++++ 5 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 libavformat/dvdclut.c create mode 100644 libavformat/dvdclut.h diff --git a/doc/demuxers.texi b/doc/demuxers.texi index f4bac8f3b3..1a17c6db16 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -394,6 +394,11 @@ often with junk data intended for controlling a real DVD player's buffering speed and with no other material data value. Default is 1, true. +@item clut_rgb @var{bool} +Output subtitle palettes (CLUTs) as RGB, required for Matroska. +Disable to output the palette in its original YUV colorspace. +Default is 1, true. + @end table @subsection Examples diff --git a/libavformat/Makefile b/libavformat/Makefile index 8811a0ffc9..a3bfc209c3 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -194,7 +194,7 @@ OBJS-$(CONFIG_DTS_MUXER) += rawenc.o OBJS-$(CONFIG_DV_MUXER) += dvenc.o OBJS-$(CONFIG_DVBSUB_DEMUXER) += dvbsub.o rawdec.o OBJS-$(CONFIG_DVBTXT_DEMUXER) += dvbtxt.o rawdec.o -OBJS-$(CONFIG_DVDVIDEO_DEMUXER) += dvdvideodec.o +OBJS-$(CONFIG_DVDVIDEO_DEMUXER) += dvdvideodec.o dvdclut.o OBJS-$(CONFIG_DXA_DEMUXER) += dxa.o OBJS-$(CONFIG_EA_CDATA_DEMUXER) += eacdata.o OBJS-$(CONFIG_EA_DEMUXER) += electronicarts.o diff --git a/libavformat/dvdclut.c b/libavformat/dvdclut.c new file mode 100644 index 0000000000..cd4b103e4b --- /dev/null +++ b/libavformat/dvdclut.c @@ -0,0 +1,75 @@ +/* + * DVD-Video subpicture CLUT (Color Lookup Table) utilities + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/bprint.h" +#include "libavutil/colorspace.h" +#include "libavutil/common.h" + +#include "dvdclut.h" +#include "internal.h" + +int ff_dvdclut_palette_extradata_cat(const uint32_t *clut, + const size_t clut_size, + AVCodecParameters *par) +{ + AVBPrint bp; + + if (clut_size != FF_DVDCLUT_CLUT_SIZE) + return AVERROR(EINVAL); + + av_bprint_init(&bp, 0, FF_DVDCLUT_EXTRADATA_SIZE); + + av_bprintf(&bp, "palette: "); + + for (int i = 0; i < FF_DVDCLUT_CLUT_LEN; i++) + av_bprintf(&bp, "%06"PRIx32"%s", clut[i], + i != (FF_DVDCLUT_CLUT_LEN - 1) ? ", " : ""); + + av_bprintf(&bp, "\n"); + + return ff_bprint_to_codecpar_extradata(par, &bp); +} + +int ff_dvdclut_yuv_to_rgb(uint32_t *clut, const size_t clut_size) +{ + int y, cb, cr; + uint8_t r, g, b; + int r_add, g_add, b_add; + + if (clut_size != FF_DVDCLUT_CLUT_SIZE) + return AVERROR(EINVAL); + + for (int i = 0; i < FF_DVDCLUT_CLUT_LEN; i++) { + y = (clut[i] >> 16) & 0xFF; + cr = (clut[i] >> 8) & 0xFF; + cb = clut[i] & 0xFF; + + YUV_TO_RGB1_CCIR(cb, cr); + + y = (y - 16) * FIX(255.0 / 219.0); + r = av_clip_uint8((y + r_add - 1024) >> SCALEBITS); + g = av_clip_uint8((y + g_add - 1024) >> SCALEBITS); + b = av_clip_uint8((y + b_add - 1024) >> SCALEBITS); + + clut[i] = (r << 16) | (g << 8) | b; + } + + return 0; +} diff --git a/libavformat/dvdclut.h b/libavformat/dvdclut.h new file mode 100644 index 0000000000..41cea7e2c9 --- /dev/null +++ b/libavformat/dvdclut.h @@ -0,0 +1,37 @@ +/* + * DVD-Video subpicture CLUT (Color Lookup Table) utilities + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_DVDCLUT_H +#define AVFORMAT_DVDCLUT_H + +#include "libavcodec/codec_par.h" + +/* ("palette: ") + ("rrggbb, "*15) + ("rrggbb") + \n + \0 */ +#define FF_DVDCLUT_EXTRADATA_SIZE (9 + (8 * 15) + 6 + 1 + 1) +#define FF_DVDCLUT_CLUT_LEN 16 +#define FF_DVDCLUT_CLUT_SIZE FF_DVDCLUT_CLUT_LEN * sizeof(uint32_t) + +int ff_dvdclut_palette_extradata_cat(const uint32_t *clut, + const size_t clut_size, + AVCodecParameters *par); + +int ff_dvdclut_yuv_to_rgb(uint32_t *clut, const size_t clut_size); + +#endif /* AVFORMAT_DVDCLUT_H */ diff --git a/libavformat/dvdvideodec.c b/libavformat/dvdvideodec.c index b83ae0c2a5..3bc76f5c65 100644 --- a/libavformat/dvdvideodec.c +++ b/libavformat/dvdvideodec.c @@ -49,6 +49,7 @@ #include "avio_internal.h" #include "avlanguage.h" #include "demux.h" +#include "dvdclut.h" #include "internal.h" #include "url.h" @@ -95,6 +96,7 @@ typedef struct DVDVideoPGCSubtitleStreamEntry { int startcode; enum DVDVideoSubpictureViewport viewport; int disposition; + uint32_t clut[FF_DVDCLUT_CLUT_LEN]; const char *lang_iso; } DVDVideoPGCSubtitleStreamEntry; @@ -128,6 +130,7 @@ typedef struct DVDVideoDemuxContext { int opt_angle; /* the user-provided angle number (1-indexed) */ int opt_chapter_end; /* the user-provided exit PTT (0 for last) */ int opt_chapter_start; /* the user-provided entry PTT (1-indexed) */ + int opt_clut_rgb; /* output subtitle palette (CLUT) as RGB */ int opt_pg; /* the user-provided PG number (1-indexed) */ int opt_pgc; /* the user-provided PGC number (1-indexed) */ int opt_preindex; /* pre-indexing mode (2-pass read) */ @@ -1038,6 +1041,8 @@ break_error: static int dvdvideo_subp_stream_analyze(AVFormatContext *s, uint32_t offset, subp_attr_t subp_attr, DVDVideoPGCSubtitleStreamEntry *entry) { + DVDVideoDemuxContext *c = s->priv_data; + char lang_dvd[3] = {0}; entry->startcode = 0x20 + (offset & 0x1F); @@ -1045,6 +1050,11 @@ static int dvdvideo_subp_stream_analyze(AVFormatContext *s, uint32_t offset, sub if (subp_attr.lang_extension == 9) entry->disposition |= AV_DISPOSITION_FORCED; + memcpy(&entry->clut, c->play_state.pgc->palette, FF_DVDCLUT_CLUT_SIZE); + + if (c->opt_clut_rgb) + ff_dvdclut_yuv_to_rgb(entry->clut, FF_DVDCLUT_CLUT_SIZE); + AV_WB16(lang_dvd, subp_attr.lang_code); entry->lang_iso = ff_convert_lang_to(lang_dvd, AV_LANG_ISO639_2_BIBL); @@ -1056,6 +1066,7 @@ static int dvdvideo_subp_stream_add(AVFormatContext *s, DVDVideoPGCSubtitleStrea { AVStream *st; FFStream *sti; + int ret; st = avformat_new_stream(s, NULL); if (!st) @@ -1065,6 +1076,9 @@ static int dvdvideo_subp_stream_add(AVFormatContext *s, DVDVideoPGCSubtitleStrea st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codecpar->codec_id = AV_CODEC_ID_DVD_SUBTITLE; + if ((ret = ff_dvdclut_palette_extradata_cat(entry->clut, FF_DVDCLUT_CLUT_SIZE, st->codecpar)) < 0) + return ret; + if (entry->lang_iso) av_dict_set(&st->metadata, "language", entry->lang_iso, 0); @@ -1373,6 +1387,7 @@ static const AVOption dvdvideo_options[] = { {"angle", "playback angle number", OFFSET(opt_angle), AV_OPT_TYPE_INT, { .i64=1 }, 1, 9, AV_OPT_FLAG_DECODING_PARAM }, {"chapter_end", "exit chapter (PTT) number (0=end)", OFFSET(opt_chapter_end), AV_OPT_TYPE_INT, { .i64=0 }, 0, 99, AV_OPT_FLAG_DECODING_PARAM }, {"chapter_start", "entry chapter (PTT) number", OFFSET(opt_chapter_start), AV_OPT_TYPE_INT, { .i64=1 }, 1, 99, AV_OPT_FLAG_DECODING_PARAM }, + {"clut_rgb", "output subtitle palette (CLUT) as RGB", OFFSET(opt_clut_rgb), AV_OPT_TYPE_BOOL, { .i64=1 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, {"pg", "entry PG number (0=auto)", OFFSET(opt_pg), AV_OPT_TYPE_INT, { .i64=0 }, 0, 255, AV_OPT_FLAG_DECODING_PARAM }, {"pgc", "entry PGC number (0=auto)", OFFSET(opt_pgc), AV_OPT_TYPE_INT, { .i64=0 }, 0, 999, AV_OPT_FLAG_DECODING_PARAM }, {"preindex", "enable for accurate chapter markers, slow (2-pass read)", OFFSET(opt_preindex), AV_OPT_TYPE_BOOL, { .i64=0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, From patchwork Wed Mar 6 07:19:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marth64 X-Patchwork-Id: 46830 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:d90e:b0:19e:cdac:8cce with SMTP id jd14csp224808pzb; Tue, 5 Mar 2024 23:20:56 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCWlkM4hYX+sWkalaMz0FkM4IKN9YSx0f6woUO5GiXa20mDxRSDWTu4K4SvVQT02Abvi2jIvaefwlf4hyqGlTaGjtRJCsNtEtlaiWA== X-Google-Smtp-Source: AGHT+IFiUB7Fvz5u49XvShJPrzADwXzsDHz2RLfkTuBQPFGofltav7+GlUrf1LF2pFpqxiXVpKUA X-Received: by 2002:a17:906:408d:b0:a45:69f5:c3c9 with SMTP id u13-20020a170906408d00b00a4569f5c3c9mr4960200ejj.6.1709709655773; Tue, 05 Mar 2024 23:20:55 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1709709655; cv=none; d=google.com; s=arc-20160816; b=DPwW5RA3HkBigq5CZMAPfBLk/DQvxSHhN1/eKrXkHeqilMF4FdxJAUfIlRyW/DtvaJ AJPWvH24l5HVvYyQXm8dy5Z3cIRQFTQgJsnv6Z1hvgBMVGzx3OvJH2aKnyhqkJdBV+70 46+ucKmxOlBMh8ptLyyThv/XwZiksrlo3O6f05bI1KRSkJwqto4Nv0m8YzoubWB/BmpX 8GvOlJb6aw50zwbaNMnuEfrUHBl+CU0tdCznpHGQgCALgdj2H2+a82hFPo9ZR2jxB1vz 0KWFusARDY5k5Z15LSl0rULN9M0dvZkVuA+sTFirnvftWLwRdJo4jun2v8gmCQCezJi2 Ymnw== 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:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=ojIuoKTsxay8h0WieQO9DVmSpIDowF3kJ/RmOaChB/8=; fh=PlWMzmI9LD2qGS7ipLrQl8z0iaQTLQLHzoGuXcBzpCg=; b=HzJYz2GnFoQU6XOKXZirFJtT5k6yU4gMZW8wtEExMmHyVJE9ha/5hJnAZPnX2/uds8 pN3ySHT8cXNIQp78Won2dT7JmNNfxn1cC3L9NmxHmag3Hdw6xbdlZYtGDc5X/po3VWyX q5cUf3QCu0l3K/CIJ+4KgtXv77SuxiRx2fvdpe9jYc4iAT5Ual++5tIf4BeKpNixTynC t6vhxwvuHximXaUmeK4H8EIVomdKaWXN/OF5wostfzIU3Qlg/cPaaveQ/vWhfJlJ8UAd R6HRxFvvzgrFJQvHtH4xjvwtHNtFNvrJCZsJw8/bxPPy03h2aOaaZwCNuebQ0m6zoFYN 4xfg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@proxyid.net header.s=google header.b=Cdrzlfp0; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id i16-20020aa7dd10000000b00567f8e54aa7si32900edv.247.2024.03.05.23.20.54; Tue, 05 Mar 2024 23:20:55 -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=@proxyid.net header.s=google header.b=Cdrzlfp0; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1789768CBBC; Wed, 6 Mar 2024 09:20:51 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-oi1-f228.google.com (mail-oi1-f228.google.com [209.85.167.228]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 39E8368C446 for ; Wed, 6 Mar 2024 09:20:44 +0200 (EET) Received: by mail-oi1-f228.google.com with SMTP id 5614622812f47-3bbbc6e51d0so4584291b6e.3 for ; Tue, 05 Mar 2024 23:20:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=proxyid.net; s=google; t=1709709642; x=1710314442; darn=ffmpeg.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1A7v6DeyhWHc70QKw0u6ley+3bNzBM3uzP+fA6bxb+A=; b=Cdrzlfp0UcudppTjcaI5CPdAqYThUHFHab1wmT7K49cQjbWLt/WX61fa3HYerM4gN3 8S3TqIbBWC7lpraanHM/lpo6W83rkF6gDl7wG3Nu0FsKmX+JxqiMX7MG6yEZLQAqXeh1 GXAkMHZ3Yf0QVq/XpV5PjrNskvu/b9fKy0jzBNeB3NvUZ0VlbGswgOP9ee7D+bbQEZo2 qMrvNYtDRHI3NvAWZHsl84LXoQhq7G89dNMrbUkgXjSbYkbmgeW30N3AYkoKBKZpSzxm x55V/OLBluBvFTkRzKW5EAf1QqKcIDLNhGdd0li7IhyiKvr13ldxLIVRhNI5qJ0w7+r9 opnA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709709642; x=1710314442; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=1A7v6DeyhWHc70QKw0u6ley+3bNzBM3uzP+fA6bxb+A=; b=LslaN7G1EE3stISGgIPQiFyg3IWio9plcoc4esKeBvuBxDLjh/EhAbWmAY5XQ/Znni fm87l2dSSrvtJKv9wfp1Hp0xbOyyWDy0b8ett4Xf7iXxBo0GMoogfiB45rQzWFolwgcY hMzc54jG1doGCO20hjpohDIgjk53Rnr195u93x3jaP6gpJgIVUvYjcxY7AutKBPeCpqW R+EvK1aPITMfNMP27BANz9vv6DUlRmp12QfTvMW+2qqHPWj8ldkV+zP+ikhJvrr606eD 9Fozx9KZ/LHKE5fR4V9y8JMUIHdZHO3KTCen3/n0/31QlzKIpVIOdxzfbmLKvM6cAuqJ NLjw== X-Gm-Message-State: AOJu0YyQFM/a51whUqNC8QIyZbDyNNG63TDL8EKLlPsV42BO61zxqz7c Bxsr6CM+B0eC4r0dPxpNG9/A2uDkyqQ1cgBVwahOQyz7MwjYv7H8YNNh5JtkePq99AWcoJmnDkO JZo1WO1q+VeuxW8pmJAopYKnKvOMgUaclMfHSow2S X-Received: by 2002:a05:6808:1a83:b0:3c2:16f2:2e5a with SMTP id bm3-20020a0568081a8300b003c216f22e5amr2216741oib.4.1709709641981; Tue, 05 Mar 2024 23:20:41 -0800 (PST) Received: from wsx-cc1-001.. (c-76-141-249-38.hsd1.il.comcast.net. [76.141.249.38]) by smtp-relay.gmail.com with ESMTPS id s5-20020a63ff45000000b005dc846d791csm553686pgk.14.2024.03.05.23.20.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 23:20:41 -0800 (PST) X-Relaying-Domain: proxyid.net From: Marth64 To: ffmpeg-devel@ffmpeg.org Date: Wed, 6 Mar 2024 01:19:12 -0600 Message-Id: <20240306071913.2735832-2-marth64@proxyid.net> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240306071913.2735832-1-marth64@proxyid.net> References: <20240306071913.2735832-1-marth64@proxyid.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/3] avformat/dvdvideodec: add menu demuxing support 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 Cc: Marth64 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: vEh1IexwHjX7 Many DVDs have valuable assets in their menu structures, including background video or music. Some discs also abuse the menu feature to include actual feature footage that needs to change aspect ratio (in order to trick the DVD player). This patch allows extraction and archival of these assets, but does not enable controllable playback (which needs a full-fledged player and nav VM). Menus are processed directly with dvdread and the existing foundation of the demuxer. Will eventually add option to list their coordinates as well, so users do not have to rely on other tools to find them. Signed-off-by: Marth64 --- doc/demuxers.texi | 43 +++++- libavformat/dvdvideodec.c | 315 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 339 insertions(+), 19 deletions(-) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index 1a17c6db16..e2ea66c1a5 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -289,8 +289,10 @@ This demuxer accepts the following option: DVD-Video demuxer, powered by libdvdnav and libdvdread. -Can directly ingest DVD titles, specifically sequential PGCs, -into a conversion pipeline. Menus and seeking are not supported at this time. +Can directly ingest DVD titles, specifically sequential PGCs, into +a conversion pipeline. Menu assets, such as background video or audio, +can also be demuxed given the menu's coordinates (at best effort). +Seeking is not supported at this time. Block devices (DVD drives), ISO files, and directory structures are accepted. Activate with @code{-f dvdvideo} in front of one of these inputs. @@ -347,37 +349,56 @@ This demuxer accepts the following options: @item title @var{int} The title number to play. Must be set if @option{pgc} and @option{pg} are not set. +Not applicable to menus. Default is 0 (auto), which currently only selects the first available title (title 1) and notifies the user about the implications. @item chapter_start @var{int} -The chapter, or PTT (part-of-title), number to start at. Default is 1. +The chapter, or PTT (part-of-title), number to start at. Not applicable to menus. +Default is 1. @item chapter_end @var{int} -The chapter, or PTT (part-of-title), number to end at. Default is 0, -which is a special value to signal end at the last possible chapter. +The chapter, or PTT (part-of-title), number to end at. Not applicable to menus. +Default is 0, which is a special value to signal end at the last possible chapter. @item angle @var{int} The video angle number, referring to what is essentially an additional video stream that is composed from alternate frames interleaved in the VOBs. +Not applicable to menus. Default is 1. @item region @var{int} The region code to use for playback. Some discs may use this to default playback at a particular angle in different regions. This option will not affect the region code -of a real DVD drive, if used as an input. Default is 0, "world". +of a real DVD drive, if used as an input. Not applicable to menus. +Default is 0, "world". + +@item menu @var{bool} +Demux menu assets instead of navigating a title. Requires exact coordinates +of the menu (@option{menu_lu}, @option{menu_vts}, @option{pgc}, @option{pg}). +Default is false. + +@item menu_lu @var{int} +The menu language to demux. In DVD, menus are grouped by language. +Default is 0, the first language unit. + +@item menu_vts @var{int} +The VTS where the menu lives, or 0 if it is a VMG menu (root-level). +Default is 0, VMG menu. @item pgc @var{int} The entry PGC to start playback, in conjunction with @option{pg}. Alternative to setting @option{title}. Chapter markers are not supported at this time. +Must be explicitly set for menus. Default is 0, automatically resolve from value of @option{title}. @item pg @var{int} The entry PG to start playback, in conjunction with @option{pgc}. Alternative to setting @option{title}. Chapter markers are not supported at this time. -Default is 0, automatically resolve from value of @option{title}. +Default is 0, automatically resolve from value of @option{title}, or +start from the beginning (PG 1) of the menu. @item preindex @var{bool} Enable this to have accurate chapter (PTT) markers and duration measurement, @@ -385,6 +406,7 @@ which requires a slow second pass read in order to index the chapter marker timestamps from NAV packets. This is non-ideal extra work for real optical drives. It is recommended and faster to use this option with a backup of the DVD structure stored on a hard drive. Not compatible with @option{pgc} and @option{pg}. +Not applicable to menus. Default is 0, false. @item trim @var{bool} @@ -392,6 +414,7 @@ Skip padding cells (i.e. cells shorter than 1 second) from the beginning. There exist many discs with filler segments at the beginning of the PGC, often with junk data intended for controlling a real DVD player's buffering speed and with no other material data value. +Not applicable to menus. Default is 1, true. @item clut_rgb @var{bool} @@ -421,6 +444,12 @@ Open only chapter 5 from title 1 from a given DVD structure: @example ffmpeg -f dvdvideo -chapter_start 5 -chapter_end 5 -title 1 -i ... @end example + +@item +Demux menu with language 1 from VTS 1, PGC 1, starting at PG 1: +@example +ffmpeg -f dvdvideo -menu 1 -menu_lu 1 -menu_vts 1 -pgc 1 -pg 1 -i ... +@end example @end itemize @section ea diff --git a/libavformat/dvdvideodec.c b/libavformat/dvdvideodec.c index 3bc76f5c65..2c7ffdd148 100644 --- a/libavformat/dvdvideodec.c +++ b/libavformat/dvdvideodec.c @@ -57,9 +57,11 @@ #define DVDVIDEO_BLOCK_SIZE 2048 #define DVDVIDEO_TIME_BASE_Q (AVRational) { 1, 90000 } #define DVDVIDEO_PTS_WRAP_BITS 64 /* VOBUs use 32 (PES allows 33) */ - #define DVDVIDEO_LIBDVDX_LOG_BUFFER_SIZE 1024 +#define PCI_START_BYTE 45 /* complement dvdread's DSI_START_BYTE */ +static const uint8_t dvdvideo_nav_header[4] = { 0x00, 0x00, 0x01, 0xBF }; + enum DVDVideoSubpictureViewport { DVDVIDEO_SUBP_VIEWPORT_FULLSCREEN, DVDVIDEO_SUBP_VIEWPORT_WIDESCREEN, @@ -121,6 +123,15 @@ typedef struct DVDVideoPlaybackState { uint64_t *pgc_pg_times_est; /* PG start times as reported by IFO */ pgc_t *pgc; /* handle to the active PGC */ dvdnav_t *dvdnav; /* handle to the dvdnav VM */ + + /* the following fields are only used for menu playback */ + int celln_start; /* starting cell number */ + int celln_end; /* ending cell number */ + int sector_offset; /* current sector relative to the current VOB */ + uint32_t sector_end; /* end sector relative to the current VOBU */ + uint32_t vobu_next; /* the next VOBU pointer */ + uint32_t vobu_remaining; /* remaining blocks for current VOBU */ + dvd_file_t *vob_file; /* handle to the menu VOB (VMG or VTS) */ } DVDVideoPlaybackState; typedef struct DVDVideoDemuxContext { @@ -131,6 +142,9 @@ typedef struct DVDVideoDemuxContext { int opt_chapter_end; /* the user-provided exit PTT (0 for last) */ int opt_chapter_start; /* the user-provided entry PTT (1-indexed) */ int opt_clut_rgb; /* output subtitle palette (CLUT) as RGB */ + int opt_menu; /* demux menu domain instead of title domain */ + int opt_menu_lu; /* the menu language unit (logical grouping) */ + int opt_menu_vts; /* the menu VTS, or 0 for VMG (main menu) */ int opt_pg; /* the user-provided PG number (1-indexed) */ int opt_pgc; /* the user-provided PGC number (1-indexed) */ int opt_preindex; /* pre-indexing mode (2-pass read) */ @@ -227,6 +241,16 @@ static int dvdvideo_ifo_open(AVFormatContext *s) return AVERROR_EXTERNAL; } + if (c->opt_menu) { + if (c->opt_menu_vts > 0 && !(c->vts_ifo = ifoOpen(c->dvdread, c->opt_menu_vts))) { + av_log(s, AV_LOG_ERROR, "Unable to open IFO structure for VTS %d\n", c->opt_menu_vts); + + return AVERROR_EXTERNAL; + } + + return 0; + } + if (c->opt_title > c->vmg_ifo->tt_srpt->nr_of_srpts) { av_log(s, AV_LOG_ERROR, "Title %d not found\n", c->opt_title); @@ -290,6 +314,182 @@ static int dvdvideo_is_pgc_promising(AVFormatContext *s, pgc_t *pgc) return 0; } +static void dvdvideo_menu_close(AVFormatContext *s, DVDVideoPlaybackState *state) +{ + if (state->vob_file) + DVDCloseFile(state->vob_file); +} + +static int dvdvideo_menu_open(AVFormatContext *s, DVDVideoPlaybackState *state) +{ + DVDVideoDemuxContext *c = s->priv_data; + pgci_ut_t *pgci_ut; + + pgci_ut = c->opt_menu_vts ? c->vts_ifo->pgci_ut : c->vmg_ifo->pgci_ut; + if (!pgci_ut) { + av_log(s, AV_LOG_ERROR, "Invalid PGC table for menu [LU %d, PGC %d]\n", + c->opt_menu_lu, c->opt_pgc); + + return AVERROR_INVALIDDATA; + } + + if (c->opt_pgc < 1 || + c->opt_menu_lu < 1 || + c->opt_menu_lu > pgci_ut->nr_of_lus || + c->opt_pgc > pgci_ut->lu[c->opt_menu_lu - 1].pgcit->nr_of_pgci_srp) { + + av_log(s, AV_LOG_ERROR, "Menu [LU %d, PGC %d] not found\n", c->opt_menu_lu, c->opt_pgc); + + return AVERROR(EINVAL); + } + + /* make sure the PGC is valid */ + state->pgcn = c->opt_pgc - 1; + state->pgc = pgci_ut->lu[c->opt_menu_lu - 1].pgcit->pgci_srp[c->opt_pgc - 1].pgc; + + if (!state->pgc || !state->pgc->program_map || !state->pgc->cell_playback) { + av_log(s, AV_LOG_ERROR, "Invalid PGC structure for menu [LU %d, PGC %d]\n", + c->opt_menu_lu, c->opt_pgc); + + return AVERROR_INVALIDDATA; + } + + /* make sure the PG is valid */ + state->entry_pgn = c->opt_pg; + if (state->entry_pgn < 1 || state->entry_pgn > state->pgc->nr_of_programs) { + av_log(s, AV_LOG_ERROR, "Entry PG %d not found\n", state->entry_pgn); + + return AVERROR(EINVAL); + } + + /* make sure the program map isn't leading us to nowhere */ + state->celln_start = state->pgc->program_map[state->entry_pgn - 1]; + state->celln_end = state->pgc->nr_of_cells; + state->celln = state->celln_start; + if (state->celln_start > state->pgc->nr_of_cells) { + av_log(s, AV_LOG_ERROR, "Invalid PGC structure: program map points to unknown cell\n"); + + return AVERROR_INVALIDDATA; + } + + state->sector_end = state->pgc->cell_playback[state->celln - 1].last_sector; + state->vobu_next = state->pgc->cell_playback[state->celln - 1].first_sector; + state->sector_offset = state->vobu_next; + + if (c->opt_menu_vts > 0) + state->in_vts = 1; + + if (!(state->vob_file = DVDOpenFile(c->dvdread, c->opt_menu_vts, DVD_READ_MENU_VOBS))) { + av_log(s, AV_LOG_ERROR, !c->opt_menu_vts ? + "Unable to open main menu VOB (VIDEO_TS.VOB)\n" : + "Unable to open menu VOBs for VTS %d\n", c->opt_menu_vts); + + return AVERROR_EXTERNAL; + } + + return 0; +} + +static int dvdvideo_menu_next_ps_block(AVFormatContext *s, DVDVideoPlaybackState *state, + uint8_t *buf, int buf_size, + void (*flush_cb)(AVFormatContext *s)) +{ + ssize_t blocks_read = 0; + uint8_t read_buf[DVDVIDEO_BLOCK_SIZE] = {0}; + pci_t pci = (pci_t) {0}; + dsi_t dsi = (dsi_t) {0}; + + if (buf_size != DVDVIDEO_BLOCK_SIZE) { + av_log(s, AV_LOG_ERROR, "Invalid buffer size (expected=%d actual=%d)\n", + DVDVIDEO_BLOCK_SIZE, buf_size); + + return AVERROR(EINVAL); + } + + /* we were at the end of a vobu, so now go to the next one or EOF */ + if (!state->vobu_remaining && state->in_pgc) { + if (state->vobu_next == SRI_END_OF_CELL) { + if (state->celln == state->celln_end && state->sector_offset > state->sector_end) + return AVERROR_EOF; + + state->celln++; + state->sector_offset = state->pgc->cell_playback[state->celln - 1].first_sector; + state->sector_end = state->pgc->cell_playback[state->celln - 1].last_sector; + } else { + state->sector_offset = state->vobu_next; + } + } + + /* continue reading the VOBU */ + av_log(s, AV_LOG_TRACE, "reading block at offset %d\n", state->sector_offset); + + blocks_read = DVDReadBlocks(state->vob_file, state->sector_offset, 1, read_buf); + if (blocks_read != 1) { + av_log(s, AV_LOG_ERROR, "Unable to read VOB block at offset %d\n", state->sector_offset); + + return AVERROR_INVALIDDATA; + } + + /* we are at the start of a VOBU, so we are expecting a NAV packet */ + if (!state->vobu_remaining) { + if (!memcmp(&read_buf[PCI_START_BYTE - 4], dvdvideo_nav_header, 4) || + !memcmp(&read_buf[DSI_START_BYTE - 4], dvdvideo_nav_header, 4) || + read_buf[PCI_START_BYTE - 1] != 0x00 || + read_buf[DSI_START_BYTE - 1] != 0x01) { + + av_log(s, AV_LOG_ERROR, "Invalid NAV packet at offset %d: PCI or DSI header mismatch\n", + state->sector_offset); + + return AVERROR_INVALIDDATA; + } + + navRead_PCI(&pci, &read_buf[PCI_START_BYTE]); + navRead_DSI(&dsi, &read_buf[DSI_START_BYTE]); + + if (!pci.pci_gi.vobu_s_ptm || + !pci.pci_gi.vobu_e_ptm || + pci.pci_gi.vobu_s_ptm > pci.pci_gi.vobu_e_ptm) { + + av_log(s, AV_LOG_ERROR, "Invalid NAV packet at offset %d: PCI header is invalid\n", + state->sector_offset); + + return AVERROR_INVALIDDATA; + } + + state->vobu_remaining = dsi.dsi_gi.vobu_ea; + state->vobu_next = dsi.vobu_sri.next_vobu == SRI_END_OF_CELL ? SRI_END_OF_CELL : + dsi.dsi_gi.nv_pck_lbn + (dsi.vobu_sri.next_vobu & 0x7FFFFFFF); + state->sector_offset++; + + if (state->in_pgc) { + if (state->vobu_e_ptm != pci.pci_gi.vobu_s_ptm) { + if (flush_cb) + flush_cb(s); + + state->ts_offset += state->vobu_e_ptm - pci.pci_gi.vobu_s_ptm; + } + } else { + state->in_pgc = 1; + } + + state->vobu_e_ptm = pci.pci_gi.vobu_e_ptm; + + av_log(s, AV_LOG_DEBUG, "NAV packet: sector=%d " + "vobu_s_ptm=%d vobu_e_ptm=%d ts_offset=%ld\n", + dsi.dsi_gi.nv_pck_lbn, + pci.pci_gi.vobu_s_ptm, pci.pci_gi.vobu_e_ptm, state->ts_offset); + + return FFERROR_REDO; + } + + /* we are in the middle of a VOBU, so pass on the PS packet */ + memcpy(buf, &read_buf, DVDVIDEO_BLOCK_SIZE); + state->sector_offset++; + state->vobu_remaining--; + + return DVDVIDEO_BLOCK_SIZE; +} + static void dvdvideo_play_close(AVFormatContext *s, DVDVideoPlaybackState *state) { if (!state->dvdnav) @@ -716,7 +916,7 @@ static int dvdvideo_chapters_setup_preindex(AVFormatContext *s) goto end_close; av_log(s, AV_LOG_INFO, - "Indexing chapter markers, this will take a long time. Please wait...\n"); + "Indexing chapter markers, this may take a long time. Please wait...\n"); while (!(interrupt = ff_check_interrupt(&s->interrupt_callback))) { ret = dvdvideo_play_next_ps_block(s, &state, nav_buf, DVDVIDEO_BLOCK_SIZE, @@ -858,8 +1058,15 @@ static int dvdvideo_video_stream_setup(AVFormatContext *s) int ret = 0; DVDVideoVTSVideoStreamEntry entry = {0}; + video_attr_t video_attr; - if ((ret = dvdvideo_video_stream_analyze(s, c->vts_ifo->vtsi_mat->vts_video_attr, &entry)) < 0 || + if (c->opt_menu) + video_attr = !c->opt_menu_vts ? c->vmg_ifo->vmgi_mat->vmgm_video_attr : + c->vts_ifo->vtsi_mat->vtsm_video_attr; + else + video_attr = c->vts_ifo->vtsi_mat->vts_video_attr; + + if ((ret = dvdvideo_video_stream_analyze(s, video_attr, &entry)) < 0 || (ret = dvdvideo_video_stream_add(s, &entry, AVSTREAM_PARSE_HEADERS)) < 0) { av_log(s, AV_LOG_ERROR, "Unable to add video stream\n"); @@ -1009,15 +1216,29 @@ static int dvdvideo_audio_stream_add_all(AVFormatContext *s) DVDVideoDemuxContext *c = s->priv_data; int ret = 0; + int nb_streams; - for (int i = 0; i < c->vts_ifo->vtsi_mat->nr_of_vts_audio_streams; i++) { + if (c->opt_menu) + nb_streams = !c->opt_menu_vts ? c->vmg_ifo->vmgi_mat->nr_of_vmgm_audio_streams : + c->vts_ifo->vtsi_mat->nr_of_vtsm_audio_streams; + else + nb_streams = c->vts_ifo->vtsi_mat->nr_of_vts_audio_streams; + + for (int i = 0; i < nb_streams; i++) { DVDVideoPGCAudioStreamEntry entry = {0}; + audio_attr_t audio_attr; + + if (c->opt_menu) + audio_attr = !c->opt_menu_vts ? c->vmg_ifo->vmgi_mat->vmgm_audio_attr : + c->vts_ifo->vtsi_mat->vtsm_audio_attr; + else + audio_attr = c->vts_ifo->vtsi_mat->vts_audio_attr[i]; if (!(c->play_state.pgc->audio_control[i] & 0x8000)) continue; - if ((ret = dvdvideo_audio_stream_analyze(s, c->vts_ifo->vtsi_mat->vts_audio_attr[i], - c->play_state.pgc->audio_control[i], &entry)) < 0) + if ((ret = dvdvideo_audio_stream_analyze(s, audio_attr, c->play_state.pgc->audio_control[i], + &entry)) < 0) goto break_error; /* IFO structures can declare duplicate entries for the same startcode */ @@ -1127,7 +1348,16 @@ static int dvdvideo_subp_stream_add_all(AVFormatContext *s) { DVDVideoDemuxContext *c = s->priv_data; - for (int i = 0; i < c->vts_ifo->vtsi_mat->nr_of_vts_subp_streams; i++) { + int nb_streams; + + if (c->opt_menu) + nb_streams = !c->opt_menu_vts ? c->vmg_ifo->vmgi_mat->nr_of_vmgm_subp_streams : + c->vts_ifo->vtsi_mat->nr_of_vtsm_subp_streams; + else + nb_streams = c->vts_ifo->vtsi_mat->nr_of_vts_subp_streams; + + + for (int i = 0; i < nb_streams; i++) { int ret = 0; uint32_t subp_control; subp_attr_t subp_attr; @@ -1139,8 +1369,16 @@ static int dvdvideo_subp_stream_add_all(AVFormatContext *s) /* there can be several presentations for one SPU */ /* the DAR check is flexible in order to support weird authoring */ - video_attr = c->vts_ifo->vtsi_mat->vts_video_attr; - subp_attr = c->vts_ifo->vtsi_mat->vts_subp_attr[i]; + if (c->opt_menu) { + video_attr = !c->opt_menu_vts ? c->vmg_ifo->vmgi_mat->vmgm_video_attr : + c->vts_ifo->vtsi_mat->vtsm_video_attr; + + subp_attr = !c->opt_menu_vts ? c->vmg_ifo->vmgi_mat->vmgm_subp_attr : + c->vts_ifo->vtsi_mat->vtsm_subp_attr; + } else { + video_attr = c->vts_ifo->vtsi_mat->vts_video_attr; + subp_attr = c->vts_ifo->vtsi_mat->vts_subp_attr[i]; + } /* 4:3 */ if (!video_attr.display_aspect_ratio) { @@ -1196,8 +1434,12 @@ static int dvdvideo_subdemux_read_data(void *opaque, uint8_t *buf, int buf_size) if (c->play_end) return AVERROR_EOF; - ret = dvdvideo_play_next_ps_block(opaque, &c->play_state, buf, buf_size, - &nav_event, dvdvideo_subdemux_flush); + if (c->opt_menu) + ret = dvdvideo_menu_next_ps_block(s, &c->play_state, buf, buf_size, + dvdvideo_subdemux_flush); + else + ret = dvdvideo_play_next_ps_block(opaque, &c->play_state, buf, buf_size, + &nav_event, dvdvideo_subdemux_flush); if (ret == AVERROR_EOF) { c->mpeg_pb.pub.eof_reached = 1; @@ -1261,6 +1503,47 @@ static int dvdvideo_read_header(AVFormatContext *s) int ret = 0; + if (c->opt_menu) { + if (c->opt_region || + c->opt_title > 1 || + c->opt_preindex || + c->opt_chapter_start > 1 || + c->opt_chapter_end > 0) { + av_log(s, AV_LOG_ERROR, "-menu is not compatible with the -region, -title, " + "-preindex, or -chapter_start/-chapter_end options\n"); + return AVERROR(EINVAL); + } + + if (!c->opt_pgc) { + av_log(s, AV_LOG_ERROR, "If -menu is enabled, -pgc must be set to a non-zero value\n"); + + return AVERROR(EINVAL); + } + + if (!c->opt_menu_lu) { + av_log(s, AV_LOG_INFO, "Defaulting to menu language unit #1. " + "This is not always desirable, validation suggested.\n"); + + c->opt_menu_lu = 1; + } + + if (!c->opt_pg) { + av_log(s, AV_LOG_INFO, "Defaulting to menu PG #1. " + "This is not always desirable, validation suggested.\n"); + + c->opt_pg = 1; + } + + if ((ret = dvdvideo_ifo_open(s)) < 0 || + (ret = dvdvideo_menu_open(s, &c->play_state)) < 0 || + (ret = dvdvideo_subdemux_open(s)) < 0 || + (ret = dvdvideo_video_stream_setup(s)) < 0 || + (ret = dvdvideo_audio_stream_add_all(s)) < 0) + return ret; + + return 0; + } + if (c->opt_title == 0) { av_log(s, AV_LOG_INFO, "Defaulting to title #1. " "This is not always the main feature, validation suggested.\n"); @@ -1376,7 +1659,12 @@ static int dvdvideo_close(AVFormatContext *s) DVDVideoDemuxContext *c = s->priv_data; dvdvideo_subdemux_close(s); - dvdvideo_play_close(s, &c->play_state); + + if (c->opt_menu) + dvdvideo_menu_close(s, &c->play_state); + else + dvdvideo_play_close(s, &c->play_state); + dvdvideo_ifo_close(s); return 0; @@ -1388,6 +1676,9 @@ static const AVOption dvdvideo_options[] = { {"chapter_end", "exit chapter (PTT) number (0=end)", OFFSET(opt_chapter_end), AV_OPT_TYPE_INT, { .i64=0 }, 0, 99, AV_OPT_FLAG_DECODING_PARAM }, {"chapter_start", "entry chapter (PTT) number", OFFSET(opt_chapter_start), AV_OPT_TYPE_INT, { .i64=1 }, 1, 99, AV_OPT_FLAG_DECODING_PARAM }, {"clut_rgb", "output subtitle palette (CLUT) as RGB", OFFSET(opt_clut_rgb), AV_OPT_TYPE_BOOL, { .i64=1 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, + {"menu", "demux menu domain", OFFSET(opt_menu), AV_OPT_TYPE_BOOL, { .i64=0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, + {"menu_lu", "menu language unit (0=auto)", OFFSET(opt_menu_lu), AV_OPT_TYPE_INT, { .i64=0 }, 0, 99, AV_OPT_FLAG_DECODING_PARAM }, + {"menu_vts", "menu VTS (0=VMG main menu)", OFFSET(opt_menu_vts), AV_OPT_TYPE_INT, { .i64=0 }, 0, 99, AV_OPT_FLAG_DECODING_PARAM }, {"pg", "entry PG number (0=auto)", OFFSET(opt_pg), AV_OPT_TYPE_INT, { .i64=0 }, 0, 255, AV_OPT_FLAG_DECODING_PARAM }, {"pgc", "entry PGC number (0=auto)", OFFSET(opt_pgc), AV_OPT_TYPE_INT, { .i64=0 }, 0, 999, AV_OPT_FLAG_DECODING_PARAM }, {"preindex", "enable for accurate chapter markers, slow (2-pass read)", OFFSET(opt_preindex), AV_OPT_TYPE_BOOL, { .i64=0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, From patchwork Wed Mar 6 07:19:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marth64 X-Patchwork-Id: 46832 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:d90e:b0:19e:cdac:8cce with SMTP id jd14csp224934pzb; Tue, 5 Mar 2024 23:21:15 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCUjRum3aM8NB7lddYDg9+1PoK56LIJtXsszuMEHIcU0mJw3GuhODdpyj3VVjdyARigntqi2/sPtViWzXyQBhzNLD7fkRyYsjuyHYw== X-Google-Smtp-Source: AGHT+IGdC97VZJhDvlZyGejFQ/+z5rOKm/a28vBi2DY6uQ0A3x9cTx+EQgHMGoA+5X1xst+3QYDT X-Received: by 2002:a05:6402:2027:b0:565:e4b7:e784 with SMTP id ay7-20020a056402202700b00565e4b7e784mr8106831edb.40.1709709674790; Tue, 05 Mar 2024 23:21:14 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1709709674; cv=none; d=google.com; s=arc-20160816; b=uAp7ssLCW3+9AwYelQZi0f8EVJd+3Qiy4+YMVC9rJGyvaXkFXN6yheCQccJ7XSAgNk bCxMfIQb/pQRW2RknSACrBzXqHapRiQD+KfhWNpW7A/8jTJdCUsvODU9T4EyLgSDBw8A t14guQdQzc/8GoLJtNJ1ijpIXaysQm8/iIwbisA5HriaEoUBXzsO/ru0ybFVsP+FGvmN WH4M0HupTB3Zhs+fp+9dITO8q2IWTu0Z0NmZFLUU6vcJvJ07pVZl858D/c5LYsqN4NmC 2cSSuK3NryNSFdIxwxof8Got7+WRZXXSvUlsUfAn0zIE0KxRlFew3Bpw+EUGMJZ9BmFp C9yg== 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:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=pNndtyq/QL3qERBGitXnvQOi/Jz7yP0uJTX0dfZNcok=; fh=PlWMzmI9LD2qGS7ipLrQl8z0iaQTLQLHzoGuXcBzpCg=; b=rJw7bOJ5kJXcIeAHMACjE+XIXjS9BhHM2eScxN04JY36o/79aCojrp2cTjb7iA7ZUX on/KyRTjqfZT4oswr32vGYj6NRB6t9iyErtHV6QAFl8iNPQ4VlBfvUOcpW18P/V2gIkW bI72410qWO5XV7HR1fc6Z7bXDNc7r0j0G7F+ME5kPnmoLle+bKuxe92Xe5+VcWOR/QdV CazEdn+PdnUKsQkxvYAHYLJLnRnr3xoNCBfph/lGbNrKlclPJuB0eBf/mmdCqB/B4vHg GU+JkuwC2soU+z58vgaz12Elzojox+hyADc3uGl71CQzsI7O3hEF9+Hm3h0ro5OKAJW9 aVhA==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@proxyid.net header.s=google header.b=EUiAegL8; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id u9-20020a50d509000000b0056577684470si5729418edi.246.2024.03.05.23.21.14; Tue, 05 Mar 2024 23:21:14 -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=@proxyid.net header.s=google header.b=EUiAegL8; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 4B68C68CC01; Wed, 6 Mar 2024 09:20:53 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ot1-f98.google.com (mail-ot1-f98.google.com [209.85.210.98]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 72CBB68C3D2 for ; Wed, 6 Mar 2024 09:20:44 +0200 (EET) Received: by mail-ot1-f98.google.com with SMTP id 46e09a7af769-6e4e608a374so329259a34.3 for ; Tue, 05 Mar 2024 23:20:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=proxyid.net; s=google; t=1709709642; x=1710314442; darn=ffmpeg.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=sQbb5bwlotn/t6D+e1WPLj9sPk+i9y92qD3vhmWGEW8=; b=EUiAegL8zfkEIYGeQnH+x8sH7oJu0g36p6b+hkUa3m0OBRLkRrgorEKzhkaJDxhWBX KBhbUXTuoDYITxO3uLIYgokWm7iDmuFHTGf2hHPqomS8nWHKnO/JGynpqK2kudzytlDH Sxh1liMvQ4VCXfZ2YqILCSROMzE5WvLoP8nK16jtIXcM9WOzifhHR5ySbe8t8JUcohPC R9EXroP2bEPlReagM5fYKnxFfW/4dOKq6KSUw1da2g+pK74yaCjtw+VRrQMEJd68U08B XnNEcUtUujgRLNOiYXDekdLs2F80xW/iR2CGm2biXkNjrhcSNmGUydC70tAbI1V9woOo 1f0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709709642; x=1710314442; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=sQbb5bwlotn/t6D+e1WPLj9sPk+i9y92qD3vhmWGEW8=; b=Szqm3uHbXAcSODKzXoiThcaQLhlZS24NZQabaySgWbFOSqyKwDLmtMmnU7FYp4fzvi ZS8xfbbnzdVWGkMDXraY+4K+rHR2iQ1ejD0qVRTaLtVPx4A7gGlguF2WrF8pEkxufhWO 17hNknpRHEefuWafNpS2dKEZ0HAzsPltTR3SZQFjA4KLDYQCFnjIPTWWt/zV7Oov+v++ xt5sbL1+uw8vLQDcIVVJJJeS5YKRSLqEFEbS8yf6mhWPACU0n2ieCSwhEzc6V/fROPfg 2OCk6ocZgumep+4PL90Yy5J28+umpXWprlZkKTSFc/DzQvWZbGw1XWMYvPWG7SDb05OP GcSA== X-Gm-Message-State: AOJu0YydyZdtVfBEaImZ+pfEYyh1XGmA9+O3Tc64nsu0JgabxV1n/8nL DP+tosa8wtMnR62YpFAOUmGBiPNAC1T2wXz2shHppPUDVVJFKMfFxZT82dwlhugHqocgXj4os3q gWIys9u6Y/nQr64Cera9V+oN9Pm+GjyejeoeJ7mDy X-Received: by 2002:a05:6830:1e41:b0:6e4:ea7f:16f2 with SMTP id e1-20020a0568301e4100b006e4ea7f16f2mr4620620otj.18.1709709642586; Tue, 05 Mar 2024 23:20:42 -0800 (PST) Received: from wsx-cc1-001.. (c-76-141-249-38.hsd1.il.comcast.net. [76.141.249.38]) by smtp-relay.gmail.com with ESMTPS id s5-20020a63ff45000000b005dc846d791csm553686pgk.14.2024.03.05.23.20.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 23:20:42 -0800 (PST) X-Relaying-Domain: proxyid.net From: Marth64 To: ffmpeg-devel@ffmpeg.org Date: Wed, 6 Mar 2024 01:19:13 -0600 Message-Id: <20240306071913.2735832-3-marth64@proxyid.net> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240306071913.2735832-1-marth64@proxyid.net> References: <20240306071913.2735832-1-marth64@proxyid.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/3] avformat/dvdvideodec: assign mono channel layout explicitly 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 Cc: Marth64 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: J6CaHGBNWuqR Signed-off-by: Marth64 --- libavformat/dvdvideodec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/dvdvideodec.c b/libavformat/dvdvideodec.c index 2c7ffdd148..6136060288 100644 --- a/libavformat/dvdvideodec.c +++ b/libavformat/dvdvideodec.c @@ -1142,7 +1142,9 @@ static int dvdvideo_audio_stream_analyze(AVFormatContext *s, audio_attr_t audio_ return AVERROR_INVALIDDATA; } - if (nb_channels == 2) + if (nb_channels == 1) + ch_layout = (AVChannelLayout) AV_CHANNEL_LAYOUT_MONO; + else if (nb_channels == 2) ch_layout = (AVChannelLayout) AV_CHANNEL_LAYOUT_STEREO; else if (nb_channels == 6) ch_layout = (AVChannelLayout) AV_CHANNEL_LAYOUT_5POINT1;