Re: [FFmpeg-devel] [PATCH] OSQ lossless audio format support

2023-08-31 Thread Paul B Mahol
Gonna push soon.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

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


Re: [FFmpeg-devel] [PATCH] OSQ lossless audio format support

2023-08-29 Thread Andreas Rheinhardt
Paul B Mahol:
> +st->codecpar->sample_rate = AV_RL32(st->codecpar->extradata + 4);
> +if (st->codecpar->sample_rate <= 0)
> +return AVERROR_INVALIDDATA;
> +av_channel_layout_uninit(&st->codecpar->ch_layout);

Unnecessary: This channel layout belongs to an AVCodecParameters from a
freshly created AVStream; of course the channel layout is equivalent to
an uninited one.

> +st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
> +st->codecpar->ch_layout.nb_channels = st->codecpar->extradata[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-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH] OSQ lossless audio format support

2023-08-29 Thread Paul B Mahol
Now with always bitexact output and other improvements and fixes.
From 208265707d57dbc14fec886629307c239f01090b Mon Sep 17 00:00:00 2001
From: Paul B Mahol 
Date: Tue, 27 Jun 2023 19:51:54 +0200
Subject: [PATCH 2/2] avformat: add OSQ demuxer

Signed-off-by: Paul B Mahol 
---
 libavformat/Makefile |   1 +
 libavformat/allformats.c |   1 +
 libavformat/osq.c| 119 +++
 3 files changed, 121 insertions(+)
 create mode 100644 libavformat/osq.c

diff --git a/libavformat/Makefile b/libavformat/Makefile
index bd78c206b9..1c8c965a74 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -433,6 +433,7 @@ OBJS-$(CONFIG_OMA_DEMUXER)   += omadec.o pcm.o oma.o
 OBJS-$(CONFIG_OMA_MUXER) += omaenc.o rawenc.o oma.o id3v2enc.o
 OBJS-$(CONFIG_OPUS_MUXER)+= oggenc.o \
 vorbiscomment.o
+OBJS-$(CONFIG_OSQ_DEMUXER)   += osq.o rawdec.o
 OBJS-$(CONFIG_PAF_DEMUXER)   += paf.o
 OBJS-$(CONFIG_PCM_ALAW_DEMUXER)  += pcmdec.o pcm.o
 OBJS-$(CONFIG_PCM_ALAW_MUXER)+= pcmenc.o rawenc.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index 6324952bd2..f4210e4932 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -331,6 +331,7 @@ extern const FFOutputFormat ff_ogv_muxer;
 extern const AVInputFormat  ff_oma_demuxer;
 extern const FFOutputFormat ff_oma_muxer;
 extern const FFOutputFormat ff_opus_muxer;
+extern const AVInputFormat  ff_osq_demuxer;
 extern const AVInputFormat  ff_paf_demuxer;
 extern const AVInputFormat  ff_pcm_alaw_demuxer;
 extern const FFOutputFormat ff_pcm_alaw_muxer;
