FFmpeg  4.3.6
argo_asf.c
Go to the documentation of this file.
1 /*
2  * Argonaut Games ASF demuxer
3  *
4  * Copyright (C) 2020 Zane van Iperen (zane@zanevaniperen.com)
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 #include "avformat.h"
23 #include "internal.h"
24 #include "libavutil/intreadwrite.h"
25 #include "libavutil/avassert.h"
26 
27 #define ASF_TAG MKTAG('A', 'S', 'F', '\0')
28 #define ASF_FILE_HEADER_SIZE 24
29 #define ASF_CHUNK_HEADER_SIZE 20
30 
31 typedef struct ArgoASFFileHeader {
32  uint32_t magic; /*< Magic Number, {'A', 'S', 'F', '\0'} */
33  uint16_t version_major; /*< File Major Version. */
34  uint16_t version_minor; /*< File Minor Version. */
35  uint32_t num_chunks; /*< No. chunks in the file. */
36  uint32_t chunk_offset; /*< Offset to the first chunk from the start of the file. */
37  int8_t name[8]; /*< Name. */
39 
40 typedef struct ArgoASFChunkHeader {
41  uint32_t num_blocks; /*< No. blocks in the chunk. */
42  uint32_t num_samples; /*< No. samples per channel in a block. */
43  uint32_t unk1; /*< Unknown */
44  uint16_t sample_rate; /*< Sample rate. */
45  uint16_t unk2; /*< Unknown. */
46  uint32_t flags; /*< Stream flags. */
48 
49 enum {
50  ASF_CF_BITS_PER_SAMPLE = (1 << 0), /*< 16-bit if set, 8 otherwise. */
51  ASF_CF_STEREO = (1 << 1), /*< Stereo if set, mono otherwise. */
52  ASF_CF_ALWAYS1_1 = (1 << 2), /*< Unknown, always seems to be set. */
53  ASF_CF_ALWAYS1_2 = (1 << 3), /*< Unknown, always seems to be set. */
54 
57 };
58 
59 typedef struct ArgoASFDemuxContext {
62  uint32_t blocks_read;
64 
66 {
67  hdr->magic = AV_RL32(buf + 0);
68  hdr->version_major = AV_RL16(buf + 4);
69  hdr->version_minor = AV_RL16(buf + 6);
70  hdr->num_chunks = AV_RL32(buf + 8);
71  hdr->chunk_offset = AV_RL32(buf + 12);
72  for (int i = 0; i < FF_ARRAY_ELEMS(hdr->name); i++)
73  hdr->name[i] = AV_RL8(buf + 16 + i);
74 }
75 
77 {
78  hdr->num_blocks = AV_RL32(buf + 0);
79  hdr->num_samples = AV_RL32(buf + 4);
80  hdr->unk1 = AV_RL32(buf + 8);
81  hdr->sample_rate = AV_RL16(buf + 12);
82  hdr->unk2 = AV_RL16(buf + 14);
83  hdr->flags = AV_RL32(buf + 16);
84 }
85 
86 /*
87  * Known versions:
88  * 1.1: The sample files in /game-formats/brender/part2.zip
89  * 1.2: Croc! Legend of the Gobbos
90  * 2.1: Croc 2
91  */
93 {
94  return (hdr->version_major == 1 && hdr->version_minor == 1) ||
95  (hdr->version_major == 1 && hdr->version_minor == 2) ||
96  (hdr->version_major == 2 && hdr->version_minor == 1);
97 }
98 
99 static int argo_asf_probe(const AVProbeData *p)
100 {
101  ArgoASFFileHeader hdr;
102 
104 
106 
107  if (hdr.magic != ASF_TAG)
108  return 0;
109 
110  if (!argo_asf_is_known_version(&hdr))
111  return AVPROBE_SCORE_EXTENSION / 2;
112 
113  return AVPROBE_SCORE_EXTENSION + 1;
114 }
115 
117 {
118  int64_t ret;
119  AVIOContext *pb = s->pb;
120  AVStream *st;
121  ArgoASFDemuxContext *asf = s->priv_data;
123 
124  if (!(st = avformat_new_stream(s, NULL)))
125  return AVERROR(ENOMEM);
126 
127  if ((ret = avio_read(pb, buf, ASF_FILE_HEADER_SIZE)) < 0)
128  return ret;
129  else if (ret != ASF_FILE_HEADER_SIZE)
130  return AVERROR(EIO);
131 
132  argo_asf_parse_file_header(&asf->fhdr, buf);
133 
134  if (!argo_asf_is_known_version(&asf->fhdr)) {
135  avpriv_request_sample(s, "Version %hu.%hu",
137  );
138  return AVERROR_PATCHWELCOME;
139  }
140 
141  if (asf->fhdr.num_chunks == 0) {
142  return AVERROR_INVALIDDATA;
143  } else if (asf->fhdr.num_chunks > 1) {
144  avpriv_request_sample(s, ">1 chunk");
145  return AVERROR_PATCHWELCOME;
146  }
147 
149  return AVERROR_INVALIDDATA;
150 
151  if ((ret = avio_skip(pb, asf->fhdr.chunk_offset - ASF_FILE_HEADER_SIZE)) < 0)
152  return ret;
153 
154  if ((ret = avio_read(pb, buf, ASF_CHUNK_HEADER_SIZE)) < 0)
155  return ret;
156  else if (ret != ASF_CHUNK_HEADER_SIZE)
157  return AVERROR(EIO);
158 
160 
161  if ((asf->ckhdr.flags & ASF_CF_ALWAYS1) != ASF_CF_ALWAYS1 || (asf->ckhdr.flags & ASF_CF_ALWAYS0) != 0) {
162  avpriv_request_sample(s, "Nonstandard flags (0x%08X)", asf->ckhdr.flags);
163  return AVERROR_PATCHWELCOME;
164  }
165 
169 
170  if (asf->ckhdr.flags & ASF_CF_STEREO) {
172  st->codecpar->channels = 2;
173  } else {
175  st->codecpar->channels = 1;
176  }
177 
178  /* v1.1 files (FX Fighter) are all marked as 44100, but are actually 22050. */
179  if (asf->fhdr.version_major == 1 && asf->fhdr.version_minor == 1)
180  st->codecpar->sample_rate = 22050;
181  else
183 
185 
187  st->codecpar->bits_per_raw_sample = 16;
188  else
189  st->codecpar->bits_per_raw_sample = 8;
190 
191  if (st->codecpar->bits_per_raw_sample != 16) {
192  /* The header allows for these, but I've never seen any files with them. */
193  avpriv_request_sample(s, "Non 16-bit samples");
194  return AVERROR_PATCHWELCOME;
195  }
196 
197  /*
198  * (nchannel control bytes) + ((bytes_per_channel) * nchannel)
199  * For mono, this is 17. For stereo, this is 34.
200  */
201  st->codecpar->frame_size = st->codecpar->channels +
202  (asf->ckhdr.num_samples / 2) *
203  st->codecpar->channels;
204 
206 
207  st->codecpar->bit_rate = st->codecpar->channels *
208  st->codecpar->sample_rate *
210 
211  avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
212  st->start_time = 0;
213  st->duration = asf->ckhdr.num_blocks * asf->ckhdr.num_samples;
214  st->nb_frames = asf->ckhdr.num_blocks;
215  return 0;
216 }
217 
219 {
220  ArgoASFDemuxContext *asf = s->priv_data;
221 
222  AVStream *st = s->streams[0];
223  AVIOContext *pb = s->pb;
224  int ret;
225 
226  if (asf->blocks_read >= asf->ckhdr.num_blocks)
227  return AVERROR_EOF;
228 
229  if ((ret = av_get_packet(pb, pkt, st->codecpar->frame_size)) < 0)
230  return ret;
231  else if (ret != st->codecpar->frame_size)
232  return AVERROR_INVALIDDATA;
233 
234  pkt->stream_index = st->index;
235  pkt->duration = asf->ckhdr.num_samples;
236 
237  ++asf->blocks_read;
238  return 0;
239 }
240 
241 /*
242  * Not actually sure what ASF stands for.
243  * - Argonaut Sound File?
244  * - Audio Stream File?
245  */
247  .name = "argo_asf",
248  .long_name = NULL_IF_CONFIG_SMALL("Argonaut Games ASF"),
249  .priv_data_size = sizeof(ArgoASFDemuxContext),
253 };
AVInputFormat ff_argo_asf_demuxer
Definition: argo_asf.c:246
#define NULL
Definition: coverity.c:32
Bytestream IO Context.
Definition: avio.h:161
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
static void argo_asf_parse_chunk_header(ArgoASFChunkHeader *hdr, const uint8_t *buf)
Definition: argo_asf.c:76
uint32_t flags
Definition: argo_asf.c:46
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: utils.c:4948
#define avpriv_request_sample(...)
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:60
int index
stream index in AVFormatContext
Definition: avformat.h:877
#define AVPROBE_PADDING_SIZE
extra allocated bytes at the end of the probe buffer
Definition: avformat.h:455
#define AV_RL16
Definition: intreadwrite.h:42
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:329
static AVPacket pkt
#define AV_CH_LAYOUT_STEREO
static int argo_asf_is_known_version(const ArgoASFFileHeader *hdr)
Definition: argo_asf.c:92
uint32_t chunk_offset
Definition: argo_asf.c:36
int frame_size
Audio only.
Definition: codec_par.h:181
Format I/O context.
Definition: avformat.h:1351
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
uint8_t
uint32_t num_samples
Definition: argo_asf.c:42
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:373
static int argo_asf_probe(const AVProbeData *p)
Definition: argo_asf.c:99
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4526
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1419
int8_t name[8]
Definition: argo_asf.c:37
#define AVERROR_EOF
End of file.
Definition: error.h:55
int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
Allocate and read the payload of a packet and initialize its fields with default values.
Definition: utils.c:307
static int argo_asf_read_header(AVFormatContext *s)
Definition: argo_asf.c:116
uint64_t channel_layout
Audio only.
Definition: codec_par.h:162
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:625
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition: codec_par.h:89
uint16_t version_major
Definition: argo_asf.c:33
#define AV_RL8(x)
Definition: intreadwrite.h:398
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
#define AVERROR(e)
Definition: error.h:43
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:188
#define ASF_CHUNK_HEADER_SIZE
Definition: argo_asf.c:29
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:56
static void argo_asf_parse_file_header(ArgoASFFileHeader *hdr, const uint8_t *buf)
Definition: argo_asf.c:65
simple assert() macros that are a bit more flexible than ISO C assert().
uint16_t version_minor
Definition: argo_asf.c:34
#define FFMAX(a, b)
Definition: common.h:94
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:443
int block_align
Audio only.
Definition: codec_par.h:177
uint32_t num_chunks
Definition: argo_asf.c:35
#define s(width, name)
Definition: cbs_vp9.c:257
#define AV_RL32
Definition: intreadwrite.h:146
ArgoASFFileHeader fhdr
Definition: argo_asf.c:60
ArgoASFChunkHeader ckhdr
Definition: argo_asf.c:61
static int argo_asf_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: argo_asf.c:218
#define FF_ARRAY_ELEMS(a)
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:545
Stream structure.
Definition: avformat.h:876
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_reading.c:42
AVIOContext * pb
I/O context.
Definition: avformat.h:1393
uint32_t blocks_read
Definition: argo_asf.c:62
#define ASF_TAG
Definition: argo_asf.c:27
uint32_t magic
Definition: argo_asf.c:32
#define ASF_FILE_HEADER_SIZE
Definition: argo_asf.c:28
#define AVPROBE_SCORE_EXTENSION
score for file extension
Definition: avformat.h:451
This structure contains the data a format has to probe a file.
Definition: avformat.h:441
uint32_t unk1
Definition: argo_asf.c:43
int bits_per_raw_sample
This is the number of valid bits in each output sample.
Definition: codec_par.h:115
static int read_probe(const AVProbeData *pd)
Definition: jvdec.c:55
int64_t duration
Decoding: duration of the stream, in stream time base.
Definition: avformat.h:925
int sample_rate
Audio only.
Definition: codec_par.h:170
Main libavformat public API header.
int64_t start_time
Decoding: pts of the first frame of the stream in presentation order, in stream time base...
Definition: avformat.h:915
uint32_t num_blocks
Definition: argo_asf.c:41
int64_t nb_frames
number of frames in this stream if known or 0
Definition: avformat.h:927
uint16_t sample_rate
Definition: argo_asf.c:44
void * priv_data
Format private data.
Definition: avformat.h:1379
int bits_per_coded_sample
The number of bits per sample in the codedwords.
Definition: codec_par.h:102
int channels
Audio only.
Definition: codec_par.h:166
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:650
signed 16 bits, planar
Definition: samplefmt.h:67
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1023
int stream_index
Definition: packet.h:357
#define AV_CH_LAYOUT_MONO
This structure stores compressed data.
Definition: packet.h:332
uint16_t unk2
Definition: argo_asf.c:45