]> git.sesse.net Git - ffmpeg/blob - libavformat/tta.c
cosmetics: Add #endif comment.
[ffmpeg] / libavformat / tta.c
1 /*
2  * TTA demuxer
3  * Copyright (c) 2006 Alex Beregszaszi
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 #include "avformat.h"
22 #include "bitstream.h"
23
24 typedef struct {
25     int totalframes, currentframe;
26 } TTAContext;
27
28 static int tta_probe(AVProbeData *p)
29 {
30     const uint8_t *d = p->buf;
31     if (d[0] == 'T' && d[1] == 'T' && d[2] == 'A' && d[3] == '1')
32         return 80;
33     return 0;
34 }
35
36 static int tta_read_header(AVFormatContext *s, AVFormatParameters *ap)
37 {
38     TTAContext *c = s->priv_data;
39     AVStream *st;
40     int i, channels, bps, samplerate, datalen, framelen;
41     uint64_t framepos;
42
43     if (get_le32(&s->pb) != ff_get_fourcc("TTA1"))
44         return -1; // not tta file
45
46     url_fskip(&s->pb, 2); // FIXME: flags
47     channels = get_le16(&s->pb);
48     bps = get_le16(&s->pb);
49     samplerate = get_le32(&s->pb);
50     if(samplerate <= 0 || samplerate > 1000000){
51         av_log(s, AV_LOG_ERROR, "nonsense samplerate\n");
52         return -1;
53     }
54
55     datalen = get_le32(&s->pb);
56     if(datalen < 0){
57         av_log(s, AV_LOG_ERROR, "nonsense datalen\n");
58         return -1;
59     }
60
61     url_fskip(&s->pb, 4); // header crc
62
63     framelen = samplerate*256/245;
64     c->totalframes = datalen / framelen + ((datalen % framelen) ? 1 : 0);
65     c->currentframe = 0;
66
67     if(c->totalframes >= UINT_MAX/sizeof(uint32_t)){
68         av_log(s, AV_LOG_ERROR, "totalframes too large\n");
69         return -1;
70     }
71
72     st = av_new_stream(s, 0);
73     if (!st)
74         return AVERROR(ENOMEM);
75
76     av_set_pts_info(st, 64, 1, samplerate);
77     st->start_time = 0;
78     st->duration = datalen;
79
80     framepos = url_ftell(&s->pb) + 4*c->totalframes + 4;
81
82     for (i = 0; i < c->totalframes; i++) {
83         uint32_t size = get_le32(&s->pb);
84         av_add_index_entry(st, framepos, i*framelen, size, 0, AVINDEX_KEYFRAME);
85         framepos += size;
86     }
87     url_fskip(&s->pb, 4); // seektable crc
88
89     st->codec->codec_type = CODEC_TYPE_AUDIO;
90     st->codec->codec_id = CODEC_ID_TTA;
91     st->codec->channels = channels;
92     st->codec->sample_rate = samplerate;
93     st->codec->bits_per_sample = bps;
94
95     st->codec->extradata_size = url_ftell(&s->pb);
96     if(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)st->codec->extradata_size){
97         //this check is redundant as get_buffer should fail
98         av_log(s, AV_LOG_ERROR, "extradata_size too large\n");
99         return -1;
100     }
101     st->codec->extradata = av_mallocz(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE);
102     url_fseek(&s->pb, 0, SEEK_SET);
103     get_buffer(&s->pb, st->codec->extradata, st->codec->extradata_size);
104
105     return 0;
106 }
107
108 static int tta_read_packet(AVFormatContext *s, AVPacket *pkt)
109 {
110     TTAContext *c = s->priv_data;
111     AVStream *st = s->streams[0];
112     int size, ret;
113
114     // FIXME!
115     if (c->currentframe > c->totalframes)
116         return -1;
117
118     size = st->index_entries[c->currentframe].size;
119
120     ret = av_get_packet(&s->pb, pkt, size);
121     pkt->dts = st->index_entries[c->currentframe++].timestamp;
122     return ret;
123 }
124
125 static int tta_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
126 {
127     TTAContext *c = s->priv_data;
128     AVStream *st = s->streams[stream_index];
129     int index = av_index_search_timestamp(st, timestamp, flags);
130     if (index < 0)
131         return -1;
132
133     c->currentframe = index;
134     url_fseek(&s->pb, st->index_entries[index].pos, SEEK_SET);
135
136     return 0;
137 }
138
139 AVInputFormat tta_demuxer = {
140     "tta",
141     "true-audio",
142     sizeof(TTAContext),
143     tta_probe,
144     tta_read_header,
145     tta_read_packet,
146     NULL,
147     tta_read_seek,
148     .extensions = "tta",
149 };