2 * LucasArts Smush demuxer
3 * Copyright (c) 2006 Cyril Zorin
5 * This file is part of FFmpeg.
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.
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.
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
22 #include "libavutil/intreadwrite.h"
28 typedef struct SMUSHContext
{
30 int audio_stream_index
;
31 int video_stream_index
;
34 static int smush_read_probe(AVProbeData
*p
)
36 if (((AV_RL32(p
->buf
) == MKTAG('S', 'A', 'N', 'M') &&
37 AV_RL32(p
->buf
+ 8) == MKTAG('S', 'H', 'D', 'R')) ||
38 (AV_RL32(p
->buf
) == MKTAG('A', 'N', 'I', 'M') &&
39 AV_RL32(p
->buf
+ 8) == MKTAG('A', 'H', 'D', 'R')))) {
40 return AVPROBE_SCORE_MAX
;
46 static int smush_read_header(AVFormatContext
*ctx
)
48 SMUSHContext
*smush
= ctx
->priv_data
;
49 AVIOContext
*pb
= ctx
->pb
;
51 uint32_t magic
, nframes
, size
, subversion
, i
;
52 uint32_t width
= 0, height
= 0, got_audio
= 0, read
= 0;
53 uint32_t sample_rate
, channels
, palette
[256];
55 magic
= avio_rb32(pb
);
56 avio_skip(pb
, 4); // skip movie size
58 if (magic
== MKBETAG('A', 'N', 'I', 'M')) {
59 if (avio_rb32(pb
) != MKBETAG('A', 'H', 'D', 'R'))
60 return AVERROR_INVALIDDATA
;
63 if (size
< 3 * 256 + 6)
64 return AVERROR_INVALIDDATA
;
67 subversion
= avio_rl16(pb
);
68 nframes
= avio_rl16(pb
);
70 return AVERROR_INVALIDDATA
;
72 avio_skip(pb
, 2); // skip pad
74 for (i
= 0; i
< 256; i
++)
75 palette
[i
] = avio_rb24(pb
);
77 avio_skip(pb
, size
- (3 * 256 + 6));
78 } else if (magic
== MKBETAG('S', 'A', 'N', 'M')) {
79 if (avio_rb32(pb
) != MKBETAG('S', 'H', 'D', 'R'))
80 return AVERROR_INVALIDDATA
;
84 return AVERROR_INVALIDDATA
;
87 subversion
= avio_rl16(pb
);
88 nframes
= avio_rl32(pb
);
90 return AVERROR_INVALIDDATA
;
92 avio_skip(pb
, 2); // skip pad
93 width
= avio_rl16(pb
);
94 height
= avio_rl16(pb
);
95 avio_skip(pb
, 2); // skip pad
96 avio_skip(pb
, size
- 14);
98 if (avio_rb32(pb
) != MKBETAG('F', 'L', 'H', 'D'))
99 return AVERROR_INVALIDDATA
;
101 size
= avio_rb32(pb
);
102 while (!got_audio
&& ((read
+ 8) < size
)) {
103 uint32_t sig
, chunk_size
;
109 chunk_size
= avio_rb32(pb
);
112 case MKBETAG('W', 'a', 'v', 'e'):
114 sample_rate
= avio_rl32(pb
);
116 return AVERROR_INVALIDDATA
;
118 channels
= avio_rl32(pb
);
120 return AVERROR_INVALIDDATA
;
122 avio_skip(pb
, chunk_size
- 8);
125 case MKBETAG('B', 'l', '1', '6'):
126 case MKBETAG('A', 'N', 'N', 'O'):
127 avio_skip(pb
, chunk_size
);
131 return AVERROR_INVALIDDATA
;
136 avio_skip(pb
, size
- read
);
138 av_log(ctx
, AV_LOG_ERROR
, "Wrong magic\n");
139 return AVERROR_INVALIDDATA
;
142 vst
= avformat_new_stream(ctx
, 0);
144 return AVERROR(ENOMEM
);
146 smush
->video_stream_index
= vst
->index
;
148 avpriv_set_pts_info(vst
, 64, 1, 15);
152 vst
->nb_frames
= nframes
;
153 vst
->avg_frame_rate
= av_inv_q(vst
->time_base
);
154 vst
->codec
->codec_type
= AVMEDIA_TYPE_VIDEO
;
155 vst
->codec
->codec_id
= AV_CODEC_ID_SANM
;
156 vst
->codec
->codec_tag
= 0;
157 vst
->codec
->width
= width
;
158 vst
->codec
->height
= height
;
160 if (!smush
->version
) {
161 if (ff_alloc_extradata(vst
->codec
, 1024 + 2))
162 return AVERROR(ENOMEM
);
164 AV_WL16(vst
->codec
->extradata
, subversion
);
165 for (i
= 0; i
< 256; i
++)
166 AV_WL32(vst
->codec
->extradata
+ 2 + i
* 4, palette
[i
]);
170 ast
= avformat_new_stream(ctx
, 0);
172 return AVERROR(ENOMEM
);
174 smush
->audio_stream_index
= ast
->index
;
177 ast
->codec
->codec_type
= AVMEDIA_TYPE_AUDIO
;
178 ast
->codec
->codec_id
= AV_CODEC_ID_ADPCM_VIMA
;
179 ast
->codec
->codec_tag
= 0;
180 ast
->codec
->sample_rate
= sample_rate
;
181 ast
->codec
->channels
= channels
;
183 avpriv_set_pts_info(ast
, 64, 1, ast
->codec
->sample_rate
);
189 static int smush_read_packet(AVFormatContext
*ctx
, AVPacket
*pkt
)
191 SMUSHContext
*smush
= ctx
->priv_data
;
192 AVIOContext
*pb
= ctx
->pb
;
203 size
= avio_rb32(pb
);
206 case MKBETAG('F', 'R', 'M', 'E'):
209 if ((ret
= av_get_packet(pb
, pkt
, size
)) < 0)
212 pkt
->stream_index
= smush
->video_stream_index
;
215 case MKBETAG('B', 'l', '1', '6'):
216 if ((ret
= av_get_packet(pb
, pkt
, size
)) < 0)
219 pkt
->stream_index
= smush
->video_stream_index
;
223 case MKBETAG('W', 'a', 'v', 'e'):
225 return AVERROR_INVALIDDATA
;
226 if (av_get_packet(pb
, pkt
, size
) < 13)
229 pkt
->stream_index
= smush
->audio_stream_index
;
230 pkt
->flags
|= AV_PKT_FLAG_KEY
;
231 pkt
->duration
= AV_RB32(pkt
->data
);
232 if (pkt
->duration
== 0xFFFFFFFFu
)
233 pkt
->duration
= AV_RB32(pkt
->data
+ 8);
245 AVInputFormat ff_smush_demuxer
= {
247 .long_name
= NULL_IF_CONFIG_SMALL("LucasArts Smush"),
248 .priv_data_size
= sizeof(SMUSHContext
),
249 .read_probe
= smush_read_probe
,
250 .read_header
= smush_read_header
,
251 .read_packet
= smush_read_packet
,