~ubuntu-branches/ubuntu/utopic/libav/utopic-proposed

« back to all changes in this revision

Viewing changes to libavformat/paf.c

  • Committer: Package Import Robot
  • Author(s): Reinhard Tartler, Reinhard Tartler, Rico Tzschichholz
  • Date: 2014-08-30 11:02:45 UTC
  • mfrom: (1.3.47 sid)
  • Revision ID: package-import@ubuntu.com-20140830110245-io3dg7q85wfr7125
Tags: 6:11~beta1-2
[ Reinhard Tartler ]
* Make libavcodec-dev depend on libavresample-dev

[ Rico Tzschichholz ]
* Some fixes and leftovers from soname bumps

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Packed Animation File demuxer
 
3
 * Copyright (c) 2012 Paul B Mahol
 
4
 *
 
5
 * This file is part of Libav.
 
6
 *
 
7
 * Libav 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
 * Libav 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 Libav; 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/channel_layout.h"
 
23
 
 
24
#include "avformat.h"
 
25
#include "internal.h"
 
26
 
 
27
#define MAGIC "Packed Animation File V1.0\n(c) 1992-96 Amazing Studio\x0a\x1a"
 
28
#define PAF_SOUND_SAMPLES     2205
 
29
#define PAF_SOUND_FRAME_SIZE  ((256 + PAF_SOUND_SAMPLES) * 2)
 
30
 
 
31
typedef struct {
 
32
    uint32_t buffer_size;
 
33
    uint32_t frame_blks;
 
34
    uint32_t nb_frames;
 
35
    uint32_t start_offset;
 
36
    uint32_t preload_count;
 
37
    uint32_t max_video_blks;
 
38
    uint32_t max_audio_blks;
 
39
 
 
40
    uint32_t current_frame;
 
41
    uint32_t current_frame_count;
 
42
    uint32_t current_frame_block;
 
43
 
 
44
    uint32_t *blocks_count_table;
 
45
    uint32_t *frames_offset_table;
 
46
    uint32_t *blocks_offset_table;
 
47
 
 
48
    uint8_t  *video_frame;
 
49
    int video_size;
 
50
 
 
51
    uint8_t  *audio_frame;
 
52
    uint8_t  *temp_audio_frame;
 
53
    int audio_size;
 
54
 
 
55
    int got_audio;
 
56
} PAFDemuxContext;
 
57
 
 
58
static int read_probe(AVProbeData *p)
 
59
{
 
60
    if ((p->buf_size >= strlen(MAGIC)) &&
 
61
        !memcmp(p->buf, MAGIC, strlen(MAGIC)))
 
62
        return AVPROBE_SCORE_MAX;
 
63
    return 0;
 
64
}
 
65
 
 
66
static int read_close(AVFormatContext *s)
 
67
{
 
68
    PAFDemuxContext *p = s->priv_data;
 
69
 
 
70
    av_freep(&p->blocks_count_table);
 
71
    av_freep(&p->frames_offset_table);
 
72
    av_freep(&p->blocks_offset_table);
 
73
    av_freep(&p->video_frame);
 
74
    av_freep(&p->audio_frame);
 
75
    av_freep(&p->temp_audio_frame);
 
76
 
 
77
    return 0;
 
78
}
 
79
 
 
80
static void read_table(AVFormatContext *s, uint32_t *table, uint32_t count)
 
81
{
 
82
    int i;
 
83
 
 
84
    for (i = 0; i < count; i++)
 
85
        table[i] = avio_rl32(s->pb);
 
86
 
 
87
    avio_skip(s->pb, 4 * (FFALIGN(count, 512) - count));
 
88
}
 
89
 
 
90
static int read_header(AVFormatContext *s)
 