diff --git a/libavformat/osq.c b/libavformat/osq.c
new file mode 100644
index 00..363c8a3f42
--- /dev/null
+++ b/libavformat/osq.c
@@ -0,0 +1,119 @@
+/*
+ * OSQ demuxer
+ * Copyright (c) 2023 Paul B Mahol
+ *
+ * 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/intreadwrite.h"
+#include "avio_internal.h"
+#include "avformat.h"
+#include "demux.h"
+#include "internal.h"
+#include "rawdec.h"
+
+static int osq_probe(const AVProbeData *p)
+{
+if (AV_RL32(p->buf) != MKTAG('O','S','Q',' '))
+return 0;
+if (AV_RL32(p->buf + 4) != 48)
+return 0;
+if (AV_RL16(p->buf + 8) != 1)
+return 0;
+if (p->buf[10] == 0)
+return 0;
+if (p->buf[11] == 0)
+return 0;
+if (AV_RL32(p->buf + 12) == 0)
+return 0;
+if (AV_RL16(p->buf + 16) == 0)
+return 0;
+
+return AVPROBE_SCORE_MAX;
+}
+
+static int osq_read_header(AVFormatContext *s)
+{
+uint32_t t, size;
+AVStream *st;
+int ret;
+
+t = avio_rl32(s->pb);
+if (t != MKTAG('O','S','Q',' '))
+return AVERROR_INVALIDDATA;
+
+size = avio_rl32(s->pb);
+if (size != 48)
+return AVERROR_INVALIDDATA;
+
+st = avformat_new_stream(s, NULL);
+if (!st)
+return AVERROR(ENOMEM);
+if ((ret = ff_get_extradata(s, st->codecpar, s->pb, size)) < 0)
+return ret;
+
+t = avio_rl32(s->pb);
+if (t != MKTAG('R','I','F','F'))
+return AVERROR_INVALIDDATA;
+avio_skip(s->pb, 8);
+
+t = avio_rl32(s->pb);
+if (t != MKTAG('f','m','t',' '))
+return AVERROR_INVALIDDATA;
+size = avio_rl32(s->pb);
+avio_skip(s->pb, size);
+
+t = avio_rl32(s->pb);
+size = avio_rl32(s->pb);
+while (t != MKTAG('d','a','t','a')) {
+avio_skip(s->pb, size);
+
+t = avio_rl32(s->pb);
+size = avio_rl32(s->pb);
+if (avio_feof(s->pb))
+return AVERROR_INVALIDDATA;
+}
+
+st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+st->codecpar->codec_id= AV_CODEC_ID_OSQ;
+st->codecpar->sample_rate = AV_RL32(st->codecpar->extradata + 4);
+if (st->codecpar->sample_rate <= 0)
+return AVERROR_INVALIDDATA;
+av_channel_layout_uninit(&st->codecpar->ch_layout);
+st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+st->codecpar->ch_layout.nb_channels = st->codecpar->extradata[3];
+if (st->codecpar->ch_layout.nb_channels == 0)
+return AVERROR_INVALIDDATA;
+st->start_time = 0;
+st->duration = AV_RL32(st->codecpar->extradata + 16);
+avpriv_set_

Re: [FFmpeg-devel] [PATCH] OSQ lossless audio format support

2023-08-25 Thread Paul B Mahol
On Fri, Aug 25, 2023 at 6:42 PM James Almer  wrote:

> On 8/25/2023 1:28 PM, Paul B Mahol wrote:
> > On Fri, Aug 25, 2023 at 5:57 PM James Almer  wrote:
> >
> >> On 8/24/2023 7:06 PM, Paul B Mahol wrote:
> >>> On Thu, Aug 24, 2023 at 11:51 PM James Almer 
> wrote:
> >>>
>  On 8/24/2023 6:11 PM, Paul B Mahol wrote:
> > On Thu, Aug 24, 2023 at 11:00 PM James Almer 
> >> wrote:
> >
> >> On 8/24/2023 6:52 AM, Paul B Mahol wrote:
> >>> +static int osq_receive_frame(AVCodecContext *avctx, AVFrame
> *frame)
> >>> +{
> >>> +OSQContext *s = avctx->priv_data;
> >>> +GetBitContext *gb = &s->gb;
> >>> +int ret, n;
> >>> +
> >>> +while (s->bitstream_size < s->max_framesize) {
> >>> +int size;
> >>> +
> >>> +if (!s->pkt->data) {
> >>> +ret = ff_decode_get_packet(avctx, s->pkt);
> >>> +if (ret == AVERROR_EOF && s->bitstream_size > 0)
> >>> +break;
> >>> +if (ret < 0)
> >>> +return ret;
> >>> +}
> >>> +
> >>> +size = FFMIN(s->pkt->size - s->pkt_offset,
> s->max_framesize
> >> -
> >> s->bitstream_size);
> >>> +memcpy(s->bitstream + s->bitstream_size, s->pkt->data +
> >> s->pkt_offset, size);
> >>> +s->bitstream_size += size;
> >>> +s->pkt_offset += size;
> >>> +
> >>> +if (s->pkt_offset == s->pkt->size) {
> >>> +av_packet_unref(s->pkt);
> >>> +s->pkt_offset = 0;
> >>> +}
> >>
> >> This looks like you're assembling a packet of max_framesize bytes.
> You
> >> should instead do that in a parser, and ensure here that the packets
> >> fed
> >> to this decoder are <= max_framesize.
> >>
> >>> +}
> >>> +
> >>> +frame->nb_samples = FFMIN(s->frame_samples, s->nb_samples);
> >>> +if (frame->nb_samples <= 0)
> >>> +return AVERROR_EOF;
> >>> +
> >>> +if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
> >>> +goto fail;
> >>> +
> >>> +if ((ret = init_get_bits8(gb, s->bitstream,
> s->bitstream_size))
> >> <
>  0)
> >>> +goto fail;
> >>> +
> >>> +if ((ret = osq_decode_block(avctx, frame)) < 0)
> >>> +goto fail;
> >>> +
> >>> +s->nb_samples -= frame->nb_samples;
> >>> +
> >>> +n = get_bits_count(gb) / 8;
> >>> +if (n > s->bitstream_size) {
> >>> +ret = AVERROR_INVALIDDATA;
> >>> +goto fail;
> >>> +}
> >>> +
> >>> +memmove(s->bitstream, &s->bitstream[n], s->bitstream_size -
> n);
> >>> +s->bitstream_size -= n;
> >>> +
> >>> +return 0;
> >>> +
> >>> +fail:
> >>> +s->bitstream_size = 0;
> >>> +s->pkt_offset = 0;
> >>> +av_packet_unref(s->pkt);
> >>> +
> >>> +return ret;
> >>> +}
> >>> +
> >>> +const AVInputFormat ff_osq_demuxer = {
> >>> +.name   = "osq",
> >>> +.long_name  = NULL_IF_CONFIG_SMALL("raw OSQ"),
> >>> +.read_probe = osq_probe,
> >>> +.read_header= osq_read_header,
> >>> +.read_packet= ff_raw_read_partial_packet,
> >>
> >> Instead of sending an arbitrarily sized packet (1024 bytes as of
> now),
> >> you should set codecpar->frame_size and propagate packets with that
> >> amount of bytes instead.
> >> A parser is still needed, though, for non seekable input (a pipe).
> And
> >> in case the decoder is fed with non lavf input.
> >>
> >
> > Format is not seekable, packet sizes are nowhere stored in .osq
> files.
> 
>  Same case as raw formats like H.264. No packet sizes, no seekability
>  without having parsed the entire sequence to build a list of seek
>  points, etc. A parser has to assemble access units.
> 
> >>>
> >>> But there is no any info how to assemble anything here, unless
> >>> you propose decoding inside parser?
> >>>
> >>>
> >>>
> 
> >
> > Think of this format like APAC/BONK/WAVARC but just no need to keep
>  unused
> > bits from previous decoded data/packet.
> > With this fact, parser makes no sense to do.
> 
>  You know that frame_size is (frame_samples_per_channel * 16 + 1024) *
>  channels. A parser can work with that (Look at gsm parser for example.
>  There may be others too).
> 
> >>>
> >>> There is reason why variable is called max_framesize.
> >>>
> >>> You should not propagate truncated data in 1024 byte chunks, and the
>  decoder should not expect that either.
> 
> >>>
> >>> Nothing gets truncated. That is just worst case scenario size for
> packet.
> >>> In another words, size of packet can be anything between 33 and
> >>> max_framesize.
> >>
> >> By truncated i mean the demuxer propagates arbitrary 1024 byte sized
> >> packets. And in the decoder you're asse

Re: [FFmpeg-devel] [PATCH] OSQ lossless audio format support

2023-08-25 Thread James Almer

On 8/25/2023 1:28 PM, Paul B Mahol wrote:

On Fri, Aug 25, 2023 at 5:57 PM James Almer  wrote:


On 8/24/2023 7:06 PM, Paul B Mahol wrote:

On Thu, Aug 24, 2023 at 11:51 PM James Almer  wrote:


On 8/24/2023 6:11 PM, Paul B Mahol wrote:

On Thu, Aug 24, 2023 at 11:00 PM James Almer 

wrote:



On 8/24/2023 6:52 AM, Paul B Mahol wrote:

+static int osq_receive_frame(AVCodecContext *avctx, AVFrame *frame)
+{
+OSQContext *s = avctx->priv_data;
+GetBitContext *gb = &s->gb;
+int ret, n;
+
+while (s->bitstream_size < s->max_framesize) {
+int size;
+
+if (!s->pkt->data) {
+ret = ff_decode_get_packet(avctx, s->pkt);
+if (ret == AVERROR_EOF && s->bitstream_size > 0)
+break;
+if (ret < 0)
+return ret;
+}
+
+size = FFMIN(s->pkt->size - s->pkt_offset, s->max_framesize

-

s->bitstream_size);

+memcpy(s->bitstream + s->bitstream_size, s->pkt->data +

s->pkt_offset, size);

+s->bitstream_size += size;
+s->pkt_offset += size;
+
+if (s->pkt_offset == s->pkt->size) {
+av_packet_unref(s->pkt);
+s->pkt_offset = 0;
+}


This looks like you're assembling a packet of max_framesize bytes. You
should instead do that in a parser, and ensure here that the packets

fed

to this decoder are <= max_framesize.


+}
+
+frame->nb_samples = FFMIN(s->frame_samples, s->nb_samples);
+if (frame->nb_samples <= 0)
+return AVERROR_EOF;
+
+if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
+goto fail;
+
+if ((ret = init_get_bits8(gb, s->bitstream, s->bitstream_size))

<

0)

+goto fail;
+
+if ((ret = osq_decode_block(avctx, frame)) < 0)
+goto fail;
+
+s->nb_samples -= frame->nb_samples;
+
+n = get_bits_count(gb) / 8;
+if (n > s->bitstream_size) {
+ret = AVERROR_INVALIDDATA;
+goto fail;
+}
+
+memmove(s->bitstream, &s->bitstream[n], s->bitstream_size - n);
+s->bitstream_size -= n;
+
+return 0;
+
+fail:
+s->bitstream_size = 0;
+s->pkt_offset = 0;
+av_packet_unref(s->pkt);
+
+return ret;
+}
+
+const AVInputFormat ff_osq_demuxer = {
+.name   = "osq",
+.long_name  = NULL_IF_CONFIG_SMALL("raw OSQ"),
+.read_probe = osq_probe,
+.read_header= osq_read_header,
+.read_packet= ff_raw_read_partial_packet,


Instead of sending an arbitrarily sized packet (1024 bytes as of now),
you should set codecpar->frame_size and propagate packets with that
amount of bytes instead.
A parser is still needed, though, for non seekable input (a pipe). And
in case the decoder is fed with non lavf input.



Format is not seekable, packet sizes are nowhere stored in .osq files.


Same case as raw formats like H.264. No packet sizes, no seekability
without having parsed the entire sequence to build a list of seek
points, etc. A parser has to assemble access units.



But there is no any info how to assemble anything here, unless
you propose decoding inside parser?







Think of this format like APAC/BONK/WAVARC but just no need to keep

unused

bits from previous decoded data/packet.
With this fact, parser makes no sense to do.


You know that frame_size is (frame_samples_per_channel * 16 + 1024) *
channels. A parser can work with that (Look at gsm parser for example.
There may be others too).



There is reason why variable is called max_framesize.

You should not propagate truncated data in 1024 byte chunks, and the

decoder should not expect that either.



Nothing gets truncated. That is just worst case scenario size for packet.
In another words, size of packet can be anything between 33 and
max_framesize.


By truncated i mean the demuxer propagates arbitrary 1024 byte sized
packets. And in the decoder you're assembling a buffer of max_framesize
in osq_receive_frame() by requesting packets until you reach that size
or EOF, whatever comes first, before calling osq_decode_block(). So
unless you hit EOF, it will always be max_framesize. That's what i say
should be done in a simple, small parser.



I fully understand you, but your reasoning is critically flawed.
And I have no time to educated an uneducated.


Not insulting people will help your arguments.



For The Last Time:

Even if parser does that what you propose, decoder would need to keep own
internal
buffer again and than memmove() bytes around.

And even if parser is implemented that would effectively break other
possible containers different
than .osq - such containers would properly split data into packets and my
decoder would still work in such scenario but
your proposed way would only force such containers to blacklist your
proposed parser.


You know a parser is doable and the proper approach. With frame_samples 
and the first part of osq_decode_block() you can get it going. But do 
whatever you want.

___
ffmpeg-devel mailing list
ffmpeg

Re: [FFmpeg-devel] [PATCH] OSQ lossless audio format support

2023-08-25 Thread Paul B Mahol
On Fri, Aug 25, 2023 at 5:57 PM James Almer  wrote:

> On 8/24/2023 7:06 PM, Paul B Mahol wrote:
> > On Thu, Aug 24, 2023 at 11:51 PM James Almer  wrote:
> >
> >> On 8/24/2023 6:11 PM, Paul B Mahol wrote:
> >>> On Thu, Aug 24, 2023 at 11:00 PM James Almer 
> wrote:
> >>>
>  On 8/24/2023 6:52 AM, Paul B Mahol wrote:
> > +static int osq_receive_frame(AVCodecContext *avctx, AVFrame *frame)
> > +{
> > +OSQContext *s = avctx->priv_data;
> > +GetBitContext *gb = &s->gb;
> > +int ret, n;
> > +
> > +while (s->bitstream_size < s->max_framesize) {
> > +int size;
> > +
> > +if (!s->pkt->data) {
> > +ret = ff_decode_get_packet(avctx, s->pkt);
> > +if (ret == AVERROR_EOF && s->bitstream_size > 0)
> > +break;
> > +if (ret < 0)
> > +return ret;
> > +}
> > +
> > +size = FFMIN(s->pkt->size - s->pkt_offset, s->max_framesize
> -
>  s->bitstream_size);
> > +memcpy(s->bitstream + s->bitstream_size, s->pkt->data +
>  s->pkt_offset, size);
> > +s->bitstream_size += size;
> > +s->pkt_offset += size;
> > +
> > +if (s->pkt_offset == s->pkt->size) {
> > +av_packet_unref(s->pkt);
> > +s->pkt_offset = 0;
> > +}
> 
>  This looks like you're assembling a packet of max_framesize bytes. You
>  should instead do that in a parser, and ensure here that the packets
> fed
>  to this decoder are <= max_framesize.
> 
> > +}
> > +
> > +frame->nb_samples = FFMIN(s->frame_samples, s->nb_samples);
> > +if (frame->nb_samples <= 0)
> > +return AVERROR_EOF;
> > +
> > +if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
> > +goto fail;
> > +
> > +if ((ret = init_get_bits8(gb, s->bitstream, s->bitstream_size))
> <
> >> 0)
> > +goto fail;
> > +
> > +if ((ret = osq_decode_block(avctx, frame)) < 0)
> > +goto fail;
> > +
> > +s->nb_samples -= frame->nb_samples;
> > +
> > +n = get_bits_count(gb) / 8;
> > +if (n > s->bitstream_size) {
> > +ret = AVERROR_INVALIDDATA;
> > +goto fail;
> > +}
> > +
> > +memmove(s->bitstream, &s->bitstream[n], s->bitstream_size - n);
> > +s->bitstream_size -= n;
> > +
> > +return 0;
> > +
> > +fail:
> > +s->bitstream_size = 0;
> > +s->pkt_offset = 0;
> > +av_packet_unref(s->pkt);
> > +
> > +return ret;
> > +}
> > +
> > +const AVInputFormat ff_osq_demuxer = {
> > +.name   = "osq",
> > +.long_name  = NULL_IF_CONFIG_SMALL("raw OSQ"),
> > +.read_probe = osq_probe,
> > +.read_header= osq_read_header,
> > +.read_packet= ff_raw_read_partial_packet,
> 
>  Instead of sending an arbitrarily sized packet (1024 bytes as of now),
>  you should set codecpar->frame_size and propagate packets with that
>  amount of bytes instead.
>  A parser is still needed, though, for non seekable input (a pipe). And
>  in case the decoder is fed with non lavf input.
> 
> >>>
> >>> Format is not seekable, packet sizes are nowhere stored in .osq files.
> >>
> >> Same case as raw formats like H.264. No packet sizes, no seekability
> >> without having parsed the entire sequence to build a list of seek
> >> points, etc. A parser has to assemble access units.
> >>
> >
> > But there is no any info how to assemble anything here, unless
> > you propose decoding inside parser?
> >
> >
> >
> >>
> >>>
> >>> Think of this format like APAC/BONK/WAVARC but just no need to keep
> >> unused
> >>> bits from previous decoded data/packet.
> >>> With this fact, parser makes no sense to do.
> >>
> >> You know that frame_size is (frame_samples_per_channel * 16 + 1024) *
> >> channels. A parser can work with that (Look at gsm parser for example.
> >> There may be others too).
> >>
> >
> > There is reason why variable is called max_framesize.
> >
> > You should not propagate truncated data in 1024 byte chunks, and the
> >> decoder should not expect that either.
> >>
> >
> > Nothing gets truncated. That is just worst case scenario size for packet.
> > In another words, size of packet can be anything between 33 and
> > max_framesize.
>
> By truncated i mean the demuxer propagates arbitrary 1024 byte sized
> packets. And in the decoder you're assembling a buffer of max_framesize
> in osq_receive_frame() by requesting packets until you reach that size
> or EOF, whatever comes first, before calling osq_decode_block(). So
> unless you hit EOF, it will always be max_framesize. That's what i say
> should be done in a simple, small parser.
>

I fully understand you, but your reasoning is critically flawed.
And I have no time to educated an

Re: [FFmpeg-devel] [PATCH] OSQ lossless audio format support

2023-08-25 Thread James Almer

On 8/24/2023 7:06 PM, Paul B Mahol wrote:

On Thu, Aug 24, 2023 at 11:51 PM James Almer  wrote:


On 8/24/2023 6:11 PM, Paul B Mahol wrote:

On Thu, Aug 24, 2023 at 11:00 PM James Almer  wrote:


On 8/24/2023 6:52 AM, Paul B Mahol wrote:

+static int osq_receive_frame(AVCodecContext *avctx, AVFrame *frame)
+{
+OSQContext *s = avctx->priv_data;
+GetBitContext *gb = &s->gb;
+int ret, n;
+
+while (s->bitstream_size < s->max_framesize) {
+int size;
+
+if (!s->pkt->data) {
+ret = ff_decode_get_packet(avctx, s->pkt);
+if (ret == AVERROR_EOF && s->bitstream_size > 0)
+break;
+if (ret < 0)
+return ret;
+}
+
+size = FFMIN(s->pkt->size - s->pkt_offset, s->max_framesize -

s->bitstream_size);

+memcpy(s->bitstream + s->bitstream_size, s->pkt->data +

s->pkt_offset, size);

+s->bitstream_size += size;
+s->pkt_offset += size;
+
+if (s->pkt_offset == s->pkt->size) {
+av_packet_unref(s->pkt);
+s->pkt_offset = 0;
+}


This looks like you're assembling a packet of max_framesize bytes. You
should instead do that in a parser, and ensure here that the packets fed
to this decoder are <= max_framesize.


+}
+
+frame->nb_samples = FFMIN(s->frame_samples, s->nb_samples);
+if (frame->nb_samples <= 0)
+return AVERROR_EOF;
+
+if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
+goto fail;
+
+if ((ret = init_get_bits8(gb, s->bitstream, s->bitstream_size)) <

0)

+goto fail;
+
+if ((ret = osq_decode_block(avctx, frame)) < 0)
+goto fail;
+
+s->nb_samples -= frame->nb_samples;
+
+n = get_bits_count(gb) / 8;
+if (n > s->bitstream_size) {
+ret = AVERROR_INVALIDDATA;
+goto fail;
+}
+
+memmove(s->bitstream, &s->bitstream[n], s->bitstream_size - n);
+s->bitstream_size -= n;
+
+return 0;
+
+fail:
+s->bitstream_size = 0;
+s->pkt_offset = 0;
+av_packet_unref(s->pkt);
+
+return ret;
+}
+
+const AVInputFormat ff_osq_demuxer = {
+.name   = "osq",
+.long_name  = NULL_IF_CONFIG_SMALL("raw OSQ"),
+.read_probe = osq_probe,
+.read_header= osq_read_header,
+.read_packet= ff_raw_read_partial_packet,


Instead of sending an arbitrarily sized packet (1024 bytes as of now),
you should set codecpar->frame_size and propagate packets with that
amount of bytes instead.
A parser is still needed, though, for non seekable input (a pipe). And
in case the decoder is fed with non lavf input.



Format is not seekable, packet sizes are nowhere stored in .osq files.


Same case as raw formats like H.264. No packet sizes, no seekability
without having parsed the entire sequence to build a list of seek
points, etc. A parser has to assemble access units.



But there is no any info how to assemble anything here, unless
you propose decoding inside parser?







Think of this format like APAC/BONK/WAVARC but just no need to keep

unused

bits from previous decoded data/packet.
With this fact, parser makes no sense to do.


You know that frame_size is (frame_samples_per_channel * 16 + 1024) *
channels. A parser can work with that (Look at gsm parser for example.
There may be others too).



There is reason why variable is called max_framesize.

You should not propagate truncated data in 1024 byte chunks, and the

decoder should not expect that either.



Nothing gets truncated. That is just worst case scenario size for packet.
In another words, size of packet can be anything between 33 and
max_framesize.


By truncated i mean the demuxer propagates arbitrary 1024 byte sized 
packets. And in the decoder you're assembling a buffer of max_framesize 
in osq_receive_frame() by requesting packets until you reach that size 
or EOF, whatever comes first, before calling osq_decode_block(). So 
unless you hit EOF, it will always be max_framesize. That's what i say 
should be done in a simple, small parser.











+.extensions = "osq",
+.flags  = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH |

AVFMT_NO_BYTE_SEEK | AVFMT_NOTIMESTAMPS,

+.raw_codec_id   = AV_CODEC_ID_OSQ,
+.priv_data_size = sizeof(FFRawDemuxerContext),
+.priv_class = &ff_raw_demuxer_class,
+};


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

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


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

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

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

To unsubscribe, visit

Re: [FFmpeg-devel] [PATCH] OSQ lossless audio format support

2023-08-24 Thread Paul B Mahol
On Thu, Aug 24, 2023 at 11:51 PM James Almer  wrote:

> On 8/24/2023 6:11 PM, Paul B Mahol wrote:
> > On Thu, Aug 24, 2023 at 11:00 PM James Almer  wrote:
> >
> >> On 8/24/2023 6:52 AM, Paul B Mahol wrote:
> >>> +static int osq_receive_frame(AVCodecContext *avctx, AVFrame *frame)
> >>> +{
> >>> +OSQContext *s = avctx->priv_data;
> >>> +GetBitContext *gb = &s->gb;
> >>> +int ret, n;
> >>> +
> >>> +while (s->bitstream_size < s->max_framesize) {
> >>> +int size;
> >>> +
> >>> +if (!s->pkt->data) {
> >>> +ret = ff_decode_get_packet(avctx, s->pkt);
> >>> +if (ret == AVERROR_EOF && s->bitstream_size > 0)
> >>> +break;
> >>> +if (ret < 0)
> >>> +return ret;
> >>> +}
> >>> +
> >>> +size = FFMIN(s->pkt->size - s->pkt_offset, s->max_framesize -
> >> s->bitstream_size);
> >>> +memcpy(s->bitstream + s->bitstream_size, s->pkt->data +
> >> s->pkt_offset, size);
> >>> +s->bitstream_size += size;
> >>> +s->pkt_offset += size;
> >>> +
> >>> +if (s->pkt_offset == s->pkt->size) {
> >>> +av_packet_unref(s->pkt);
> >>> +s->pkt_offset = 0;
> >>> +}
> >>
> >> This looks like you're assembling a packet of max_framesize bytes. You
> >> should instead do that in a parser, and ensure here that the packets fed
> >> to this decoder are <= max_framesize.
> >>
> >>> +}
> >>> +
> >>> +frame->nb_samples = FFMIN(s->frame_samples, s->nb_samples);
> >>> +if (frame->nb_samples <= 0)
> >>> +return AVERROR_EOF;
> >>> +
> >>> +if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
> >>> +goto fail;
> >>> +
> >>> +if ((ret = init_get_bits8(gb, s->bitstream, s->bitstream_size)) <
> 0)
> >>> +goto fail;
> >>> +
> >>> +if ((ret = osq_decode_block(avctx, frame)) < 0)
> >>> +goto fail;
> >>> +
> >>> +s->nb_samples -= frame->nb_samples;
> >>> +
> >>> +n = get_bits_count(gb) / 8;
> >>> +if (n > s->bitstream_size) {
> >>> +ret = AVERROR_INVALIDDATA;
> >>> +goto fail;
> >>> +}
> >>> +
> >>> +memmove(s->bitstream, &s->bitstream[n], s->bitstream_size - n);
> >>> +s->bitstream_size -= n;
> >>> +
> >>> +return 0;
> >>> +
> >>> +fail:
> >>> +s->bitstream_size = 0;
> >>> +s->pkt_offset = 0;
> >>> +av_packet_unref(s->pkt);
> >>> +
> >>> +return ret;
> >>> +}
> >>> +
> >>> +const AVInputFormat ff_osq_demuxer = {
> >>> +.name   = "osq",
> >>> +.long_name  = NULL_IF_CONFIG_SMALL("raw OSQ"),
> >>> +.read_probe = osq_probe,
> >>> +.read_header= osq_read_header,
> >>> +.read_packet= ff_raw_read_partial_packet,
> >>
> >> Instead of sending an arbitrarily sized packet (1024 bytes as of now),
> >> you should set codecpar->frame_size and propagate packets with that
> >> amount of bytes instead.
> >> A parser is still needed, though, for non seekable input (a pipe). And
> >> in case the decoder is fed with non lavf input.
> >>
> >
> > Format is not seekable, packet sizes are nowhere stored in .osq files.
>
> Same case as raw formats like H.264. No packet sizes, no seekability
> without having parsed the entire sequence to build a list of seek
> points, etc. A parser has to assemble access units.
>

But there is no any info how to assemble anything here, unless
you propose decoding inside parser?



>
> >
> > Think of this format like APAC/BONK/WAVARC but just no need to keep
> unused
> > bits from previous decoded data/packet.
> > With this fact, parser makes no sense to do.
>
> You know that frame_size is (frame_samples_per_channel * 16 + 1024) *
> channels. A parser can work with that (Look at gsm parser for example.
> There may be others too).
>

There is reason why variable is called max_framesize.

You should not propagate truncated data in 1024 byte chunks, and the
> decoder should not expect that either.
>

Nothing gets truncated. That is just worst case scenario size for packet.
In another words, size of packet can be anything between 33 and
max_framesize.


>
> >
> >
> >>> +.extensions = "osq",
> >>> +.flags  = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH |
> >> AVFMT_NO_BYTE_SEEK | AVFMT_NOTIMESTAMPS,
> >>> +.raw_codec_id   = AV_CODEC_ID_OSQ,
> >>> +.priv_data_size = sizeof(FFRawDemuxerContext),
> >>> +.priv_class = &ff_raw_demuxer_class,
> >>> +};
> >>
> >> ___
> >> ffmpeg-devel mailing list
> >> ffmpeg-devel@ffmpeg.org
> >> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >>
> >> To unsubscribe, visit link above, or email
> >> ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
> >>
> > ___
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >
> > To unsubscribe, visit link above, or email
> > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe

Re: [FFmpeg-devel] [PATCH] OSQ lossless audio format support

2023-08-24 Thread James Almer

On 8/24/2023 6:11 PM, Paul B Mahol wrote:

On Thu, Aug 24, 2023 at 11:00 PM James Almer  wrote:


On 8/24/2023 6:52 AM, Paul B Mahol wrote:

+static int osq_receive_frame(AVCodecContext *avctx, AVFrame *frame)
+{
+OSQContext *s = avctx->priv_data;
+GetBitContext *gb = &s->gb;
+int ret, n;
+
+while (s->bitstream_size < s->max_framesize) {
+int size;
+
+if (!s->pkt->data) {
+ret = ff_decode_get_packet(avctx, s->pkt);
+if (ret == AVERROR_EOF && s->bitstream_size > 0)
+break;
+if (ret < 0)
+return ret;
+}
+
+size = FFMIN(s->pkt->size - s->pkt_offset, s->max_framesize -

s->bitstream_size);

+memcpy(s->bitstream + s->bitstream_size, s->pkt->data +

s->pkt_offset, size);

+s->bitstream_size += size;
+s->pkt_offset += size;
+
+if (s->pkt_offset == s->pkt->size) {
+av_packet_unref(s->pkt);
+s->pkt_offset = 0;
+}


This looks like you're assembling a packet of max_framesize bytes. You
should instead do that in a parser, and ensure here that the packets fed
to this decoder are <= max_framesize.


+}
+
+frame->nb_samples = FFMIN(s->frame_samples, s->nb_samples);
+if (frame->nb_samples <= 0)
+return AVERROR_EOF;
+
+if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
+goto fail;
+
+if ((ret = init_get_bits8(gb, s->bitstream, s->bitstream_size)) < 0)
+goto fail;
+
+if ((ret = osq_decode_block(avctx, frame)) < 0)
+goto fail;
+
+s->nb_samples -= frame->nb_samples;
+
+n = get_bits_count(gb) / 8;
+if (n > s->bitstream_size) {
+ret = AVERROR_INVALIDDATA;
+goto fail;
+}
+
+memmove(s->bitstream, &s->bitstream[n], s->bitstream_size - n);
+s->bitstream_size -= n;
+
+return 0;
+
+fail:
+s->bitstream_size = 0;
+s->pkt_offset = 0;
+av_packet_unref(s->pkt);
+
+return ret;
+}
+
+const AVInputFormat ff_osq_demuxer = {
+.name   = "osq",
+.long_name  = NULL_IF_CONFIG_SMALL("raw OSQ"),
+.read_probe = osq_probe,
+.read_header= osq_read_header,
+.read_packet= ff_raw_read_partial_packet,


Instead of sending an arbitrarily sized packet (1024 bytes as of now),
you should set codecpar->frame_size and propagate packets with that
amount of bytes instead.
A parser is still needed, though, for non seekable input (a pipe). And
in case the decoder is fed with non lavf input.



Format is not seekable, packet sizes are nowhere stored in .osq files.


Same case as raw formats like H.264. No packet sizes, no seekability 
without having parsed the entire sequence to build a list of seek 
points, etc. A parser has to assemble access units.




Think of this format like APAC/BONK/WAVARC but just no need to keep unused
bits from previous decoded data/packet.
With this fact, parser makes no sense to do.


You know that frame_size is (frame_samples_per_channel * 16 + 1024) * 
channels. A parser can work with that (Look at gsm parser for example. 
There may be others too).
You should not propagate truncated data in 1024 byte chunks, and the 
decoder should not expect that either.






+.extensions = "osq",
+.flags  = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH |

AVFMT_NO_BYTE_SEEK | AVFMT_NOTIMESTAMPS,

+.raw_codec_id   = AV_CODEC_ID_OSQ,
+.priv_data_size = sizeof(FFRawDemuxerContext),
+.priv_class = &ff_raw_demuxer_class,
+};


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

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


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

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

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

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


Re: [FFmpeg-devel] [PATCH] OSQ lossless audio format support

2023-08-24 Thread Paul B Mahol
On Thu, Aug 24, 2023 at 11:00 PM James Almer  wrote:

> On 8/24/2023 6:52 AM, Paul B Mahol wrote:
> > +static int osq_receive_frame(AVCodecContext *avctx, AVFrame *frame)
> > +{
> > +OSQContext *s = avctx->priv_data;
> > +GetBitContext *gb = &s->gb;
> > +int ret, n;
> > +
> > +while (s->bitstream_size < s->max_framesize) {
> > +int size;
> > +
> > +if (!s->pkt->data) {
> > +ret = ff_decode_get_packet(avctx, s->pkt);
> > +if (ret == AVERROR_EOF && s->bitstream_size > 0)
> > +break;
> > +if (ret < 0)
> > +return ret;
> > +}
> > +
> > +size = FFMIN(s->pkt->size - s->pkt_offset, s->max_framesize -
> s->bitstream_size);
> > +memcpy(s->bitstream + s->bitstream_size, s->pkt->data +
> s->pkt_offset, size);
> > +s->bitstream_size += size;
> > +s->pkt_offset += size;
> > +
> > +if (s->pkt_offset == s->pkt->size) {
> > +av_packet_unref(s->pkt);
> > +s->pkt_offset = 0;
> > +}
>
> This looks like you're assembling a packet of max_framesize bytes. You
> should instead do that in a parser, and ensure here that the packets fed
> to this decoder are <= max_framesize.
>
> > +}
> > +
> > +frame->nb_samples = FFMIN(s->frame_samples, s->nb_samples);
> > +if (frame->nb_samples <= 0)
> > +return AVERROR_EOF;
> > +
> > +if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
> > +goto fail;
> > +
> > +if ((ret = init_get_bits8(gb, s->bitstream, s->bitstream_size)) < 0)
> > +goto fail;
> > +
> > +if ((ret = osq_decode_block(avctx, frame)) < 0)
> > +goto fail;
> > +
> > +s->nb_samples -= frame->nb_samples;
> > +
> > +n = get_bits_count(gb) / 8;
> > +if (n > s->bitstream_size) {
> > +ret = AVERROR_INVALIDDATA;
> > +goto fail;
> > +}
> > +
> > +memmove(s->bitstream, &s->bitstream[n], s->bitstream_size - n);
> > +s->bitstream_size -= n;
> > +
> > +return 0;
> > +
> > +fail:
> > +s->bitstream_size = 0;
> > +s->pkt_offset = 0;
> > +av_packet_unref(s->pkt);
> > +
> > +return ret;
> > +}
> > +
> > +const AVInputFormat ff_osq_demuxer = {
> > +.name   = "osq",
> > +.long_name  = NULL_IF_CONFIG_SMALL("raw OSQ"),
> > +.read_probe = osq_probe,
> > +.read_header= osq_read_header,
> > +.read_packet= ff_raw_read_partial_packet,
>
> Instead of sending an arbitrarily sized packet (1024 bytes as of now),
> you should set codecpar->frame_size and propagate packets with that
> amount of bytes instead.
> A parser is still needed, though, for non seekable input (a pipe). And
> in case the decoder is fed with non lavf input.
>

Format is not seekable, packet sizes are nowhere stored in .osq files.

Think of this format like APAC/BONK/WAVARC but just no need to keep unused
bits from previous decoded data/packet.
With this fact, parser makes no sense to do.


> > +.extensions = "osq",
> > +.flags  = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH |
> AVFMT_NO_BYTE_SEEK | AVFMT_NOTIMESTAMPS,
> > +.raw_codec_id   = AV_CODEC_ID_OSQ,
> > +.priv_data_size = sizeof(FFRawDemuxerContext),
> > +.priv_class = &ff_raw_demuxer_class,
> > +};
>
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
>
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

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


Re: [FFmpeg-devel] [PATCH] OSQ lossless audio format support

2023-08-24 Thread James Almer

On 8/24/2023 6:52 AM, Paul B Mahol wrote:

+static int osq_receive_frame(AVCodecContext *avctx, AVFrame *frame)
+{
+OSQContext *s = avctx->priv_data;
+GetBitContext *gb = &s->gb;
+int ret, n;
+
+while (s->bitstream_size < s->max_framesize) {
+int size;
+
+if (!s->pkt->data) {
+ret = ff_decode_get_packet(avctx, s->pkt);
+if (ret == AVERROR_EOF && s->bitstream_size > 0)
+break;
+if (ret < 0)
+return ret;
+}
+
+size = FFMIN(s->pkt->size - s->pkt_offset, s->max_framesize - 
s->bitstream_size);
+memcpy(s->bitstream + s->bitstream_size, s->pkt->data + s->pkt_offset, 
size);
+s->bitstream_size += size;
+s->pkt_offset += size;
+
+if (s->pkt_offset == s->pkt->size) {
+av_packet_unref(s->pkt);
+s->pkt_offset = 0;
+}


This looks like you're assembling a packet of max_framesize bytes. You 
should instead do that in a parser, and ensure here that the packets fed 
to this decoder are <= max_framesize.



+}
+
+frame->nb_samples = FFMIN(s->frame_samples, s->nb_samples);
+if (frame->nb_samples <= 0)
+return AVERROR_EOF;
+
+if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
+goto fail;
+
+if ((ret = init_get_bits8(gb, s->bitstream, s->bitstream_size)) < 0)
+goto fail;
+
+if ((ret = osq_decode_block(avctx, frame)) < 0)
+goto fail;
+
+s->nb_samples -= frame->nb_samples;
+
+n = get_bits_count(gb) / 8;
+if (n > s->bitstream_size) {
+ret = AVERROR_INVALIDDATA;
+goto fail;
+}
+
+memmove(s->bitstream, &s->bitstream[n], s->bitstream_size - n);
+s->bitstream_size -= n;
+
+return 0;
+
+fail:
+s->bitstream_size = 0;
+s->pkt_offset = 0;
+av_packet_unref(s->pkt);
+
+return ret;
+}
+
+const AVInputFormat ff_osq_demuxer = {
+.name   = "osq",
+.long_name  = NULL_IF_CONFIG_SMALL("raw OSQ"),
+.read_probe = osq_probe,
+.read_header= osq_read_header,
+.read_packet= ff_raw_read_partial_packet,


Instead of sending an arbitrarily sized packet (1024 bytes as of now), 
you should set codecpar->frame_size and propagate packets with that 
amount of bytes instead.
A parser is still needed, though, for non seekable input (a pipe). And 
in case the decoder is fed with non lavf input.



+.extensions = "osq",
+.flags  = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | 
AVFMT_NO_BYTE_SEEK | AVFMT_NOTIMESTAMPS,
+.raw_codec_id   = AV_CODEC_ID_OSQ,
+.priv_data_size = sizeof(FFRawDemuxerContext),
+.priv_class = &ff_raw_demuxer_class,
+};


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

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


Re: [FFmpeg-devel] [PATCH] OSQ lossless audio format support

2023-08-24 Thread Paul B Mahol
On Thu, Aug 24, 2023 at 9:54 PM James Almer  wrote:

> On 8/24/2023 6:52 AM, Paul B Mahol wrote:
> > Patches attached.
> >
> > Stereo decoding have some issues with some predictors so not yet
> bitexact.
> >
> > Please comment.
>
> > +static av_cold int osq_close(AVCodecContext *avctx)
> > +{
> > +OSQContext *s = avctx->priv_data;
> > +
> > +av_freep(&s->bitstream);
> > +s->bitstream_size = 0;
> > +
> > +for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++)
>
> FFMIN(avctx->ch_layout.nb_channels, 2);
>
> This being a FF_CODEC_CAP_INIT_CLEANUP decoder, osq_close() could be
> called before osq_init() has a chance to validate nb_channels.
>

Will use ELEMS_ARRAY macro.


> > +av_freep(&s->decode_buffer[ch]);
> > +
> > +return 0;
> > +}
> > +
> > static av_cold int osq_init(AVCodecContext *avctx)
> > +{
> > +OSQContext *s = avctx->priv_data;
> > +
> > +if (avctx->extradata_size < 48)
> > +return AVERROR(EINVAL);
> > +
> > +if (avctx->extradata[0] != 1) {
> > +av_log(avctx, AV_LOG_ERROR, "Unsupported version.\n");
> > +return AVERROR_INVALIDDATA;
> > +}
> > +
> > +avctx->sample_rate = AV_RL32(avctx->extradata + 4);
> > +if (avctx->sample_rate < 1)
> > +return AVERROR_INVALIDDATA;
> > +
> > +avctx->ch_layout.nb_channels = avctx->extradata[3];
>
> You'd need to uninit ch_layout first, as the user may have filled it
> with something (as is the case with the lavf demuxer).
>

Fixed.


>
> > +if (avctx->ch_layout.nb_channels < 1)
> > +return AVERROR_INVALIDDATA;
> > +
> > +switch (avctx->extradata[2]) {
> > +case  8: avctx->sample_fmt = AV_SAMPLE_FMT_U8P; break;
> > +case 16: avctx->sample_fmt = AV_SAMPLE_FMT_S16P; break;
> > +case 20:
> > +case 24:
> > +case 28:
> > +case 32: avctx->sample_fmt = AV_SAMPLE_FMT_S32P; break;
> > +default: return AVERROR_INVALIDDATA;
> > +}
> > +
> > +s->nb_samples = AV_RL64(avctx->extradata + 16);
> > +s->frame_samples = AV_RL16(avctx->extradata + 8);
> > +s->max_framesize = (s->frame_samples * 16 + 1024) *
> avctx->ch_layout.nb_channels;
>
> Do you even need to propagate this header using extradata? You can set
> codecpar's sample_fmt and frame_size in the demuxer, much like you're
> doing for sample_rate and ch_layout.
> There doesn't seem to be a value that can't be propagated using the
> proper existing fields here.
>

version is passed via extradata, its more cleaner approach.


>
> > +
> > +s->bitstream = av_calloc(s->max_framesize +
> AV_INPUT_BUFFER_PADDING_SIZE, sizeof(*s->bitstream));
>
> av_mallocz(). sizeof(*s->bitstream) is 1.
>

nit, i think it changes effectively nothing.


> > +if (!s->bitstream)
> > +return AVERROR(ENOMEM);
> > +
> > +for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) {
> > +s->decode_buffer[ch] = av_calloc(s->frame_samples + 4,
> > + sizeof(*s->decode_buffer[ch]));
> > +if (!s->decode_buffer[ch])
> > +return AVERROR(ENOMEM);
> > +}
> > +
> > +s->pkt = avctx->internal->in_pkt;
> > +
> > +return 0;
> > +}
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
>
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

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


Re: [FFmpeg-devel] [PATCH] OSQ lossless audio format support

2023-08-24 Thread Andreas Rheinhardt
James Almer:
> On 8/24/2023 6:52 AM, Paul B Mahol wrote:
>> Patches attached.
>>
>> Stereo decoding have some issues with some predictors so not yet
>> bitexact.
>>
>> Please comment.
> 
>> +static av_cold int osq_close(AVCodecContext *avctx)
>> +{
>> +    OSQContext *s = avctx->priv_data;
>> +
>> +    av_freep(&s->bitstream);
>> +    s->bitstream_size = 0;
>> +
>> +    for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++)
> 
> FFMIN(avctx->ch_layout.nb_channels, 2);
> 

Easier to just use FF_ARRAY_ELEMS(s->decoder_buffer). No harm in freeing
a NULL.

> This being a FF_CODEC_CAP_INIT_CLEANUP decoder, osq_close() could be
> called before osq_init() has a chance to validate nb_channels.
> 
>> +    av_freep(&s->decode_buffer[ch]);
>> +
>> +    return 0;
>> +}
>> +
>> static av_cold int osq_init(AVCodecContext *avctx)
>> +{
>> +    OSQContext *s = avctx->priv_data;
>> +
>> +    if (avctx->extradata_size < 48)
>> +    return AVERROR(EINVAL);
>> +
>> +    if (avctx->extradata[0] != 1) {
>> +    av_log(avctx, AV_LOG_ERROR, "Unsupported version.\n");
>> +    return AVERROR_INVALIDDATA;
>> +    }
>> +
>> +    avctx->sample_rate = AV_RL32(avctx->extradata + 4);
>> +    if (avctx->sample_rate < 1)
>> +    return AVERROR_INVALIDDATA;
>> +
>> +    avctx->ch_layout.nb_channels = avctx->extradata[3];
> 
> You'd need to uninit ch_layout first, as the user may have filled it
> with something (as is the case with the lavf demuxer).
> 
>> +    if (avctx->ch_layout.nb_channels < 1)
>> +    return AVERROR_INVALIDDATA;
>> +
>> +    switch (avctx->extradata[2]) {
>> +    case  8: avctx->sample_fmt = AV_SAMPLE_FMT_U8P; break;
>> +    case 16: avctx->sample_fmt = AV_SAMPLE_FMT_S16P; break;
>> +    case 20:
>> +    case 24:
>> +    case 28:
>> +    case 32: avctx->sample_fmt = AV_SAMPLE_FMT_S32P; break;
>> +    default: return AVERROR_INVALIDDATA;
>> +    }
>> +
>> +    s->nb_samples = AV_RL64(avctx->extradata + 16);
>> +    s->frame_samples = AV_RL16(avctx->extradata + 8);
>> +    s->max_framesize = (s->frame_samples * 16 + 1024) *
>> avctx->ch_layout.nb_channels;
> 
> Do you even need to propagate this header using extradata? You can set
> codecpar's sample_fmt and frame_size in the demuxer, much like you're
> doing for sample_rate and ch_layout.
> There doesn't seem to be a value that can't be propagated using the
> proper existing fields here.
> 
>> +
>> +    s->bitstream = av_calloc(s->max_framesize +
>> AV_INPUT_BUFFER_PADDING_SIZE, sizeof(*s->bitstream));
> 
> av_mallocz(). sizeof(*s->bitstream) is 1.
> 
>> +    if (!s->bitstream)
>> +    return AVERROR(ENOMEM);
>> +
>> +    for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) {
>> +    s->decode_buffer[ch] = av_calloc(s->frame_samples + 4,
>> + sizeof(*s->decode_buffer[ch]));
>> +    if (!s->decode_buffer[ch])
>> +    return AVERROR(ENOMEM);
>> +    }
>> +
>> +    s->pkt = avctx->internal->in_pkt;
>> +
>> +    return 0;
>> +}
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

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

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


Re: [FFmpeg-devel] [PATCH] OSQ lossless audio format support

2023-08-24 Thread James Almer

On 8/24/2023 6:52 AM, Paul B Mahol wrote:

Patches attached.

Stereo decoding have some issues with some predictors so not yet bitexact.

Please comment.



+static av_cold int osq_close(AVCodecContext *avctx)
+{
+OSQContext *s = avctx->priv_data;
+
+av_freep(&s->bitstream);
+s->bitstream_size = 0;
+
+for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++)


FFMIN(avctx->ch_layout.nb_channels, 2);

This being a FF_CODEC_CAP_INIT_CLEANUP decoder, osq_close() could be 
called before osq_init() has a chance to validate nb_channels.



+av_freep(&s->decode_buffer[ch]);
+
+return 0;
+}
+
static av_cold int osq_init(AVCodecContext *avctx)
+{
+OSQContext *s = avctx->priv_data;
+
+if (avctx->extradata_size < 48)
+return AVERROR(EINVAL);
+
+if (avctx->extradata[0] != 1) {
+av_log(avctx, AV_LOG_ERROR, "Unsupported version.\n");
+return AVERROR_INVALIDDATA;
+}
+
+avctx->sample_rate = AV_RL32(avctx->extradata + 4);
+if (avctx->sample_rate < 1)
+return AVERROR_INVALIDDATA;
+
+avctx->ch_layout.nb_channels = avctx->extradata[3];


You'd need to uninit ch_layout first, as the user may have filled it 
with something (as is the case with the lavf demuxer).



+if (avctx->ch_layout.nb_channels < 1)
+return AVERROR_INVALIDDATA;
+
+switch (avctx->extradata[2]) {
+case  8: avctx->sample_fmt = AV_SAMPLE_FMT_U8P; break;
+case 16: avctx->sample_fmt = AV_SAMPLE_FMT_S16P; break;
+case 20:
+case 24:
+case 28:
+case 32: avctx->sample_fmt = AV_SAMPLE_FMT_S32P; break;
+default: return AVERROR_INVALIDDATA;
+}
+
+s->nb_samples = AV_RL64(avctx->extradata + 16);
+s->frame_samples = AV_RL16(avctx->extradata + 8);
+s->max_framesize = (s->frame_samples * 16 + 1024) * 
avctx->ch_layout.nb_channels;


Do you even need to propagate this header using extradata? You can set 
codecpar's sample_fmt and frame_size in the demuxer, much like you're 
doing for sample_rate and ch_layout.
There doesn't seem to be a value that can't be propagated using the 
proper existing fields here.



+
+s->bitstream = av_calloc(s->max_framesize + AV_INPUT_BUFFER_PADDING_SIZE, 
sizeof(*s->bitstream));


av_mallocz(). sizeof(*s->bitstream) is 1.


+if (!s->bitstream)
+return AVERROR(ENOMEM);
+
+for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) {
+s->decode_buffer[ch] = av_calloc(s->frame_samples + 4,
+ sizeof(*s->decode_buffer[ch]));
+if (!s->decode_buffer[ch])
+return AVERROR(ENOMEM);
+}
+
+s->pkt = avctx->internal->in_pkt;
+
+return 0;
+}

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

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


Re: [FFmpeg-devel] [PATCH] OSQ lossless audio format support

2023-08-24 Thread Paul B Mahol
On Thu, Aug 24, 2023 at 8:06 PM Michael Niedermayer 
wrote:

> On Thu, Aug 24, 2023 at 11:52:45AM +0200, Paul B Mahol wrote:
> > Patches attached.
> >
> > Stereo decoding have some issues with some predictors so not yet
> bitexact.
> >
> > Please comment.
>
>
> [...]
> > diff --git a/libavformat/osq.c b/libavformat/osq.c
> > new file mode 100644
> > index 00..36ce25313f
> > --- /dev/null
> > +++ b/libavformat/osq.c
> > @@ -0,0 +1,117 @@
> > +/*
> > + * OSQ demuxer
> > + * Copyright (c) 2023 Paul B Mahol
> > + *
> > + * 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/intreadwrite.h"
> > +#include "avio_internal.h"
> > +#include "avformat.h"
> > +#include "demux.h"
> > +#include "internal.h"
> > +#include "rawdec.h"
> > +
> > +static int osq_probe(const AVProbeData *p)
> > +{
>
> > +if (AV_RL32(p->buf) != MKTAG('O','S','Q',' '))
> > +return 0;
> > +if (AV_RL32(p->buf + 4) != 48)
> > +return 0;
> > +if (AV_RL16(p->buf + 8) != 1)
> > +return 0;
>
> this can be simplified to a single memcmp() with a 10 byte array
>
>
nit



>
> > +if (!p->buf[10])
> > +return 0;
> > +if (!p->buf[11])
> > +return 0;
> > +if (AV_RL32(p->buf + 12) == 0)
> > +return 0;
> > +if (AV_RL16(p->buf + 16) == 0)
> > +return 0;
>
> inconsistant, you mix !x and == 0 for the same kind of check
>
>
nit, changed


>
> > +
> > +return AVPROBE_SCORE_MAX;
> > +}
> > +
> > +static int osq_read_header(AVFormatContext *s)
> > +{
> > +uint32_t t, size;
> > +AVStream *st;
> > +int ret;
> > +
> > +t = avio_rl32(s->pb);
> > +if (t != MKTAG('O','S','Q',' '))
> > +return AVERROR_INVALIDDATA;
> > +
> > +size = avio_rl32(s->pb);
> > +if (size != 48)
> > +return AVERROR_INVALIDDATA;
> > +
> > +st = avformat_new_stream(s, NULL);
> > +if (!st)
> > +return AVERROR(ENOMEM);
> > +if ((ret = ff_get_extradata(s, st->codecpar, s->pb, size)) < 0)
> > +return ret;
> > +
>
> > +t = avio_rl32(s->pb);
> > +if (t != MKTAG('R','I','F','F'))
> > +return AVERROR_INVALIDDATA;
> > +avio_skip(s->pb, 8);
> > +
> > +t = avio_rl32(s->pb);
> > +if (t != MKTAG('f','m','t',' '))
> > +return AVERROR_INVALIDDATA;
> > +size = avio_rl32(s->pb);
> > +avio_skip(s->pb, size);
> > +
> > +t = avio_rl32(s->pb);
> > +size = avio_rl32(s->pb);
> > +while (t != MKTAG('d','a','t','a')) {
> > +avio_skip(s->pb, size);
> > +
> > +t = avio_rl32(s->pb);
> > +size = avio_rl32(s->pb);
> > +if (avio_feof(s->pb))
> > +return AVERROR_INVALIDDATA;
> > +}
>
> This looks familiar, can code be shared with other RIFF based formats ?
>
>
If its really critical, maybe later.


>
> > +
> > +st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
> > +st->codecpar->codec_id= AV_CODEC_ID_OSQ;
> > +st->codecpar->sample_rate = AV_RL32(st->codecpar->extradata + 4);
> > +if (st->codecpar->sample_rate == 0)
> > +return AVERROR_INVALIDDATA;
>
> missing check for negative numbers
>

fixed


>
>
> [...]
> > diff --git a/libavcodec/osq.c b/libavcodec/osq.c
> > new file mode 100644
> > index 00..b6dc5c1bb4
> > --- /dev/null
> > +++ b/libavcodec/osq.c
> > @@ -0,0 +1,435 @@
> > +/*
> > + * OSQ audio decoder
> > + * Copyright (c) 2023 Paul B Mahol
> > + *
> > + * 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, Fift

Re: [FFmpeg-devel] [PATCH] OSQ lossless audio format support

2023-08-24 Thread Michael Niedermayer
On Thu, Aug 24, 2023 at 11:52:45AM +0200, Paul B Mahol wrote:
> Patches attached.
> 
> Stereo decoding have some issues with some predictors so not yet bitexact.
> 
> Please comment.


[...]
> diff --git a/libavformat/osq.c b/libavformat/osq.c
> new file mode 100644
> index 00..36ce25313f
> --- /dev/null
> +++ b/libavformat/osq.c
> @@ -0,0 +1,117 @@
> +/*
> + * OSQ demuxer
> + * Copyright (c) 2023 Paul B Mahol
> + *
> + * 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/intreadwrite.h"
> +#include "avio_internal.h"
> +#include "avformat.h"
> +#include "demux.h"
> +#include "internal.h"
> +#include "rawdec.h"
> +
> +static int osq_probe(const AVProbeData *p)
> +{

> +if (AV_RL32(p->buf) != MKTAG('O','S','Q',' '))
> +return 0;
> +if (AV_RL32(p->buf + 4) != 48)
> +return 0;
> +if (AV_RL16(p->buf + 8) != 1)
> +return 0;

this can be simplified to a single memcmp() with a 10 byte array


> +if (!p->buf[10])
> +return 0;
> +if (!p->buf[11])
> +return 0;
> +if (AV_RL32(p->buf + 12) == 0)
> +return 0;
> +if (AV_RL16(p->buf + 16) == 0)
> +return 0;

inconsistant, you mix !x and == 0 for the same kind of check


> +
> +return AVPROBE_SCORE_MAX;
> +}
> +
> +static int osq_read_header(AVFormatContext *s)
> +{
> +uint32_t t, size;
> +AVStream *st;
> +int ret;
> +
> +t = avio_rl32(s->pb);
> +if (t != MKTAG('O','S','Q',' '))
> +return AVERROR_INVALIDDATA;
> +
> +size = avio_rl32(s->pb);
> +if (size != 48)
> +return AVERROR_INVALIDDATA;
> +
> +st = avformat_new_stream(s, NULL);
> +if (!st)
> +return AVERROR(ENOMEM);
> +if ((ret = ff_get_extradata(s, st->codecpar, s->pb, size)) < 0)
> +return ret;
> +

> +t = avio_rl32(s->pb);
> +if (t != MKTAG('R','I','F','F'))
> +return AVERROR_INVALIDDATA;
> +avio_skip(s->pb, 8);
> +
> +t = avio_rl32(s->pb);
> +if (t != MKTAG('f','m','t',' '))
> +return AVERROR_INVALIDDATA;
> +size = avio_rl32(s->pb);
> +avio_skip(s->pb, size);
> +
> +t = avio_rl32(s->pb);
> +size = avio_rl32(s->pb);
> +while (t != MKTAG('d','a','t','a')) {
> +avio_skip(s->pb, size);
> +
> +t = avio_rl32(s->pb);
> +size = avio_rl32(s->pb);
> +if (avio_feof(s->pb))
> +return AVERROR_INVALIDDATA;
> +}

This looks familiar, can code be shared with other RIFF based formats ?


> +
> +st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
> +st->codecpar->codec_id= AV_CODEC_ID_OSQ;
> +st->codecpar->sample_rate = AV_RL32(st->codecpar->extradata + 4);
> +if (st->codecpar->sample_rate == 0)
> +return AVERROR_INVALIDDATA;

missing check for negative numbers


[...]
> diff --git a/libavcodec/osq.c b/libavcodec/osq.c
> new file mode 100644
> index 00..b6dc5c1bb4
> --- /dev/null
> +++ b/libavcodec/osq.c
> @@ -0,0 +1,435 @@
> +/*
> + * OSQ audio decoder
> + * Copyright (c) 2023 Paul B Mahol
> + *
> + * 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
> + */
> +

