Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6147 serge 1
/*
2
 * mtv demuxer
3
 * Copyright (c) 2006 Reynaldo H. Verdejo Pinochet
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
/**
23
 * @file
24
 * MTV demuxer.
25
 */
26
 
27
#include "libavutil/bswap.h"
28
#include "libavutil/intreadwrite.h"
29
#include "avformat.h"
30
#include "internal.h"
31
 
32
#define MTV_ASUBCHUNK_DATA_SIZE 500
33
#define MTV_HEADER_SIZE 512
34
#define MTV_AUDIO_PADDING_SIZE 12
35
#define MTV_IMAGE_DEFAULT_BPP 16
36
#define MTV_AUDIO_SAMPLING_RATE 44100
37
 
38
typedef struct MTVDemuxContext {
39
 
40
    unsigned int file_size;         ///< filesize, not always right
41
    unsigned int segments;          ///< number of 512 byte segments
42
    unsigned int audio_identifier;  ///< 'MP3' on all files I have seen
43
    unsigned int audio_br;          ///< bitrate of audio channel (mp3)
44
    unsigned int img_colorfmt;      ///< frame colorfmt rgb 565/555
45
    unsigned int img_bpp;           ///< frame bits per pixel
46
    unsigned int img_width;
47
    unsigned int img_height;
48
    unsigned int img_segment_size;  ///< size of image segment
49
    unsigned int video_fps;
50
    unsigned int full_segment_size;
51
 
52
} MTVDemuxContext;
53
 
54
static int mtv_probe(AVProbeData *p)
55
{
56
    /* we need at least 57 bytes from the header
57
     * to try parsing all required fields
58
     */
59
    if (p->buf_size < 57)
60
        return 0;
61
 
62
    /* Magic is 'AMV' */
63
    if (*p->buf != 'A' || *(p->buf + 1) != 'M' || *(p->buf + 2) != 'V')
64
        return 0;
65
 
66
    /* Audio magic is always MP3 */
67
    if (p->buf[43] != 'M' || p->buf[44] != 'P' || p->buf[45] != '3')
68
        return 0;
69
 
70
    /* Check for nonzero in bpp and (width|height) header fields */
71
    if(!(p->buf[51] && AV_RL16(&p->buf[52]) | AV_RL16(&p->buf[54])))
72
        return 0;
73
 
74
    /* If width or height are 0 then imagesize header field should not */
75
    if(!AV_RL16(&p->buf[52]) || !AV_RL16(&p->buf[54]))
76
    {
77
        if(!!AV_RL16(&p->buf[56]))
78
            return AVPROBE_SCORE_EXTENSION;
79
        else
80
            return 0;
81
    }
82
 
83
    /* Image bpp is not an absolutely required
84
     * field as we latter claim it should be 16
85
     * no matter what. All samples in the wild
86
     * are RGB565/555.
87
     */
88
    if(p->buf[51] != MTV_IMAGE_DEFAULT_BPP)
89
        return AVPROBE_SCORE_EXTENSION / 2;
90
 
91
    /* We had enough data to parse header values
92
     * but we expect to be able to get 512 bytes
93
     * of header to be sure.
94
     */
95
    if (p->buf_size < MTV_HEADER_SIZE)
96
        return AVPROBE_SCORE_EXTENSION;
97
 
98
    return AVPROBE_SCORE_MAX;
99
}
100
 