91
{
 
92
    PAFDemuxContext *p  = s->priv_data;
 
93
    AVIOContext     *pb = s->pb;
 
94
    AVStream        *ast, *vst;
 
95
    int ret = 0;
 
96
 
 
97
    avio_skip(pb, 132);
 
98
 
 
99
    vst = avformat_new_stream(s, 0);
 
100
    if (!vst)
 
101
        return AVERROR(ENOMEM);
 
102
 
 
103
    vst->start_time = 0;
 
104
    vst->nb_frames  =
 
105
    vst->duration   =
 
106
    p->nb_frames    = avio_rl32(pb);
 
107
    avio_skip(pb, 4);
 
108
 
 
109
    vst->codec->width  = avio_rl32(pb);
 
110
    vst->codec->height = avio_rl32(pb);
 
111
    avio_skip(pb, 4);
 
112
 
 
113
    vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
 
114
    vst->codec->codec_tag  = 0;
 
115
    vst->codec->codec_id   = AV_CODEC_ID_PAF_VIDEO;
 
116
    avpriv_set_pts_info(vst, 64, 1, 10);
 
117
 
 
118
    ast = avformat_new_stream(s, 0);
 
119
    if (!ast)
 
120
        return AVERROR(ENOMEM);
 
121
 
 
122
    ast->start_time            = 0;
 
123
    ast->codec->codec_type     = AVMEDIA_TYPE_AUDIO;
 
124
    ast->codec->codec_tag      = 0;
 
125
    ast->codec->codec_id       = AV_CODEC_ID_PAF_AUDIO;
 
126
    ast->codec->channels       = 2;
 
127
    ast->codec->channel_layout = AV_CH_LAYOUT_STEREO;
 
128
    ast->codec->sample_rate    = 22050;
 
129
    avpriv_set_pts_info(ast, 64, 1, 22050);
 
130
 
 
131
    p->buffer_size    = avio_rl32(pb);
 
132
    p->preload_count  = avio_rl32(pb);
 
133
    p->frame_blks     = avio_rl32(pb);
 
134
    p->start_offset   = avio_rl32(pb);
 
135
    p->max_video_blks = avio_rl32(pb);
 
136
    p->max_audio_blks = avio_rl32(pb);
 
137
    if (p->buffer_size    < 175  ||
 
138
        p->max_audio_blks < 2    ||
 
139
        p->max_video_blks < 1    ||
 
140
        p->frame_blks     < 1    ||
 
141
        p->nb_frames      < 1    ||
 
142
        p->preload_count  < 1    ||
 
143
        p->buffer_size    > 2048 ||
 
144
        p->max_video_blks > 2048 ||
 
145
        p->max_audio_blks > 2048 ||
 
146
        p->nb_frames      > INT_MAX / sizeof(uint32_t) ||
 
147
        p->frame_blks     > INT_MAX / sizeof(uint32_t))
 
148
        return AVERROR_INVALIDDATA;
 
149
 
 
150
    p->blocks_count_table  = av_mallocz(p->nb_frames *
 
151
                                        sizeof(*p->blocks_count_table));
 
152
    p->frames_offset_table = av_mallocz(p->nb_frames *
 
153
                                        sizeof(*p->frames_offset_table));
 
154
    p->blocks_offset_table = av_mallocz(p->frame_blks *
 
155
                                        sizeof(*p->blocks_offset_table));
 
156
 
 
157
    p->video_size  = p->max_video_blks * p->buffer_size;
 
158
    p->video_frame = av_mallocz(p->video_size);
 
159
 
 
160
    p->audio_size       = p->max_audio_blks * p->buffer_size;
 
161
    p->audio_frame      = av_mallocz(p->audio_size);
 
162
    p->temp_audio_frame = av_mallocz(p->audio_size);
 
163
 
 
164
    if (!p->blocks_count_table  ||
 
165
        !p->frames_offset_table ||
 
166
        !p->blocks_offset_table ||
 
167
        !p->video_frame         ||
 
168
        !p->audio_frame         ||
 
169
        !p->temp_audio_frame) {
 
170
        ret = AVERROR(ENOMEM);
 
171
        goto fail;
 
172
    }
 
173
 
 
174
    avio_seek(pb, p->buffer_size, SEEK_SET);
 
175
 
 
176
    read_table(s, p->blocks_count_table,  p->nb_frames);
 
177
    read_table(s, p->frames_offset_table, p->nb_frames);
 
178
    read_table(s, p->blocks_offset_table, p->frame_blks);
 
179
 
 
180
    p->got_audio = 0;
 
181
    p->current_frame = 0;
 
182
    p->current_frame_block = 0;
 
183
 
 
184
    avio_seek(pb, p->start_offset, SEEK_SET);
 
185
 
 
186
    return 0;
 
187
 
 
188
fail:
 
189
    read_close(s);
 
190
 
 
191
    return ret;
 
192
}
 
