diff mbox series

[FFmpeg-devel] QOA decoding support

Message ID CAPYw7P7HjG6Ow+Uv4JJgyhyKiqSsTqBLOePwU9hOw5pF61peiw@mail.gmail.com
State New
Headers show
Series [FFmpeg-devel] QOA decoding support | expand

Checks

Context Check Description
andriy/make_x86 fail Make failed

Commit Message

Paul B Mahol Sept. 23, 2023, 9:39 p.m. UTC
Patches attached.

Comments

Andreas Rheinhardt Sept. 24, 2023, 12:05 a.m. UTC | #1
Paul B Mahol:
> +    .flags          = AVFMT_GENERIC_INDEX,
> +    .extensions     = "qoa",
> +    .raw_codec_id   = AV_CODEC_ID_QOA,

This will not compile: The codec_id is only added in the second patch.

> +    .priv_data_size = sizeof(FFRawDemuxerContext),
> +    .priv_class     = &ff_raw_demuxer_class,


> 
> +        if (!qoa->frame_size) {
> +            for (; i < buf_size; i++) {
> +                state = (state << 8) | buf[i];
> +                if (((state & 0xFFFF) > 0 && (state >> 56))) {
> +                    qoa->frame_size = state & 0xFFFF;
> +                    qoa->duration = (state >> 16) & 0xFFFF;
> +                    break;
> +                }
> +            }
> +        }

So this codec uses a length field. In this case it is quite simple to
avoid the parser (and its implicit memcpy) altogether and just make the
demuxer directly output packets of the correct size. This is quite
natural given that this format does not seem to provide any features
like resyncing support (or at least the parser does not implement them).

> 
> +#include "avcodec.h"
> +#include "codec_internal.h"
> +#include "decode.h"
> +#include "get_bits.h"

You don't use the GetBit API at all.

> +#include "bytestream.h"