101
static int mtv_read_header(AVFormatContext *s)
102
{
103
    MTVDemuxContext *mtv = s->priv_data;
104
    AVIOContext   *pb  = s->pb;
105
    AVStream        *st;
106
    unsigned int    audio_subsegments;
107
 
108
    avio_skip(pb, 3);
109
    mtv->file_size         = avio_rl32(pb);
110
    mtv->segments          = avio_rl32(pb);
111
    avio_skip(pb, 32);
112
    mtv->audio_identifier  = avio_rl24(pb);
113
    mtv->audio_br          = avio_rl16(pb);
114
    mtv->img_colorfmt      = avio_rl24(pb);
115
    mtv->img_bpp           = avio_r8(pb);
116
    mtv->img_width         = avio_rl16(pb);
117
    mtv->img_height        = avio_rl16(pb);
118
    mtv->img_segment_size  = avio_rl16(pb);
119
 
120
    /* Assume 16bpp even if claimed otherwise.
121
     * We know its going to be RGBG565/555 anyway
122
     */
123
    if (mtv->img_bpp != MTV_IMAGE_DEFAULT_BPP) {
124
        av_log (s, AV_LOG_WARNING, "Header claims %dbpp (!= 16). Ignoring\n",
125
                mtv->img_bpp);
126
        mtv->img_bpp = MTV_IMAGE_DEFAULT_BPP;
127
    }
128
 
129
    /* Calculate width and height if missing from header */
130
 
131
    if (!mtv->img_width && mtv->img_height > 0 && mtv->img_bpp >= 8)
132
        mtv->img_width=mtv->img_segment_size / (mtv->img_bpp>>3)
133
                        / mtv->img_height;
134
 
135
    if (!mtv->img_height && mtv->img_width > 0 && mtv->img_bpp >= 8)
136
        mtv->img_height=mtv->img_segment_size / (mtv->img_bpp>>3)
137
                        / mtv->img_width;
138
 
139
    if(!mtv->img_height || !mtv->img_width || !mtv->img_segment_size){
140
        av_log(s, AV_LOG_ERROR, "width or height or segment_size is invalid and I cannot calculate them from other information\n");
141
        return AVERROR_INVALIDDATA;
142
    }
143
 
144
    avio_skip(pb, 4);
145
    audio_subsegments = avio_rl16(pb);
146
 
147
    if (audio_subsegments == 0) {
148
        avpriv_request_sample(s, "MTV files without audio");
149
        return AVERROR_PATCHWELCOME;
150
    }
151
 
152
    mtv->full_segment_size =
153
        audio_subsegments * (MTV_AUDIO_PADDING_SIZE + MTV_ASUBCHUNK_DATA_SIZE) +
154
        mtv->img_segment_size;
155
    mtv->video_fps         = (mtv->audio_br / 4) / audio_subsegments;
156
 
157
    // FIXME Add sanity check here
158
 
159
    // all systems go! init decoders
160
 
161
    // video - raw rgb565
162
 
163
    st = avformat_new_stream(s, NULL);
164
    if(!st)
165
        return AVERROR(ENOMEM);
166
 
167
    avpriv_set_pts_info(st, 64, 1, mtv->video_fps);
168
    st->codec->codec_type      = AVMEDIA_TYPE_VIDEO;
169
    st->codec->codec_id        = AV_CODEC_ID_RAWVIDEO;
170
    st->codec->pix_fmt         = AV_PIX_FMT_RGB565BE;
171
    st->codec->width           = mtv->img_width;
172
    st->codec->height          = mtv->img_height;
173
    st->codec->extradata       = av_strdup("BottomUp");
174
    st->codec->extradata_size  = 9;
175
 
176
    // audio - mp3
177
 
178
    st = avformat_new_stream(s, NULL);
179
    if(!st)
180
        return AVERROR(ENOMEM);
181
 
182
    avpriv_set_pts_info(st, 64, 1, MTV_AUDIO_SAMPLING_RATE);
183
    st->codec->codec_type      = AVMEDIA_TYPE_AUDIO;
184
    st->codec->codec_id        = AV_CODEC_ID_MP3;
185
    st->codec->bit_rate        = mtv->audio_br;
186
    st->need_parsing           = AVSTREAM_PARSE_FULL;
187
 
188
    // Jump over header
189
 
190
    if(avio_seek(pb, MTV_HEADER_SIZE, SEEK_SET) != MTV_HEADER_SIZE)
191
        return AVERROR(EIO);
192
 
193
    return 0;
194
 
195
}
196
 
197
static int mtv_read_packet(AVFormatContext *s, AVPacket *pkt)
198
{
199
    MTVDemuxContext *mtv = s->priv_data;
200
    AVIOContext *pb = s->pb;
201
    int ret;
202
 
203
    if((avio_tell(pb) - s->internal->data_offset + mtv->img_segment_size) % mtv->full_segment_size)
204
    {
205
        avio_skip(pb, MTV_AUDIO_PADDING_SIZE);
206
 
207
        ret = av_get_packet(pb, pkt, MTV_ASUBCHUNK_DATA_SIZE);
208
        if(ret < 0)
209
            return ret;
210
 
211
        pkt->pos -= MTV_AUDIO_PADDING_SIZE;
212
        pkt->stream_index = 1;
213
 
214
    }else
215
    {
216
        ret = av_get_packet(pb, pkt, mtv->img_segment_size);
217
        if(ret < 0)
218
            return ret;
219
 
220
        pkt->stream_index = 0;
221
    }
222
 
223
    return ret;
224
}
225
 
226
AVInputFormat ff_mtv_demuxer = {
227
    .name           = "mtv",
228
    .long_name      = NULL_IF_CONFIG_SMALL("MTV"),
229
    .priv_data_size = sizeof(MTVDemuxContext),
230
    .read_probe     = mtv_probe,
231
    .read_header    = mtv_read_header,
232
    .read_packet    = mtv_read_packet,
233
};