193
 
 
194
static int read_packet(AVFormatContext *s, AVPacket *pkt)
 
195
{
 
196
    PAFDemuxContext *p  = s->priv_data;
 
197
    AVIOContext     *pb = s->pb;
 
198
    uint32_t count, offset;
 
199
    int size, i;
 
200
 
 
201
    if (p->current_frame >= p->nb_frames || pb->eof_reached)
 
202
        return AVERROR_EOF;
 
203
 
 
204
    if (p->got_audio) {
 
205
        if (av_new_packet(pkt, p->audio_size) < 0)
 
206
            return AVERROR(ENOMEM);
 
207
 
 
208
        memcpy(pkt->data, p->temp_audio_frame, p->audio_size);
 
209
        pkt->duration     = PAF_SOUND_SAMPLES * (p->audio_size / PAF_SOUND_FRAME_SIZE);
 
210
        pkt->flags       |= AV_PKT_FLAG_KEY;
 
211
        pkt->stream_index = 1;
 
212
        p->got_audio      = 0;
 
213
        return pkt->size;
 
214
    }
 
215
 
 
216
    count = (p->current_frame == 0) ? p->preload_count
 
217
                                    : p->blocks_count_table[p->current_frame - 1];
 
218
    for (i = 0; i < count; i++) {
 
219
        if (p->current_frame_block >= p->frame_blks)
 
220
            return AVERROR_INVALIDDATA;
 
221
 
 
222
        offset = p->blocks_offset_table[p->current_frame_block] & ~(1U << 31);
 
223
        if (p->blocks_offset_table[p->current_frame_block] & (1U << 31)) {
 
224
            if (offset > p->audio_size - p->buffer_size)
 
225
                return AVERROR_INVALIDDATA;
 
226
 
 
227
            avio_read(pb, p->audio_frame + offset, p->buffer_size);
 
228
            if (offset == (p->max_audio_blks - 2) * p->buffer_size) {
 
229
                memcpy(p->temp_audio_frame, p->audio_frame, p->audio_size);
 
230
                p->got_audio = 1;
 
231
            }
 
232
        } else {
 
233
            if (offset > p->video_size - p->buffer_size)
 
234
                return AVERROR_INVALIDDATA;
 
235
 
 
236
            avio_read(pb, p->video_frame + offset, p->buffer_size);
 
237
        }
 
238
        p->current_frame_block++;
 
239
    }
 
240
 
 
241
    if (p->frames_offset_table[p->current_frame] >= p->video_size)
 
242
        return AVERROR_INVALIDDATA;
 
243
 
 
244
    size = p->video_size - p->frames_offset_table[p->current_frame];
 
245
 
 
246
    if (av_new_packet(pkt, size) < 0)
 
247
        return AVERROR(ENOMEM);
 
248
 
 
249
    pkt->stream_index = 0;
 
250
    pkt->duration     = 1;
 
251
    memcpy(pkt->data, p->video_frame + p->frames_offset_table[p->current_frame], size);
 
252
    if (pkt->data[0] & 0x20)
 
253
        pkt->flags |= AV_PKT_FLAG_KEY;
 
254
    p->current_frame++;
 
255
 
 
256
    return pkt->size;
 
257
}
 
258
 
 
259
AVInputFormat ff_paf_demuxer = {
 
260
    .name           = "paf",
 
261
    .long_name      = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File"),
 
262
    .priv_data_size = sizeof(PAFDemuxContext),
 
263
    .read_probe     = read_probe,
 
264
    .read_header    = read_header,
 
265
    .read_packet    = read_packet,
 
266
    .read_close     = read_close,
 
267
};