annotate cafdec.c @ 5910:536e5527c1e0 libavformat

Define AVMediaType enum, and use it instead of enum CodecType, which is deprecated and will be dropped at the next major bump.
author stefano
date Tue, 30 Mar 2010 23:30:55 +0000
parents 134741dc8327
children 08cd1179a20d
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
5206
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
1 /*
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
2 * Core Audio Format demuxer
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
3 * Copyright (c) 2007 Justin Ruggles
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
4 * Copyright (c) 2009 Peter Ross
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
5 *
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
6 * This file is part of FFmpeg.
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
7 *
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
8 * FFmpeg is free software; you can redistribute it and/or
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
9 * modify it under the terms of the GNU Lesser General Public
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
10 * License as published by the Free Software Foundation; either
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
11 * version 2.1 of the License, or (at your option) any later version.
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
12 *
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
13 * FFmpeg is distributed in the hope that it will be useful,
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
16 * Lesser General Public License for more details.
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
17 *
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
18 * You should have received a copy of the GNU Lesser General Public
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
19 * License along with FFmpeg; if not, write to the Free Software
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
21 */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
22
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
23 /**
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
24 * @file libavformat/cafdec.c
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
25 * Core Audio Format demuxer
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
26 */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
27
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
28 #include "avformat.h"
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
29 #include "riff.h"
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
30 #include "isom.h"
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
31 #include "libavutil/intreadwrite.h"
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
32 #include "caf.h"
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
33
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
34 typedef struct {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
35 int bytes_per_packet; ///< bytes in a packet, or 0 if variable
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
36 int frames_per_packet; ///< frames in a packet, or 0 if variable
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
37 int64_t num_bytes; ///< total number of bytes in stream
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
38
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
39 int64_t packet_cnt; ///< packet counter
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
40 int64_t frame_cnt; ///< frame counter
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
41
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
42 int64_t data_start; ///< data start position, in bytes
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
43 int64_t data_size; ///< raw data size, in bytes
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
44 } CaffContext;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
45
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
46 static int probe(AVProbeData *p)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
47 {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
48 if (AV_RB32(p->buf) == MKBETAG('c','a','f','f') && AV_RB16(&p->buf[4]) == 1)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
49 return AVPROBE_SCORE_MAX;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
50 return 0;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
51 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
52
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
53 /** Read audio description chunk */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
54 static int read_desc_chunk(AVFormatContext *s)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
55 {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
56 ByteIOContext *pb = s->pb;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
57 CaffContext *caf = s->priv_data;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
58 AVStream *st;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
59 int flags;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
60
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
61 /* new audio stream */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
62 st = av_new_stream(s, 0);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
63 if (!st)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
64 return AVERROR_NOMEM;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
65
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
66 /* parse format description */
5910
536e5527c1e0 Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents: 5834
diff changeset
67 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
5206
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
68 st->codec->sample_rate = av_int2dbl(get_be64(pb));
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
69 st->codec->codec_tag = get_be32(pb);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
70 flags = get_be32(pb);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
71 caf->bytes_per_packet = get_be32(pb);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
72 st->codec->block_align = caf->bytes_per_packet;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
73 caf->frames_per_packet = get_be32(pb);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
74 st->codec->channels = get_be32(pb);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
75 st->codec->bits_per_coded_sample = get_be32(pb);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
76
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
77 /* calculate bit rate for constant size packets */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
78 if (caf->frames_per_packet > 0 && caf->bytes_per_packet > 0) {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
79 st->codec->bit_rate = (uint64_t)st->codec->sample_rate * (uint64_t)caf->bytes_per_packet * 8
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
80 / (uint64_t)caf->frames_per_packet;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
81 } else {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
82 st->codec->bit_rate = 0;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
83 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
84
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
85 /* determine codec */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
86 if (st->codec->codec_tag == MKBETAG('l','p','c','m'))
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
87 st->codec->codec_id = ff_mov_get_lpcm_codec_id(st->codec->bits_per_coded_sample, (flags ^ 0x2) | 0x4);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
88 else
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
89 st->codec->codec_id = ff_codec_get_id(ff_codec_caf_tags, st->codec->codec_tag);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
90 return 0;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
91 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
92
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
93 /** Read magic cookie chunk */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
94 static int read_kuki_chunk(AVFormatContext *s, int64_t size)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
95 {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
96 ByteIOContext *pb = s->pb;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
97 AVStream *st = s->streams[0];
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
98
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
99 if (size < 0 || size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
100 return -1;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
101
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
102 if (st->codec->codec_id == CODEC_ID_AAC) {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
103 /* The magic cookie format for AAC is an mp4 esds atom.
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
104 The lavc AAC decoder requires the data from the codec specific
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
105 description as extradata input. */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
106 int strt, skip;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
107 MOVAtom atom;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
108
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
109 strt = url_ftell(pb);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
110 ff_mov_read_esds(s, pb, atom);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
111 skip = size - (url_ftell(pb) - strt);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
112 if (skip < 0 || !st->codec->extradata ||
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
113 st->codec->codec_id != CODEC_ID_AAC) {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
114 av_log(s, AV_LOG_ERROR, "invalid AAC magic cookie\n");
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
115 return AVERROR_INVALIDDATA;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
116 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
117 url_fskip(pb, skip);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
118 } else {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
119 st->codec->extradata = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
120 if (!st->codec->extradata)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
121 return AVERROR(ENOMEM);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
122 get_buffer(pb, st->codec->extradata, size);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
123 st->codec->extradata_size = size;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
124 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
125
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
126 return 0;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
127 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
128
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
129 /** Read packet table chunk */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
130 static int read_pakt_chunk(AVFormatContext *s, int64_t size)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
131 {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
132 ByteIOContext *pb = s->pb;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
133 AVStream *st = s->streams[0];
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
134 CaffContext *caf = s->priv_data;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
135 int64_t pos = 0, ccount;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
136 int num_packets, i;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
137
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
138 ccount = url_ftell(pb);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
139
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
140 num_packets = get_be64(pb);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
141 if (num_packets < 0 || INT32_MAX / sizeof(AVIndexEntry) < num_packets)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
142 return AVERROR_INVALIDDATA;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
143
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
144 st->nb_frames = get_be64(pb); /* valid frames */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
145 st->nb_frames += get_be32(pb); /* priming frames */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
146 st->nb_frames += get_be32(pb); /* remainder frames */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
147
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
148 st->duration = 0;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
149 for (i = 0; i < num_packets; i++) {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
150 av_add_index_entry(s->streams[0], pos, st->duration, 0, 0, AVINDEX_KEYFRAME);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
151 pos += caf->bytes_per_packet ? caf->bytes_per_packet : ff_mp4_read_descr_len(pb);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
152 st->duration += caf->frames_per_packet ? caf->frames_per_packet : ff_mp4_read_descr_len(pb);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
153 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
154
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
155 if (url_ftell(pb) - ccount != size) {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
156 av_log(s, AV_LOG_ERROR, "error reading packet table\n");
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
157 return -1;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
158 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
159
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
160 caf->num_bytes = pos;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
161 return 0;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
162 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
163
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
164 /** Read information chunk */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
165 static void read_info_chunk(AVFormatContext *s, int64_t size)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
166 {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
167 ByteIOContext *pb = s->pb;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
168 unsigned int i;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
169 unsigned int nb_entries = get_be32(pb);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
170 for (i = 0; i < nb_entries; i++) {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
171 char key[32];
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
172 char value[1024];
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
173 get_strz(pb, key, sizeof(key));
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
174 get_strz(pb, value, sizeof(value));
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
175 av_metadata_set(&s->metadata, key, value);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
176 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
177 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
178
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
179 static int read_header(AVFormatContext *s,
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
180 AVFormatParameters *ap)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
181 {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
182 ByteIOContext *pb = s->pb;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
183 CaffContext *caf = s->priv_data;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
184 AVStream *st;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
185 uint32_t tag = 0;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
186 int found_data, ret;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
187 int64_t size;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
188
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
189 url_fskip(pb, 8); /* magic, version, file flags */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
190
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
191 /* audio description chunk */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
192 if (get_be32(pb) != MKBETAG('d','e','s','c')) {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
193 av_log(s, AV_LOG_ERROR, "desc chunk not present\n");
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
194 return AVERROR_INVALIDDATA;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
195 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
196 size = get_be64(pb);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
197 if (size != 32)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
198 return AVERROR_INVALIDDATA;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
199
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
200 ret = read_desc_chunk(s);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
201 if (ret)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
202 return ret;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
203 st = s->streams[0];
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
204
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
205 /* parse each chunk */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
206 found_data = 0;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
207 while (!url_feof(pb)) {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
208
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
209 /* stop at data chunk if seeking is not supported or
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
210 data chunk size is unknown */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
211 if (found_data && (caf->data_size < 0 || url_is_streamed(pb)))
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
212 break;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
213
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
214 tag = get_be32(pb);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
215 size = get_be64(pb);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
216 if (url_feof(pb))
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
217 break;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
218
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
219 switch (tag) {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
220 case MKBETAG('d','a','t','a'):
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
221 url_fskip(pb, 4); /* edit count */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
222 caf->data_start = url_ftell(pb);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
223 caf->data_size = size < 0 ? -1 : size - 4;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
224 if (caf->data_size > 0 && !url_is_streamed(pb))
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
225 url_fskip(pb, caf->data_size);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
226 found_data = 1;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
227 break;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
228
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
229 /* magic cookie chunk */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
230 case MKBETAG('k','u','k','i'):
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
231 if (read_kuki_chunk(s, size))
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
232 return AVERROR_INVALIDDATA;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
233 break;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
234
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
235 /* packet table chunk */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
236 case MKBETAG('p','a','k','t'):
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
237 if (read_pakt_chunk(s, size))
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
238 return AVERROR_INVALIDDATA;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
239 break;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
240
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
241 case MKBETAG('i','n','f','o'):
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
242 read_info_chunk(s, size);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
243 break;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
244
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
245 default:
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
246 #define _(x) ((x) >= ' ' ? (x) : ' ')
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
247 av_log(s, AV_LOG_WARNING, "skipping CAF chunk: %08X (%c%c%c%c)\n",
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
248 tag, _(tag>>24), _((tag>>16)&0xFF), _((tag>>8)&0xFF), _(tag&0xFF));
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
249 #undef _
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
250 case MKBETAG('f','r','e','e'):
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
251 if (size < 0)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
252 return AVERROR_INVALIDDATA;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
253 url_fskip(pb, size);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
254 break;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
255 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
256 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
257
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
258 if (!found_data)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
259 return AVERROR_INVALIDDATA;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
260
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
261 if (caf->bytes_per_packet > 0 && caf->frames_per_packet > 0) {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
262 if (caf->data_size > 0)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
263 st->nb_frames = (caf->data_size / caf->bytes_per_packet) * caf->frames_per_packet;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
264 } else if (st->nb_index_entries) {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
265 st->codec->bit_rate = st->codec->sample_rate * caf->data_size * 8 /
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
266 st->duration;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
267 } else {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
268 av_log(s, AV_LOG_ERROR, "Missing packet table. It is required when "
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
269 "block size or frame size are variable.\n");
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
270 return AVERROR_INVALIDDATA;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
271 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
272 s->file_size = url_fsize(pb);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
273 s->file_size = FFMAX(0, s->file_size);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
274
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
275 av_set_pts_info(st, 64, 1, st->codec->sample_rate);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
276 st->start_time = 0;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
277
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
278 /* position the stream at the start of data */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
279 if (caf->data_size >= 0)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
280 url_fseek(pb, caf->data_start, SEEK_SET);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
281
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
282 return 0;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
283 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
284
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
285 #define CAF_MAX_PKT_SIZE 4096
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
286
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
287 static int read_packet(AVFormatContext *s, AVPacket *pkt)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
288 {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
289 ByteIOContext *pb = s->pb;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
290 AVStream *st = s->streams[0];
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
291 CaffContext *caf = s->priv_data;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
292 int res, pkt_size = 0, pkt_frames = 0;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
293 int64_t left = CAF_MAX_PKT_SIZE;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
294
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
295 if (url_feof(pb))
5834
134741dc8327 Replace all the occurrences of AVERROR_EIO with AVERROR(EIO), and mark
stefano
parents: 5206
diff changeset
296 return AVERROR(EIO);
5206
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
297
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
298 /* don't read past end of data chunk */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
299 if (caf->data_size > 0) {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
300 left = (caf->data_start + caf->data_size) - url_ftell(pb);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
301 if (left <= 0)
5834
134741dc8327 Replace all the occurrences of AVERROR_EIO with AVERROR(EIO), and mark
stefano
parents: 5206
diff changeset
302 return AVERROR(EIO);
5206
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
303 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
304
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
305 pkt_frames = caf->frames_per_packet;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
306 pkt_size = caf->bytes_per_packet;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
307
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
308 if (pkt_size > 0 && pkt_frames == 1) {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
309 pkt_size = (CAF_MAX_PKT_SIZE / pkt_size) * pkt_size;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
310 pkt_size = FFMIN(pkt_size, left);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
311 pkt_frames = pkt_size / caf->bytes_per_packet;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
312 } else if (st->nb_index_entries) {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
313 if (caf->packet_cnt < st->nb_index_entries - 1) {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
314 pkt_size = st->index_entries[caf->packet_cnt + 1].pos - st->index_entries[caf->packet_cnt].pos;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
315 pkt_frames = st->index_entries[caf->packet_cnt + 1].timestamp - st->index_entries[caf->packet_cnt].timestamp;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
316 } else if (caf->packet_cnt == st->nb_index_entries - 1) {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
317 pkt_size = caf->num_bytes - st->index_entries[caf->packet_cnt].pos;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
318 pkt_frames = st->duration - st->index_entries[caf->packet_cnt].timestamp;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
319 } else {
5834
134741dc8327 Replace all the occurrences of AVERROR_EIO with AVERROR(EIO), and mark
stefano
parents: 5206
diff changeset
320 return AVERROR(EIO);
5206
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
321 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
322 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
323
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
324 if (pkt_size == 0 || pkt_frames == 0 || pkt_size > left)
5834
134741dc8327 Replace all the occurrences of AVERROR_EIO with AVERROR(EIO), and mark
stefano
parents: 5206
diff changeset
325 return AVERROR(EIO);
5206
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
326
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
327 res = av_get_packet(pb, pkt, pkt_size);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
328 if (res < 0)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
329 return res;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
330
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
331 pkt->size = res;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
332 pkt->stream_index = 0;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
333 pkt->dts = pkt->pts = caf->frame_cnt;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
334
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
335 caf->packet_cnt++;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
336 caf->frame_cnt += pkt_frames;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
337
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
338 return 0;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
339 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
340
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
341 static int read_seek(AVFormatContext *s, int stream_index,
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
342 int64_t timestamp, int flags)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
343 {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
344 AVStream *st = s->streams[0];
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
345 CaffContext *caf = s->priv_data;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
346 int64_t pos;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
347
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
348 timestamp = FFMAX(timestamp, 0);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
349
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
350 if (caf->frames_per_packet > 0 && caf->bytes_per_packet > 0) {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
351 /* calculate new byte position based on target frame position */
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
352 pos = caf->bytes_per_packet * timestamp / caf->frames_per_packet;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
353 if (caf->data_size > 0)
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
354 pos = FFMIN(pos, caf->data_size);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
355 caf->packet_cnt = pos / caf->bytes_per_packet;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
356 caf->frame_cnt = caf->frames_per_packet * caf->packet_cnt;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
357 } else if (st->nb_index_entries) {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
358 caf->packet_cnt = av_index_search_timestamp(st, timestamp, flags);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
359 caf->frame_cnt = st->index_entries[caf->packet_cnt].timestamp;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
360 pos = st->index_entries[caf->packet_cnt].pos;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
361 } else {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
362 return -1;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
363 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
364
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
365 url_fseek(s->pb, pos + caf->data_start, SEEK_SET);
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
366 return 0;
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
367 }
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
368
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
369 AVInputFormat caf_demuxer = {
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
370 "caf",
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
371 NULL_IF_CONFIG_SMALL("Apple Core Audio Format"),
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
372 sizeof(CaffContext),
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
373 probe,
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
374 read_header,
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
375 read_packet,
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
376 NULL,
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
377 read_seek,
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
378 .codec_tag = (const AVCodecTag*[]){ff_codec_caf_tags, 0},
08c92d88d980 Core Audio Format demuxer
pross
parents:
diff changeset
379 };