> +#define ASSERT_LEVEL 5

that looks strange
assert level is set by the user building this, also there is no level 5


> +#include "libavutil/avassert.h"
> +#include "libavutil/internal.h"
> +#include "libavutil/intreadwrite.h"
> +#include "avcodec.h"
> +#include "codec_internal.h"
> +#include "decode.h"
> +#include "internal.h"
> +#define BITSTREAM_READER_LE
> +#include "get_

[FFmpeg-devel] [PATCH] OSQ lossless audio format support

2023-08-24 Thread Paul B Mahol
Patches attached.

Stereo decoding have some issues with some predictors so not yet bitexact.

Please comment.
From a90b4fbd4178d4ef434e1255ed20dddebde0ddb8 Mon Sep 17 00:00:00 2001
From: Paul B Mahol 
Date: Tue, 27 Jun 2023 19:51:54 +0200
Subject: [PATCH 2/2] avformat: add OSQ demuxer

Signed-off-by: Paul B Mahol 
---
 libavformat/Makefile |   1 +
 libavformat/allformats.c |   1 +
 libavformat/osq.c| 117 +++
 3 files changed, 119 insertions(+)
 create mode 100644 libavformat/osq.c

diff --git a/libavformat/Makefile b/libavformat/Makefile
index bd78c206b9..1c8c965a74 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -433,6 +433,7 @@ OBJS-$(CONFIG_OMA_DEMUXER)   += omadec.o pcm.o oma.o
 OBJS-$(CONFIG_OMA_MUXER) += omaenc.o rawenc.o oma.o id3v2enc.o
 OBJS-$(CONFIG_OPUS_MUXER)+= oggenc.o \
 vorbiscomment.o
