]> git.sesse.net Git - ffmpeg/blob - libavformat/takdec.c
avformat/hlsenc: move the segment files handler close to before temp flags process
[ffmpeg] / libavformat / takdec.c
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) {
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 };