> 
> +    for (int sample_index = 0; sample_index < frame->nb_samples * nb_channels;
> +         sample_index += QOA_SLICE_LEN) {
> +        for (int ch = 0; ch < nb_channels; ch++) {

So the number of times the second loop is executed is quadratic in
nb_channels. Is this really intended? The frame_size check is not
quadratic in nb_channels. In fact, it does not seem to account for this
double-loop here at all.

- Andreas
Paul B Mahol Sept. 24, 2023, 12:48 a.m. UTC | #2
On Sun, Sep 24, 2023 at 2:04 AM Andreas Rheinhardt <
andreas.rheinhardt@outlook.com> wrote:

> Paul B Mahol:
> > +    .flags          = AVFMT_GENERIC_INDEX,
> > +    .extensions     = "qoa",
> > +    .raw_codec_id   = AV_CODEC_ID_QOA,
>
> This will not compile: The codec_id is only added in the second patch.
>
> > +    .priv_data_size = sizeof(FFRawDemuxerContext),
> > +    .priv_class     = &ff_raw_demuxer_class,
>
>
> >
> > +        if (!qoa->frame_size) {
> > +            for (; i < buf_size; i++) {
> > +                state = (state << 8) | buf[i];
> > +                if (((state & 0xFFFF) > 0 && (state >> 56))) {
> > +                    qoa->frame_size = state & 0xFFFF;
> > +                    qoa->duration = (state >> 16) & 0xFFFF;
> > +                    break;
> > +                }
> > +            }
> > +        }
>
> So this codec uses a length field. In this case it is quite simple to
> avoid the parser (and its implicit memcpy) altogether and just make the
> demuxer directly output packets of the correct size. This is quite
> natural given that this format does not seem to provide any features
> like resyncing support (or at least the parser does not implement them).
>

But channels/sample rate may differ between packets.
Also it may be in other formats, like wav. So I picked parser as more
valuable implementation.


>
> >
> > +#include "avcodec.h"
> > +#include "codec_internal.h"
> > +#include "decode.h"
> > +#include "get_bits.h"
>
> You don't use the GetBit API at all.
>
> > +#include "bytestream.h"
>
> >
> > +    for (int sample_index = 0; sample_index < frame->nb_samples *
> nb_channels;
> > +         sample_index += QOA_SLICE_LEN) {
> > +        for (int ch = 0; ch < nb_channels; ch++) {
>
> So the number of times the second loop is executed is quadratic in
> nb_channels. Is this really intended? The frame_size check is not
> quadratic in nb_channels. In fact, it does not seem to account for this
> double-loop here at all.
>
> - Andreas
>
> _______________________________________________
> 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".
>
Paul B Mahol Sept. 24, 2023, 12:50 a.m. UTC | #3
New patches.
Paul B Mahol Sept. 27, 2023, 12:44 p.m. UTC | #4
On Sun, Sep 24, 2023 at 2:50 AM Paul B Mahol <onemda@gmail.com> wrote:

>
> New patches.
>

Will apply.
Andreas Rheinhardt Sept. 27, 2023, 12:52 p.m. UTC | #5
Paul B Mahol:
> On Sun, Sep 24, 2023 at 2:04 AM Andreas Rheinhardt <
> andreas.rheinhardt@outlook.com> wrote:
> 
>> Paul B Mahol:
>>>
>>> +        if (!qoa->frame_size) {
>>> +            for (; i < buf_size; i++) {
>>> +                state = (state << 8) | buf[i];
>>> +                if (((state & 0xFFFF) > 0 && (state >> 56))) {
>>> +                    qoa->frame_size = state & 0xFFFF;
>>> +                    qoa->duration = (state >> 16) & 0xFFFF;
>>> +                    break;
>>> +                }
>>> +            }
>>> +        }
>>
>> So this codec uses a length field. In this case it is quite simple to
>> avoid the parser (and its implicit memcpy) altogether and just make the
>> demuxer directly output packets of the correct size. This is quite
>> natural given that this format does not seem to provide any features
>> like resyncing support (or at least the parser does not implement them).
>>
> 
> But channels/sample rate may differ between packets.

And?

> Also it may be in other formats, like wav. So I picked parser as more
> valuable implementation.
> 

Then you could simply reuse the code inside libavformat.

- Andreas
Paul B Mahol Sept. 27, 2023, 12:52 p.m. UTC | #6
On Wed, Sep 27, 2023 at 2:51 PM Andreas Rheinhardt <
andreas.rheinhardt@outlook.com> wrote:

> Paul B Mahol:
> > On Sun, Sep 24, 2023 at 2:04 AM Andreas Rheinhardt <
> > andreas.rheinhardt@outlook.com> wrote:
> >
> >> Paul B Mahol:
> >>>
> >>> +        if (!qoa->frame_size) {
> >>> +            for (; i < buf_size; i++) {
> >>> +                state = (state << 8) | buf[i];
> >>> +                if (((state & 0xFFFF) > 0 && (state >> 56))) {
> >>> +                    qoa->frame_size = state & 0xFFFF;
> >>> +                    qoa->duration = (state >> 16) & 0xFFFF;
> >>> +                    break;
> >>> +                }
> >>> +            }
> >>> +        }
> >>
> >> So this codec uses a length field. In this case it is quite simple to
> >> avoid the parser (and its implicit memcpy) altogether and just make the
> >> demuxer directly output packets of the correct size. This is quite
> >> natural given that this format does not seem to provide any features
> >> like resyncing support (or at least the parser does not implement them).
> >>
> >
> > But channels/sample rate may differ between packets.
>
> And?
>
> > Also it may be in other formats, like wav. So I picked parser as more
> > valuable implementation.
> >
>
> Then you could simply reuse the code inside libavformat.
>

What code?
I think that having parser is much more useful.


>
> - Andreas
>
> _______________________________________________
> 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".
>
Tomas Härdin Sept. 27, 2023, 12:54 p.m. UTC | #7
Needs a FATE test.

/Tomas
Paul B Mahol Sept. 27, 2023, 12:56 p.m. UTC | #8
On Wed, Sep 27, 2023 at 2:55 PM Tomas Härdin <git@haerdin.se> wrote:

> Needs a FATE test.
>
>
Feel free to upload sample(s).


> /Tomas
> _______________________________________________
> 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".
>
Nicolas George Sept. 27, 2023, 12:57 p.m. UTC | #9
Paul B Mahol (12023-09-27):
> I think that having parser is much more useful.

Having a parser when it can be done without is a waste of code and
resources.

Do not push like that.
Tomas Härdin Sept. 27, 2023, 12:57 p.m. UTC | #10
ons 2023-09-27 klockan 14:56 +0200 skrev Paul B Mahol:
> On Wed, Sep 27, 2023 at 2:55 PM Tomas Härdin <git@haerdin.se> wrote:
> 
> > Needs a FATE test.
> > 
> > 
> Feel free to upload sample(s).

Don't have any. But I presume you do. Also wasn't it decided that new
formats/codecs mustn't be added without tests?

/Tomas
Nicolas George Sept. 27, 2023, 12:58 p.m. UTC | #11
Andreas Rheinhardt (12023-09-27):
> Then you could simply reuse the code inside libavformat.

Do you finally support merging the libraries then?

Because otherwise, using from libavformat code for an individual
component of libavcodec requires adding a new avpriv function.

Regards,
Paul B Mahol Sept. 27, 2023, 12:59 p.m. UTC | #12
On Wed, Sep 27, 2023 at 2:57 PM Tomas Härdin <git@haerdin.se> wrote:

> ons 2023-09-27 klockan 14:56 +0200 skrev Paul B Mahol:
> > On Wed, Sep 27, 2023 at 2:55 PM Tomas Härdin <git@haerdin.se> wrote:
> >
> > > Needs a FATE test.
> > >
> > >
> > Feel free to upload sample(s).
>
> Don't have any. But I presume you do. Also wasn't it decided that new

formats/codecs mustn't be added without tests?
>

Nope, that is ridiculous. One adds samples after.



> /Tomas
> _______________________________________________
> 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".
>
Paul B Mahol Sept. 27, 2023, 1 p.m. UTC | #13
On Wed, Sep 27, 2023 at 2:57 PM Nicolas George <george@nsup.org> wrote:

> Paul B Mahol (12023-09-27):
> > I think that having parser is much more useful.
>
> Having a parser when it can be done without is a waste of code and
> resources.
>
> Do not push like that.
>

As you never pushed anything marginally useful to codebase, I'm free to
ignore your
destructive and evil inputs/comments.


>
> --
>   Nicolas George
> _______________________________________________
> 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".
>
Paul B Mahol Sept. 27, 2023, 1:02 p.m. UTC | #14
On Wed, Sep 27, 2023 at 2:57 PM Nicolas George <george@nsup.org> wrote:

> Paul B Mahol (12023-09-27):
> > I think that having parser is much more useful.
>
> Having a parser when it can be done without is a waste of code and
> resources.
>

I already wrote that parser is useful addition. Mainly because of many
factors.

Once you understand how demuxer/parsers/decoders works together and also
understand whole Multimedia architecture in FFmpeg you will post more
valuable reviews and/or comments,
and be more useful contributor to project.


>
> Do not push like that.
>
> --
>   Nicolas George
> _______________________________________________
> 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".
>
Andreas Rheinhardt Sept. 27, 2023, 1:05 p.m. UTC | #15
Nicolas George:
> Andreas Rheinhardt (12023-09-27):
>> Then you could simply reuse the code inside libavformat.
> 
> Do you finally support merging the libraries then?
> 
> Because otherwise, using from libavformat code for an individual
> component of libavcodec requires adding a new avpriv function.
> 

What I meant was: He shall write a simple function which reads from the
input, determines the size of the packet, allocates and reads the actual
packet (thereby avoiding memcpy's) and sets the codec parameters based
upon the input (changes may need to be propagated via side-data
updates). This is supposed to do what the parser does and it is supposed
to stay completely inside libavformat to be reused by e.g. the Wav
demuxer if needed. There is no need for a separate copy of this code
inside libavcodec, so whether the libraries are split or not is
irrelevant here.

- Andreas
Tomas Härdin Sept. 27, 2023, 1:05 p.m. UTC | #16
ons 2023-09-27 klockan 14:59 +0200 skrev Paul B Mahol:
> On Wed, Sep 27, 2023 at 2:57 PM Tomas Härdin <git@haerdin.se> wrote:
> 
> > ons 2023-09-27 klockan 14:56 +0200 skrev Paul B Mahol:
> > > On Wed, Sep 27, 2023 at 2:55 PM Tomas Härdin <git@haerdin.se>
> > > wrote:
> > > 
> > > > Needs a FATE test.
> > > > 
> > > > 
> > > Feel free to upload sample(s).
> > 
> > Don't have any. But I presume you do. Also wasn't it decided that
> > new
> 
> formats/codecs mustn't be added without tests?
> > 
> 
> Nope, that is ridiculous. One adds samples after.

As long as they get added. But there's a higher risk of forgetting if
one does it after the fact. Adding samples to fate-suite first and
demanding tests at the same time as the code is added means less risk
of forgetting.

/Tomas
Paul B Mahol Sept. 27, 2023, 1:09 p.m. UTC | #17
On Wed, Sep 27, 2023 at 3:04 PM Andreas Rheinhardt <
andreas.rheinhardt@outlook.com> wrote:

> Nicolas George:
> > Andreas Rheinhardt (12023-09-27):
> >> Then you could simply reuse the code inside libavformat.
> >
> > Do you finally support merging the libraries then?
> >
> > Because otherwise, using from libavformat code for an individual
> > component of libavcodec requires adding a new avpriv function.
> >
>
> What I meant was: He shall write a simple function which reads from the
> input, determines the size of the packet, allocates and reads the actual
> packet (thereby avoiding memcpy's) and sets the codec parameters based
> upon the input (changes may need to be propagated via side-data
> updates). This is supposed to do what the parser does and it is supposed
> to stay completely inside libavformat to be reused by e.g. the Wav
> demuxer if needed. There is no need for a separate copy of this code
> inside libavcodec, so whether the libraries are split or not is
> irrelevant here.
>

How many demuxer and/or decoders have you wrote as of today? 0/0.
So you do not know what you talk about.

I never block your intrusive changes and I could on same principles like
you can mine and be much
less kind and forgetting like you too.


> - Andreas
>
> _______________________________________________
> 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".
>
Michael Niedermayer Sept. 27, 2023, 6:37 p.m. UTC | #18
On Wed, Sep 27, 2023 at 03:00:35PM +0200, Paul B Mahol wrote:
> On Wed, Sep 27, 2023 at 2:57 PM Nicolas George <george@nsup.org> wrote:
> 
> > Paul B Mahol (12023-09-27):
> > > I think that having parser is much more useful.
> >
> > Having a parser when it can be done without is a waste of code and
> > resources.
> >
> > Do not push like that.
> >
> 
> As you never pushed anything marginally useful to codebase, I'm free to

6 Code of Conduct
Be friendly and respectful towards others and third parties. Treat others the way you yourself want to be treated.
Be considerate. Not everyone shares the same viewpoint and priorities as you do. Different opinions and interpretations help the project. Looking at issues from a different perspective assists development.
Do not assume malice for things that can be attributed to incompetence. Even if it is malice, it’s rarely good to start with that as initial assumption.
Stay friendly even if someone acts contrarily. Everyone has a bad day once in a while. If you yourself have a bad day or are angry then try to take a break and reply once you are calm and without anger if you have to.
Try to help other team members and cooperate if you can.
The goal of software development is to create technical excellence, not for any individual to be better and "win" against the others. Large software projects are only possible and successful through teamwork.
If someone struggles do not put them down. Give them a helping hand instead and point them in the right direction.
Finally, keep in mind the immortal words of Bill and Ted, "Be excellent to each other."

Thank you

[...]
Paul B Mahol Sept. 27, 2023, 7:59 p.m. UTC | #19
On 9/27/23, Michael Niedermayer <michael@niedermayer.cc> wrote:
> On Wed, Sep 27, 2023 at 03:00:35PM +0200, Paul B Mahol wrote:
>> On Wed, Sep 27, 2023 at 2:57 PM Nicolas George <george@nsup.org> wrote:
>>
>> > Paul B Mahol (12023-09-27):
>> > > I think that having parser is much more useful.
>> >
>> > Having a parser when it can be done without is a waste of code and
>> > resources.
>> >
>> > Do not push like that.
>> >
>>
>> As you never pushed anything marginally useful to codebase, I'm free to
>
> 6 Code of Conduct
> Be friendly and respectful towards others and third parties. Treat others
> the way you yourself want to be treated.
> Be considerate. Not everyone shares the same viewpoint and priorities as you
> do. Different opinions and interpretations help the project. Looking at
> issues from a different perspective assists development.
> Do not assume malice for things that can be attributed to incompetence. Even
> if it is malice, it’s rarely good to start with that as initial assumption.
> Stay friendly even if someone acts contrarily. Everyone has a bad day once
> in a while. If you yourself have a bad day or are angry then try to take a
> break and reply once you are calm and without anger if you have to.
> Try to help other team members and cooperate if you can.
> The goal of software development is to create technical excellence, not for
> any individual to be better and "win" against the others. Large software
> projects are only possible and successful through teamwork.
> If someone struggles do not put them down. Give them a helping hand instead
> and point them in the right direction.
> Finally, keep in mind the immortal words of Bill and Ted, "Be excellent to
> each other."
>
> Thank you

Thanks, will push patch set in next 12h.

>
> [...]
> --
> Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> The greatest way to live with honor in this world is to be what we pretend
> to be. -- Socrates
>
Paul B Mahol Oct. 6, 2023, 11:54 a.m. UTC | #20
On 9/27/23, Paul B Mahol <onemda@gmail.com> wrote:
> On 9/27/23, Michael Niedermayer <michael@niedermayer.cc> wrote:
>> On Wed, Sep 27, 2023 at 03:00:35PM +0200, Paul B Mahol wrote:
>>> On Wed, Sep 27, 2023 at 2:57 PM Nicolas George <george@nsup.org> wrote:
>>>
>>> > Paul B Mahol (12023-09-27):
>>> > > I think that having parser is much more useful.
>>> >
>>> > Having a parser when it can be done without is a waste of code and
>>> > resources.
>>> >
>>> > Do not push like that.
>>> >
>>>
>>> As you never pushed anything marginally useful to codebase, I'm free to
>>
>> 6 Code of Conduct
>> Be friendly and respectful towards others and third parties. Treat others
>> the way you yourself want to be treated.
>> Be considerate. Not everyone shares the same viewpoint and priorities as
>> you
>> do. Different opinions and interpretations help the project. Looking at
>> issues from a different perspective assists development.
>> Do not assume malice for things that can be attributed to incompetence.
>> Even
>> if it is malice, it’s rarely good to start with that as initial
>> assumption.
>> Stay friendly even if someone acts contrarily. Everyone has a bad day
>> once
>> in a while. If you yourself have a bad day or are angry then try to take
>> a
>> break and reply once you are calm and without anger if you have to.
>> Try to help other team members and cooperate if you can.
>> The goal of software development is to create technical excellence, not
>> for
>> any individual to be better and "win" against the others. Large software
>> projects are only possible and successful through teamwork.
>> If someone struggles do not put them down. Give them a helping hand
>> instead
>> and point them in the right direction.
>> Finally, keep in mind the immortal words of Bill and Ted, "Be excellent
>> to
>> each other."
>>
>> Thank you
>
> Thanks, will push patch set in next 12h.
>

Oh, forgot to push, pushing soon.
diff mbox series

Patch

From 1bf5a9170745cdcf25df9e144fd31bb172afdbd1 Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda@gmail.com>
Date: Sat, 23 Sep 2023 16:38:35 +0200
Subject: [PATCH 1/2] avformat: add QOA demuxer

Signed-off-by: Paul B Mahol <onemda@gmail.com>
---
 libavformat/Makefile     |  1 +
 libavformat/allformats.c |  1 +
 libavformat/qoadec.c     | 83 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 85 insertions(+)
 create mode 100644 libavformat/qoadec.c

diff --git a/libavformat/Makefile b/libavformat/Makefile
index 329055ccfd..2db83aff81 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -484,6 +484,7 @@  OBJS-$(CONFIG_PP_BNK_DEMUXER)            += pp_bnk.o
 OBJS-$(CONFIG_PVA_DEMUXER)               += pva.o
 OBJS-$(CONFIG_PVF_DEMUXER)               += pvfdec.o pcm.o
 OBJS-$(CONFIG_QCP_DEMUXER)               += qcp.o
+OBJS-$(CONFIG_QOA_DEMUXER)               += qoadec.o
 OBJS-$(CONFIG_R3D_DEMUXER)               += r3d.o
 OBJS-$(CONFIG_RAWVIDEO_DEMUXER)          += rawvideodec.o
 OBJS-$(CONFIG_RAWVIDEO_MUXER)            += rawenc.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index d4b505a5a3..c8bb4e3866 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -383,6 +383,7 @@  extern const FFOutputFormat ff_psp_muxer;
 extern const AVInputFormat  ff_pva_demuxer;
 extern const AVInputFormat  ff_pvf_demuxer;
 extern const AVInputFormat  ff_qcp_demuxer;
+extern const AVInputFormat  ff_qoa_demuxer;
 extern const AVInputFormat  ff_r3d_demuxer;
 extern const AVInputFormat  ff_rawvideo_demuxer;
 extern const FFOutputFormat ff_rawvideo_muxer;
diff --git a/libavformat/qoadec.c b/libavformat/qoadec.c
new file mode 100644
index 0000000000..228e08cee8
--- /dev/null
+++ b/libavformat/qoadec.c
@@ -0,0 +1,83 @@ 
+/*
+ * QOA demuxer
+ *
+ * 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 "avformat.h"
+#include "avio_internal.h"
+#include "internal.h"
+#include "rawdec.h"
+#include "libavutil/intreadwrite.h"
+
+static int qoa_probe(const AVProbeData *p)
+{
+    if ((p->buf_size < 16) ||
+        (AV_RB32(p->buf) != MKBETAG('q','o','a','f')) ||
+        (AV_RB32(p->buf + 4) == 0) ||
+        (p->buf[8] == 0) ||
+        (AV_RB24(p->buf + 9) == 0) ||
+        (AV_RB16(p->buf + 12) == 0) ||
+        (AV_RB16(p->buf + 14) == 0))
+        return 0;
+    return AVPROBE_SCORE_MAX;
+}
+
+static int qoa_read_header(AVFormatContext *s)
+{
+    AVIOContext *pb = s->pb;
+    AVStream *st;
+
+    st = avformat_new_stream(s, NULL);
+    if (!st)
+        return AVERROR(ENOMEM);
+
+    avio_skip(pb, 4);
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = AV_CODEC_ID_QOA;
+    ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL_RAW;
+    st->duration = avio_rb32(pb);
+    st->start_time = 0;
+
+    ffio_ensure_seekback(pb, 4);
+    st->codecpar->ch_layout.nb_channels = avio_r8(pb);
+    if (st->codecpar->ch_layout.nb_channels == 0)
+        return AVERROR_INVALIDDATA;
+
+    st->codecpar->sample_rate = avio_rb24(pb);
+    if (st->codecpar->sample_rate == 0)
+        return AVERROR_INVALIDDATA;
+
+    avio_seek(pb, -4, SEEK_CUR);
+
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
+
+    return 0;
+}
+
+const AVInputFormat ff_qoa_demuxer = {
+    .name           = "qoa",
+    .long_name      = NULL_IF_CONFIG_SMALL("raw QOA"),
+    .read_probe     = qoa_probe,
+    .read_header    = qoa_read_header,
+    .read_packet    = ff_raw_read_partial_packet,
+    .flags          = AVFMT_GENERIC_INDEX,
+    .extensions     = "qoa",
+    .raw_codec_id   = AV_CODEC_ID_QOA,
+    .priv_data_size = sizeof(FFRawDemuxerContext),
+    .priv_class     = &ff_raw_demuxer_class,
+};
-- 
2.42.0