+OBJS-$(CONFIG_OSQ_DEMUXER)   += osq.o rawdec.o
 OBJS-$(CONFIG_PAF_DEMUXER)   += paf.o
 OBJS-$(CONFIG_PCM_ALAW_DEMUXER)  += pcmdec.o pcm.o
 OBJS-$(CONFIG_PCM_ALAW_MUXER)+= pcmenc.o rawenc.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index 6324952bd2..f4210e4932 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -331,6 +331,7 @@ extern const FFOutputFormat ff_ogv_muxer;
 extern const AVInputFormat  ff_oma_demuxer;
 extern const FFOutputFormat ff_oma_muxer;
 extern const FFOutputFormat ff_opus_muxer;
+extern const AVInputFormat  ff_osq_demuxer;
 extern const AVInputFormat  ff_paf_demuxer;
 extern const AVInputFormat  ff_pcm_alaw_demuxer;
 extern const FFOutputFormat ff_pcm_alaw_muxer;
diff --git a/libavformat/osq.c b/libavformat/osq.c
new file mode 100644
index 00..36ce25313f
--- /dev/null
+++ b/libavformat/osq.c
@@ -0,0 +1,117 @@
+/*
+ * OSQ demuxer
+ * Copyright (c) 2023 Paul B Mahol
+ *
+ * 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/intreadwrite.h"
+#include "avio_internal.h"
+#include "avformat.h"
+#include "demux.h"
+#include "internal.h"
+#include "rawdec.h"
+
+static int osq_probe(const AVProbeData *p)
+{
+if (AV_RL32(p->buf) != MKTAG('O','S','Q',' '))
+return 0;
+if (AV_RL32(p->buf + 4) != 48)
+return 0;
+if (AV_RL16(p->buf + 8) != 1)
+return 0;
+if (!p->buf[10])
+return 0;
+if (!p->buf[11])
+return 0;
+if (AV_RL32(p->buf + 12) == 0)
+return 0;
+if (AV_RL16(p->buf + 16) == 0)
+return 0;
+
+return AVPROBE_SCORE_MAX;
+}
+
+static int osq_read_header(AVFormatContext *s)
+{
+uint32_t t, size;
+AVStream *st;
+int ret;
+
+t = avio_rl32(s->pb);
+if (t != MKTAG('O','S','Q',' '))
+return AVERROR_INVALIDDATA;
+
+size = avio_rl32(s->pb);
+if (size != 48)
+return AVERROR_INVALIDDATA;
+
+st = avformat_new_stream(s, NULL);
+if (!st)
+return AVERROR(ENOMEM);
+if ((ret = ff_get_extradata(s, st->codecpar, s->pb, size)) < 0)
+return ret;
+
+t = avio_rl32(s->pb);
+if (t != MKTAG('R','I','F','F'))
+return AVERROR_INVALIDDATA;
+avio_skip(s->pb, 8);
+
+t = avio_rl32(s->pb);
+if (t != MKTAG('f','m','t',' '))
+return AVERROR_INVALIDDATA;
+size = avio_rl32(s->pb);
+avio_skip(s->pb, size);
+
+t = avio_rl32(s->pb);
+size = avio_rl32(s->pb);
+while (t != MKTAG('d','a','t','a')) {
+avio_skip(s->pb, size);
+
+t = avio_rl32(s->pb);
+size = avio_rl32(s->pb);
+if (avio_feof(s->pb))
+return AVERROR_INVALIDDATA;
+}
+
+st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+st->codecpar->codec_id= AV_CODEC_ID_OSQ;
+st->codecpar->sample_rate = AV_RL32(st->codecpar->extradata + 4);
+if (st->codecpar->sample_rate == 0)
+return AVERROR_INVALIDDATA;
+st->codecpar->ch_layout.nb_channels = st->codecpar->extradata[3];
+if (st->codecpar->ch_layout.nb_channels == 0)
+return AVERROR_INVALIDDATA;
+st->start_time = 0;
+st->duration = AV_RL32(st->codecpar->extradata + 16);
+avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
+
+return 0;
+}
+
+const AVInp