Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: Marton Balint <cus@passwd.hu>
To: ffmpeg-devel@ffmpeg.org
Cc: Marton Balint <cus@passwd.hu>
Subject: [FFmpeg-devel] [PATCH 3/3] avformat/electronicarts: add option to return alpha channel in the main video stream in VP6A codec
Date: Sun, 13 Nov 2022 19:44:41 +0100
Message-ID: <20221113184441.1741-3-cus@passwd.hu> (raw)
In-Reply-To: <20221113184441.1741-1-cus@passwd.hu>

Signed-off-by: Marton Balint <cus@passwd.hu>
---
 doc/demuxers.texi            | 18 ++++++++++++++++
 libavformat/electronicarts.c | 42 +++++++++++++++++++++++++++++++-----
 libavformat/version.h        |  2 +-
 3 files changed, 56 insertions(+), 6 deletions(-)

diff --git a/doc/demuxers.texi b/doc/demuxers.texi
index 2b6dd86c2a..f07f3f5318 100644
--- a/doc/demuxers.texi
+++ b/doc/demuxers.texi
@@ -285,6 +285,24 @@ This demuxer accepts the following option:
 
 @end table
 
+@section ea
+
+Electronic Arts Multimedia format demuxer.
+
+This format is used by various Electronic Arts games.
+
+@subsection Options
+
+@table @option
+
+@item merge_alpha @var{bool}
+
+Normally the VP6 alpha channel (if exists) is returned as a secondary video
+stream, by setting this option you can make the demuxer return a single video
+stream which contains the alpha channel in addition to the ordinary video.
+
+@end table
+
 @section imf
 
 Interoperable Master Format demuxer.
diff --git a/libavformat/electronicarts.c b/libavformat/electronicarts.c
index 0532264f38..e7f574aede 100644
--- a/libavformat/electronicarts.c
+++ b/libavformat/electronicarts.c
@@ -28,6 +28,7 @@
 #include <inttypes.h>
 
 #include "libavutil/intreadwrite.h"
+#include "libavutil/opt.h"
 #include "avformat.h"
 #include "internal.h"
 
@@ -75,6 +76,8 @@ typedef struct VideoProperties {
 } VideoProperties;
 
 typedef struct EaDemuxContext {
+    const AVClass *class;
+
     int big_endian;
 
     VideoProperties video, alpha;
@@ -88,6 +91,7 @@ typedef struct EaDemuxContext {
     int num_samples;
 
     int platform;
+    int merge_alpha;
 } EaDemuxContext;
 
 static uint32_t read_arbitrary(AVIOContext *pb)
@@ -442,6 +446,10 @@ static int process_ea_header(AVFormatContext *s)
 
         case AVhd_TAG:
             err = process_video_header_vp6(s, &ea->alpha);
+            if (err >= 0 && ea->video.codec == AV_CODEC_ID_VP6 && ea->merge_alpha) {
+                ea->alpha.codec = 0;
+                ea->video.codec = AV_CODEC_ID_VP6A;
+            }
             break;
         }
 
@@ -578,7 +586,7 @@ static int ea_read_packet(AVFormatContext *s, AVPacket *pkt)
     int partial_packet = 0;
     int hit_end = 0;
     unsigned int chunk_type, chunk_size;
-    int ret = 0, packet_read = 0, key = 0;
+    int ret = 0, packet_read = 0, key = 0, vp6a;
     int av_uninit(num_samples);
 
     while ((!packet_read && !hit_end) || partial_packet) {
@@ -721,19 +729,28 @@ static int ea_read_packet(AVFormatContext *s, AVPacket *pkt)
 get_video_packet:
             if (!chunk_size)
                 continue;
+            if (chunk_size > INT_MAX - 3)
+                return AVERROR_INVALIDDATA;
+
+            vp6a = (ea->video.codec == AV_CODEC_ID_VP6A && (chunk_type == MV0F_TAG || chunk_type == MV0K_TAG));
 
             if (partial_packet) {
                 ret = av_append_packet(pb, pkt, chunk_size);
-            } else
-                ret = av_get_packet(pb, pkt, chunk_size);
+            } else {
+                if (vp6a)
+                    avio_seek(pb, -3, SEEK_CUR);
+                ret = av_get_packet(pb, pkt, chunk_size + (vp6a ? 3 : 0));
+                if (ret >= 0 && vp6a)
+                   AV_WB24(pkt->data, chunk_size);
+            }
             packet_read = 1;
 
             if (ret < 0) {
                 partial_packet = 0;
                 break;
             }
-            partial_packet = chunk_type == MVIh_TAG;
-            if (chunk_type == AV0K_TAG || chunk_type == AV0F_TAG)
+            partial_packet = vp6a || chunk_type == MVIh_TAG;
+            if (ea->alpha.codec && (chunk_type == AV0K_TAG || chunk_type == AV0F_TAG))
                 pkt->stream_index = ea->alpha.stream_index;
             else
                 pkt->stream_index = ea->video.stream_index;
@@ -752,6 +769,20 @@ get_video_packet:
     return ret;
 }
 
+#define OFFSET(x) offsetof(EaDemuxContext, x)
+#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
+static const AVOption options[] = {
+    {"merge_alpha", "return VP6 alpha in the main video stream", OFFSET(merge_alpha), AV_OPT_TYPE_BOOL,  {.i64 = 0}, 0, 1, FLAGS },
+    {NULL}
+};
+
+static const AVClass ea_class = {
+    .class_name = "ea demuxer",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
 const AVInputFormat ff_ea_demuxer = {
     .name           = "ea",
     .long_name      = NULL_IF_CONFIG_SMALL("Electronic Arts Multimedia"),
@@ -759,4 +790,5 @@ const AVInputFormat ff_ea_demuxer = {
     .read_probe     = ea_probe,
     .read_header    = ea_read_header,
     .read_packet    = ea_read_packet,
+    .priv_class     = &ea_class,
 };
diff --git a/libavformat/version.h b/libavformat/version.h
index 7c9d50b7b3..a7e5a9ac66 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -32,7 +32,7 @@
 #include "version_major.h"
 
 #define LIBAVFORMAT_VERSION_MINOR  34
-#define LIBAVFORMAT_VERSION_MICRO 101
+#define LIBAVFORMAT_VERSION_MICRO 102
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
                                                LIBAVFORMAT_VERSION_MINOR, \
-- 
2.35.3

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

  parent reply	other threads:[~2022-11-13 18:45 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-13 18:44 [FFmpeg-devel] [PATCH 1/3] avformat/electronicarts: fix EOF check Marton Balint
2022-11-13 18:44 ` [FFmpeg-devel] [PATCH 2/3] avformat/electronicarts: set packet_read in one place Marton Balint
2022-11-17  7:30   ` Peter Ross
2022-11-13 18:44 ` Marton Balint [this message]
2022-11-14 16:34   ` [FFmpeg-devel] [PATCH 3/3] avformat/electronicarts: add option to return alpha channel in the main video stream in VP6A codec Anton Khirnov
2022-11-14 22:05     ` Marton Balint
2022-11-17  7:32       ` Peter Ross
2022-11-22 22:31         ` Marton Balint
2022-11-17  7:29 ` [FFmpeg-devel] [PATCH 1/3] avformat/electronicarts: fix EOF check Peter Ross

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221113184441.1741-3-cus@passwd.hu \
    --to=cus@passwd.hu \
    --cc=ffmpeg-devel@ffmpeg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git