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"
29 typedef struct SMUSHContext
{
31 int audio_stream_index
;
32 int video_stream_index
;
35 static int smush_read_probe(const AVProbeData
*p
)
37 if (((AV_RL32(p
->buf
) == MKTAG('S', 'A', 'N', 'M') &&
38 AV_RL32(p
->buf
+ 8) == MKTAG('S', 'H', 'D', 'R')) ||
39 (AV_RL32(p
->buf
) == MKTAG('A', 'N', 'I', 'M') &&
40 AV_RL32(p
->buf
+ 8) == MKTAG('A', 'H', 'D', 'R')))) {
41 return AVPROBE_SCORE_MAX
;
47 static int smush_read_header(AVFormatContext
*ctx
)
49 SMUSHContext
*smush
= ctx
->priv_data
;
50 AVIOContext
*pb
= ctx
->pb
;
52 uint32_t magic
, nframes
, size
, subversion
, i
;
53 uint32_t width
= 0, height
= 0, got_audio
= 0, read
= 0;
54 uint32_t sample_rate
, channels
, palette
[256], frame_rate
= 15;
57 magic
= avio_rb32(pb
);
58 avio_skip(pb
, 4); // skip movie size
60 if (magic
== MKBETAG('A', 'N', 'I', 'M')) {
61 if (avio_rb32(pb
) != MKBETAG('A', 'H', 'D', 'R'))
62 return AVERROR_INVALIDDATA
;
65 if (size
< 3 * 256 + 6)
66 return AVERROR_INVALIDDATA
;
70 subversion
= avio_rl16(pb
);
71 nframes
= avio_rl16(pb
);
73 return AVERROR_INVALIDDATA
;
75 avio_skip(pb
, 2); // skip pad
77 for (i
= 0; i
< 256; i
++)
78 palette
[i
] = avio_rb24(pb
);
82 return AVERROR_INVALIDDATA
;
84 frame_rate
= avio_rl32(pb
);
85 avio_skip(pb
, 4); // max size of FRME chunk in file
86 sample_rate
= avio_rl32(pb
);
87 if (frame_rate
< 1 || frame_rate
> 70)
91 } else if (magic
== MKBETAG('S', 'A', 'N', 'M')) {
92 if (avio_rb32(pb
) != MKBETAG('S', 'H', 'D', 'R'))
93 return AVERROR_INVALIDDATA
;
97 return AVERROR_INVALIDDATA
;
100 subversion
= avio_rl16(pb
);
101 nframes
= avio_rl32(pb
);
103 return AVERROR_INVALIDDATA
;
105 avio_skip(pb
, 2); // skip pad
106 width
= avio_rl16(pb
);
107 height
= avio_rl16(pb
);
108 avio_skip(pb
, 2); // skip pad
109 avio_skip(pb
, size
- 14);
111 if (avio_rb32(pb
) != MKBETAG('F', 'L', 'H', 'D'))
112 return AVERROR_INVALIDDATA
;
114 size
= avio_rb32(pb
);
115 while (!got_audio
&& ((read
+ 8) < size
)) {
116 uint32_t sig
, chunk_size
;
122 chunk_size
= avio_rb32(pb
);
125 case MKBETAG('W', 'a', 'v', 'e'):
127 sample_rate
= avio_rl32(pb
);
129 return AVERROR_INVALIDDATA
;
131 channels
= avio_rl32(pb
);
133 return AVERROR_INVALIDDATA
;
135 avio_skip(pb
, chunk_size
- 8);
138 case MKBETAG('B', 'l', '1', '6'):
139 case MKBETAG('A', 'N', 'N', 'O'):
140 avio_skip(pb
, chunk_size
);
144 return AVERROR_INVALIDDATA
;
148 avio_skip(pb
, size
- read
);
150 av_log(ctx
, AV_LOG_ERROR
, "Wrong magic\n");
151 return AVERROR_INVALIDDATA
;
154 vst
= avformat_new_stream(ctx
, 0);
156 return AVERROR(ENOMEM
);
158 smush
->video_stream_index
= vst
->index
;
160 avpriv_set_pts_info(vst
, 64, 1, frame_rate
);
164 vst
->nb_frames
= nframes
;
165 vst
->avg_frame_rate
= av_inv_q(vst
->time_base
);
166 vst
->codecpar
->codec_type
= AVMEDIA_TYPE_VIDEO
;
167 vst
->codecpar
->codec_id
= AV_CODEC_ID_SANM
;
168 vst
->codecpar
->codec_tag
= 0;
169 vst
->codecpar
->width
= width
;
170 vst
->codecpar
->height
= height
;
172 if (!smush
->version
) {
173 if ((ret
= ff_alloc_extradata(vst
->codecpar
, 1024 + 2)) < 0)
176 AV_WL16(vst
->codecpar
->extradata
, subversion
);
177 for (i
= 0; i
< 256; i
++)
178 AV_WL32(vst
->codecpar
->extradata
+ 2 + i
* 4, palette
[i
]);
182 ast
= avformat_new_stream(ctx
, 0);
184 return AVERROR(ENOMEM
);
186 smush
->audio_stream_index
= ast
->index
;
189 ast
->codecpar
->codec_type
= AVMEDIA_TYPE_AUDIO
;
190 ast
->codecpar
->codec_id
= AV_CODEC_ID_ADPCM_VIMA
;
191 ast
->codecpar
->codec_tag
= 0;
192 ast
->codecpar
->sample_rate
= sample_rate
;
193 ast
->codecpar
->ch_layout
.nb_channels
= channels
;
194 avpriv_set_pts_info(ast
, 64, 1, ast
->codecpar
->sample_rate
);
200 static int smush_read_packet(AVFormatContext
*ctx
, AVPacket
*pkt
)
202 SMUSHContext
*smush
= ctx
->priv_data
;
203 AVIOContext
*pb
= ctx
->pb
;
214 size
= avio_rb32(pb
);
217 case MKBETAG('F', 'R', 'M', 'E'):
220 if ((ret
= av_get_packet(pb
, pkt
, size
)) < 0)
223 pkt
->stream_index
= smush
->video_stream_index
;
226 case MKBETAG('B', 'l', '1', '6'):
227 if ((ret
= av_get_packet(pb
, pkt
, size
)) < 0)
230 pkt
->stream_index
= smush
->video_stream_index
;
234 case MKBETAG('W', 'a', 'v', 'e'):
236 return AVERROR_INVALIDDATA
;
237 if (av_get_packet(pb
, pkt
, size
) < 13)
238 return AVERROR_INVALIDDATA
;
240 pkt
->stream_index
= smush
->audio_stream_index
;
241 pkt
->flags
|= AV_PKT_FLAG_KEY
;
242 pkt
->duration
= AV_RB32(pkt
->data
);
243 if (pkt
->duration
== 0xFFFFFFFFu
)
244 pkt
->duration
= AV_RB32(pkt
->data
+ 8);
256 const FFInputFormat ff_smush_demuxer
= {
258 .p
.long_name
= NULL_IF_CONFIG_SMALL("LucasArts Smush"),
259 .priv_data_size
= sizeof(SMUSHContext
),
260 .read_probe
= smush_read_probe
,
261 .read_header
= smush_read_header
,
262 .read_packet
= smush_read_packet
,