4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "avio_internal.h"
25 #include "libavutil/intreadwrite.h"
27 static int qoa_probe(const AVProbeData
*p
)
29 if ((p
->buf_size
< 16) ||
30 (AV_RB32(p
->buf
) != MKBETAG('q','o','a','f')) ||
31 (AV_RB32(p
->buf
+ 4) == 0) ||
33 (AV_RB24(p
->buf
+ 9) == 0) ||
34 (AV_RB16(p
->buf
+ 12) == 0) ||
35 (AV_RB16(p
->buf
+ 14) == 0))
37 return AVPROBE_SCORE_MAX
;
40 static int qoa_read_header(AVFormatContext
*s
)
42 AVIOContext
*pb
= s
->pb
;
46 st
= avformat_new_stream(s
, NULL
);
48 return AVERROR(ENOMEM
);
51 st
->codecpar
->codec_type
= AVMEDIA_TYPE_AUDIO
;
52 st
->codecpar
->codec_id
= AV_CODEC_ID_QOA
;
53 st
->duration
= avio_rb32(pb
);
56 ret
= ffio_ensure_seekback(pb
, 4);
59 st
->codecpar
->ch_layout
.nb_channels
= avio_r8(pb
);
60 if (st
->codecpar
->ch_layout
.nb_channels
== 0)
61 return AVERROR_INVALIDDATA
;
63 st
->codecpar
->sample_rate
= avio_rb24(pb
);
64 if (st
->codecpar
->sample_rate
== 0)
65 return AVERROR_INVALIDDATA
;
67 avio_seek(pb
, -4, SEEK_CUR
);
69 avpriv_set_pts_info(st
, 64, 1, st
->codecpar
->sample_rate
);
74 static int qoa_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
76 AVIOContext
*pb
= s
->pb
;
77 uint16_t size
, duration
;
86 ret
= avio_read(pb
, hdr
, sizeof(hdr
));
87 if (ret
!= sizeof(hdr
))
90 duration
= AV_RB16(hdr
+ 4);
91 size
= AV_RB16(hdr
+ 6);
92 if ((ret
= av_new_packet(pkt
, size
)) < 0)
95 memcpy(pkt
->data
, hdr
, sizeof(hdr
));
96 ret
= avio_read(pb
, pkt
->data
+ sizeof(hdr
), size
- sizeof(hdr
));
97 if (ret
!= size
- sizeof(hdr
))
99 pkt
->stream_index
= 0;
101 pkt
->duration
= duration
;
106 const FFInputFormat ff_qoa_demuxer
= {
108 .p
.long_name
= NULL_IF_CONFIG_SMALL("QOA"),
109 .p
.flags
= AVFMT_GENERIC_INDEX
,
110 .p
.extensions
= "qoa",
111 .read_probe
= qoa_probe
,
112 .read_header
= qoa_read_header
,
113 .read_packet
= qoa_read_packet
,