blob: 1535bec64f378749b82f4da53b51a52a812711a4
1 | /* |
2 | * Raw TAK demuxer |
3 | * Copyright (c) 2012 Paul B Mahol |
4 | * |
5 | * This file is part of FFmpeg. |
6 | * |
7 | * FFmpeg is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2.1 of the License, or (at your option) any later version. |
11 | * |
12 | * FFmpeg is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Lesser General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Lesser General Public |
18 | * License along with FFmpeg; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | */ |
21 | |
22 | #include "libavutil/crc.h" |
23 | |
24 | #define BITSTREAM_READER_LE |
25 | #include "libavcodec/tak.h" |
26 | |
27 | #include "apetag.h" |
28 | #include "avformat.h" |
29 | #include "avio_internal.h" |
30 | #include "internal.h" |
31 | #include "rawdec.h" |
32 | |
33 | typedef struct TAKDemuxContext { |
34 | int mlast_frame; |
35 | int64_t data_end; |
36 | } TAKDemuxContext; |
37 | |
38 | static int tak_probe(AVProbeData *p) |
39 | { |
40 | if (!memcmp(p->buf, "tBaK", 4)) |
41 | return AVPROBE_SCORE_EXTENSION; |
42 | return 0; |
43 | } |
44 | |
45 | static unsigned long tak_check_crc(unsigned long checksum, const uint8_t *buf, |
46 | unsigned int len) |
47 | { |
48 | return av_crc(av_crc_get_table(AV_CRC_24_IEEE), checksum, buf, len); |
49 | } |
50 | |
51 | static int tak_read_header(AVFormatContext *s) |
52 | { |
53 | TAKDemuxContext *tc = s->priv_data; |
54 | AVIOContext *pb = s->pb; |
55 | GetBitContext gb; |
56 | AVStream *st; |
57 | uint8_t *buffer = NULL; |
58 | int ret; |
59 | |
60 | st = avformat_new_stream(s, 0); |
61 | if (!st) |
62 | return AVERROR(ENOMEM); |
63 | |
64 | st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; |
65 | st->codecpar->codec_id = AV_CODEC_ID_TAK; |
66 | st->need_parsing = AVSTREAM_PARSE_FULL_RAW; |
67 | |
68 | tc->mlast_frame = 0; |
69 | if (avio_rl32(pb) != MKTAG('t', 'B', 'a', 'K')) { |
70 | avio_seek(pb, -4, SEEK_CUR); |
71 | return 0; |
72 | } |
73 | |
74 | while (!avio_feof(pb)) { |
75 | enum TAKMetaDataType type; |
76 | int size; |
77 | |
78 | type = avio_r8(pb) & 0x7f; |
79 | size = avio_rl24(pb); |
80 | |
81 | switch (type) { |
82 | case TAK_METADATA_STREAMINFO: |
83 | case TAK_METADATA_LAST_FRAME: |
84 | case TAK_METADATA_ENCODER: |
85 | if (size <= 3) |
86 | return AVERROR_INVALIDDATA; |
87 | |
88 | buffer = av_malloc(size - 3 + AV_INPUT_BUFFER_PADDING_SIZE); |
89 | if (!buffer) |
90 | return AVERROR(ENOMEM); |
91 | memset(buffer + size - 3, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
92 | |
93 | ffio_init_checksum(pb, tak_check_crc, 0xCE04B7U); |
94 | if (avio_read(pb, buffer, size - 3) != size - 3) { |
95 | av_freep(&buffer); |
96 | return AVERROR(EIO); |
97 | } |
98 | if (ffio_get_checksum(s->pb) != avio_rb24(pb)) { |
99 | av_log(s, AV_LOG_ERROR, "%d metadata block CRC error.\n", type); |
100 | if (s->error_recognition & AV_EF_EXPLODE) { |
101 | av_freep(&buffer); |
102 | return AVERROR_INVALIDDATA; |
103 | } |
104 | } |
105 | |
106 | init_get_bits8(&gb, buffer, size - 3); |
107 | break; |
108 | case TAK_METADATA_MD5: { |
109 | uint8_t md5[16]; |
110 | int i; |
111 | |
112 | if (size != 19) |
113 | return AVERROR_INVALIDDATA; |
114 | ffio_init_checksum(pb, tak_check_crc, 0xCE04B7U); |
115 | avio_read(pb, md5, 16); |
116 | if (ffio_get_checksum(s->pb) != avio_rb24(pb)) { |
117 | av_log(s, AV_LOG_ERROR, "MD5 metadata block CRC error.\n"); |
118 | if (s->error_recognition & AV_EF_EXPLODE) |
119 | return AVERROR_INVALIDDATA; |
120 | } |
121 | |
122 | av_log(s, AV_LOG_VERBOSE, "MD5="); |
123 | for (i = 0; i < 16; i++) |
124 | av_log(s, AV_LOG_VERBOSE, "%02x", md5[i]); |
125 | av_log(s, AV_LOG_VERBOSE, "\n"); |
126 | break; |
127 | } |
128 | case TAK_METADATA_END: { |
129 | int64_t curpos = avio_tell(pb); |
130 | |
131 | if (pb->seekable & AVIO_SEEKABLE_NORMAL) { |
132 | ff_ape_parse_tag(s); |
133 | avio_seek(pb, curpos, SEEK_SET); |
134 | } |
135 | |
136 | tc->data_end += curpos; |
137 | return 0; |
138 | } |
139 | default: |
140 | ret = avio_skip(pb, size); |
141 | if (ret < 0) |
142 | return ret; |
143 | } |
144 | |
145 | if (type == TAK_METADATA_STREAMINFO) { |
146 | TAKStreamInfo ti; |
147 | |
148 | avpriv_tak_parse_streaminfo(&gb, &ti); |
149 | if (ti.samples > 0) |
150 | st->duration = ti.samples; |
151 | st->codecpar->bits_per_coded_sample = ti.bps; |
152 | if (ti.ch_layout) |
153 | st->codecpar->channel_layout = ti.ch_layout; |
154 | st->codecpar->sample_rate = ti.sample_rate; |
155 | st->codecpar->channels = ti.channels; |
156 | st->start_time = 0; |
157 | avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); |
158 | st->codecpar->extradata = buffer; |
159 | st->codecpar->extradata_size = size - 3; |
160 | buffer = NULL; |
161 | } else if (type == TAK_METADATA_LAST_FRAME) { |
162 | if (size != 11) |
163 | return AVERROR_INVALIDDATA; |
164 | tc->mlast_frame = 1; |
165 | tc->data_end = get_bits64(&gb, TAK_LAST_FRAME_POS_BITS) + |
166 | get_bits(&gb, TAK_LAST_FRAME_SIZE_BITS); |
167 | av_freep(&buffer); |
168 | } else if (type == TAK_METADATA_ENCODER) { |
169 | av_log(s, AV_LOG_VERBOSE, "encoder version: %0X\n", |
170 | get_bits_long(&gb, TAK_ENCODER_VERSION_BITS)); |
171 | av_freep(&buffer); |
172 | } |
173 | } |
174 | |
175 | return AVERROR_EOF; |
176 | } |
177 | |
178 | static int raw_read_packet(AVFormatContext *s, AVPacket *pkt) |
179 | { |
180 | TAKDemuxContext *tc = s->priv_data; |
181 | int ret; |
182 | |
183 | if (tc->mlast_frame) { |
184 | AVIOContext *pb = s->pb; |
185 | int64_t size, left; |
186 | |
187 | left = tc->data_end - avio_tell(pb); |
188 | size = FFMIN(left, 1024); |
189 | if (size <= 0) |
190 | return AVERROR_EOF; |
191 | |
192 | ret = av_get_packet(pb, pkt, size); |
193 | if (ret < 0) |
194 | return ret; |
195 | |
196 | pkt->stream_index = 0; |
197 | } else { |
198 | ret = ff_raw_read_partial_packet(s, pkt); |
199 | } |
200 | |
201 | return ret; |
202 | } |
203 | |
204 | AVInputFormat ff_tak_demuxer = { |
205 | .name = "tak", |
206 | .long_name = NULL_IF_CONFIG_SMALL("raw TAK"), |
207 | .priv_data_size = sizeof(TAKDemuxContext), |
208 | .read_probe = tak_probe, |
209 | .read_header = tak_read_header, |
210 | .read_packet = raw_read_packet, |
211 | .flags = AVFMT_GENERIC_INDEX, |
212 | .extensions = "tak", |
213 | .raw_codec_id = AV_CODEC_ID_TAK, |
214 | }; |
215 |