diff mbox series

[FFmpeg-devel,v2] avcodec/wmaprodec: skip foreign XMA packets

Message ID 20210901084443.56245-1-jl@conductive.de
State New
Headers show
Series [FFmpeg-devel,v2] avcodec/wmaprodec: skip foreign XMA packets | expand

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished
andriy/make_ppc success Make finished
andriy/make_fate_ppc success Make fate finished

Commit Message

Joel Linn Sept. 1, 2021, 8:44 a.m. UTC
Support decoding only a selection of the encoded XMA streams.
Previously, the decoder assumed it was decoding all available streams.
---
 libavcodec/wmaprodec.c | 65 ++++++++++++++++++++++++------------------
 1 file changed, 38 insertions(+), 27 deletions(-)

Comments

Paul B Mahol Sept. 1, 2021, 9:12 a.m. UTC | #1
I do not get it, do you use parser in your code to support decoding of XMA?

Without parser decoding is not currently supported.
Joel Linn Sept. 1, 2021, 3:48 p.m. UTC | #2
On 2021-09-01 11:12, Paul B Mahol wrote:
> I do not get it, do you use parser in your code to support decoding of 
> XMA?

No.
The duration information from the parser is of no use to me.

> Without parser decoding is not currently supported.

I could use the parser but like I said it is perpendicular to the 
problem this patch solves.
Paul B Mahol Sept. 1, 2021, 6 p.m. UTC | #3
parser sets keyframes, which allows proper decoding, so it is mandatory to
use.
diff mbox series

Patch

diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c
index 66271c4037..b957b1d1ea 100644
--- a/libavcodec/wmaprodec.c
+++ b/libavcodec/wmaprodec.c
@@ -1814,7 +1814,44 @@  static int xma_decode_packet(AVCodecContext *avctx, void *data,
     XMADecodeCtx *s = avctx->priv_data;
     int got_stream_frame_ptr = 0;
     AVFrame *frame = data;
-    int i, ret, offset = INT_MAX;
+    int i, ret, skip_current_packet;
+    int offset = INT_MAX;
+
+    /* find the owner stream of the new XMA packet that belongs to on of our streams
+     * XMA streams find their packets following packet_skips
+     * there may be other packets in between if we are not responsible for all streams
+     * (at start there is one packet per stream, then interleave non-linearly). */
+    if (s->xma[s->current_stream].packet_done ||
+        s->xma[s->current_stream].packet_loss) {
+        /* select stream with lowest skip_packets (= uses next packet) */
+        if (s->xma[s->current_stream].skip_packets != 0) {
+            int min[2];
+
+            min[0] = s->xma[0].skip_packets;
+            min[1] = i = 0;
+
+            for (i = 1; i < s->num_streams; i++) {
+                if (s->xma[i].skip_packets < min[0]) {
+                    min[0] = s->xma[i].skip_packets;
+                    min[1] = i;
+                }
+            }
+
+            s->current_stream = min[1];
+        }
+
+        skip_current_packet = !!s->xma[s->current_stream].skip_packets;
+
+        /* advance all stream packet skip counts */
+        for (i = 0; i < s->num_streams; i++) {
+            s->xma[i].skip_packets = FFMAX(0, s->xma[i].skip_packets - 1);
+        }
+
+        /* if we are not responsible for every stream, make sure we ignore
+         * XMA packets not belonging to one of our streams */
+        if (skip_current_packet)
+            return avctx->block_align;
+    }
 
     if (!s->frames[s->current_stream]->data[0]) {
         s->frames[s->current_stream]->nb_samples = 512;
@@ -1846,34 +1883,8 @@  static int xma_decode_packet(AVCodecContext *avctx, void *data,
         return ret;
     }
 
-    /* find next XMA packet's owner stream, and update.
-     * XMA streams find their packets following packet_skips
-     * (at start there is one packet per stream, then interleave non-linearly). */
     if (s->xma[s->current_stream].packet_done ||
         s->xma[s->current_stream].packet_loss) {
-
-        /* select stream with 0 skip_packets (= uses next packet) */
-        if (s->xma[s->current_stream].skip_packets != 0) {
-            int min[2];
-
-            min[0] = s->xma[0].skip_packets;
-            min[1] = i = 0;
-
-            for (i = 1; i < s->num_streams; i++) {
-                if (s->xma[i].skip_packets < min[0]) {
-                    min[0] = s->xma[i].skip_packets;
-                    min[1] = i;
-                }
-            }
-
-            s->current_stream = min[1];
-        }
-
-        /* all other streams skip next packet */
-        for (i = 0; i < s->num_streams; i++) {
-            s->xma[i].skip_packets = FFMAX(0, s->xma[i].skip_packets - 1);
-        }
-
         /* copy samples from buffer to output if possible */
         for (i = 0; i < s->num_streams; i++) {
             offset = FFMIN(offset, s->offset[i]);