3 * Copyright (c) 2006 Konstantin Shishkov
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
23 * Based on http://wiki.multimedia.cx/index.php?title=Smacker
28 #include "libavutil/bswap.h"
29 #include "libavutil/channel_layout.h"
30 #include "libavutil/intreadwrite.h"
34 #define SMACKER_PAL 0x01
35 #define SMACKER_FLAG_RING_FRAME 0x01
38 SMK_AUD_PACKED
= 0x80,
39 SMK_AUD_16BITS
= 0x20,
40 SMK_AUD_STEREO
= 0x10,
41 SMK_AUD_BINKAUD
= 0x08,
45 typedef struct SmackerContext
{
46 /* Smacker file header */
48 uint32_t width
, height
;
54 uint32_t mmap_size
, mclr_size
, full_size
, type_size
;
61 /* internal variables */
65 /* current frame for demuxing */
77 typedef struct SmackerFrame
{
82 /* palette used in Smacker */
83 static const uint8_t smk_pal
[64] = {
84 0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C,
85 0x20, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C,
86 0x41, 0x45, 0x49, 0x4D, 0x51, 0x55, 0x59, 0x5D,
87 0x61, 0x65, 0x69, 0x6D, 0x71, 0x75, 0x79, 0x7D,
88 0x82, 0x86, 0x8A, 0x8E, 0x92, 0x96, 0x9A, 0x9E,
89 0xA2, 0xA6, 0xAA, 0xAE, 0xB2, 0xB6, 0xBA, 0xBE,
90 0xC3, 0xC7, 0xCB, 0xCF, 0xD3, 0xD7, 0xDB, 0xDF,
91 0xE3, 0xE7, 0xEB, 0xEF, 0xF3, 0xF7, 0xFB, 0xFF
95 static int smacker_probe(AVProbeData
*p
)
97 if ( AV_RL32(p
->buf
) != MKTAG('S', 'M', 'K', '2')
98 && AV_RL32(p
->buf
) != MKTAG('S', 'M', 'K', '4'))
101 if (AV_RL32(p
->buf
+4) > 32768U || AV_RL32(p
->buf
+8) > 32768U)
102 return AVPROBE_SCORE_MAX
/4;
104 return AVPROBE_SCORE_MAX
;
107 static int smacker_read_header(AVFormatContext
*s
)
109 AVIOContext
*pb
= s
->pb
;
110 SmackerContext
*smk
= s
->priv_data
;
111 AVStream
*st
, *ast
[7];
115 /* read and check header */
116 smk
->magic
= avio_rl32(pb
);
117 if (smk
->magic
!= MKTAG('S', 'M', 'K', '2') && smk
->magic
!= MKTAG('S', 'M', 'K', '4'))
118 return AVERROR_INVALIDDATA
;
119 smk
->width
= avio_rl32(pb
);
120 smk
->height
= avio_rl32(pb
);
121 smk
->frames
= avio_rl32(pb
);
122 smk
->pts_inc
= (int32_t)avio_rl32(pb
);
123 if (smk
->pts_inc
> INT_MAX
/ 100) {
124 av_log(s
, AV_LOG_ERROR
, "pts_inc %d is too large\n", smk
->pts_inc
);
125 return AVERROR_INVALIDDATA
;
128 smk
->flags
= avio_rl32(pb
);
129 if(smk
->flags
& SMACKER_FLAG_RING_FRAME
)
131 for(i
= 0; i
< 7; i
++)
132 smk
->audio
[i
] = avio_rl32(pb
);
133 smk
->treesize
= avio_rl32(pb
);
135 if(smk
->treesize
>= UINT_MAX
/4){ // smk->treesize + 16 must not overflow (this check is probably redundant)
136 av_log(s
, AV_LOG_ERROR
, "treesize too large\n");
137 return AVERROR_INVALIDDATA
;
140 //FIXME remove extradata "rebuilding"
141 smk
->mmap_size
= avio_rl32(pb
);
142 smk
->mclr_size
= avio_rl32(pb
);
143 smk
->full_size
= avio_rl32(pb
);
144 smk
->type_size
= avio_rl32(pb
);
145 for(i
= 0; i
< 7; i
++) {
146 smk
->rates
[i
] = avio_rl24(pb
);
147 smk
->aflags
[i
] = avio_r8(pb
);
149 smk
->pad
= avio_rl32(pb
);
151 if(smk
->frames
> 0xFFFFFF) {
152 av_log(s
, AV_LOG_ERROR
, "Too many frames: %"PRIu32
"\n", smk
->frames
);
153 return AVERROR_INVALIDDATA
;
155 smk
->frm_size
= av_malloc_array(smk
->frames
, sizeof(*smk
->frm_size
));
156 smk
->frm_flags
= av_malloc(smk
->frames
);
157 if (!smk
->frm_size
|| !smk
->frm_flags
) {
158 av_freep(&smk
->frm_size
);
159 av_freep(&smk
->frm_flags
);
160 return AVERROR(ENOMEM
);
163 smk
->is_ver4
= (smk
->magic
!= MKTAG('S', 'M', 'K', '2'));
165 /* read frame info */
166 for(i
= 0; i
< smk
->frames
; i
++) {
167 smk
->frm_size
[i
] = avio_rl32(pb
);
169 for(i
= 0; i
< smk
->frames
; i
++) {
170 smk
->frm_flags
[i
] = avio_r8(pb
);
173 /* init video codec */
174 st
= avformat_new_stream(s
, NULL
);
176 return AVERROR(ENOMEM
);
177 smk
->videoindex
= st
->index
;
178 st
->codecpar
->width
= smk
->width
;
179 st
->codecpar
->height
= smk
->height
;
180 st
->codecpar
->format
= AV_PIX_FMT_PAL8
;
181 st
->codecpar
->codec_type
= AVMEDIA_TYPE_VIDEO
;
182 st
->codecpar
->codec_id
= AV_CODEC_ID_SMACKVIDEO
;
183 st
->codecpar
->codec_tag
= smk
->magic
;
184 /* Smacker uses 100000 as internal timebase */
186 smk
->pts_inc
= -smk
->pts_inc
;
190 av_reduce(&tbase
, &smk
->pts_inc
, tbase
, smk
->pts_inc
, (1UL<<31)-1);
191 avpriv_set_pts_info(st
, 33, smk
->pts_inc
, tbase
);
192 st
->duration
= smk
->frames
;
193 /* handle possible audio streams */
194 for(i
= 0; i
< 7; i
++) {
195 smk
->indexes
[i
] = -1;
197 ast
[i
] = avformat_new_stream(s
, NULL
);
199 return AVERROR(ENOMEM
);
200 smk
->indexes
[i
] = ast
[i
]->index
;
201 ast
[i
]->codecpar
->codec_type
= AVMEDIA_TYPE_AUDIO
;
202 if (smk
->aflags
[i
] & SMK_AUD_BINKAUD
) {
203 ast
[i
]->codecpar
->codec_id
= AV_CODEC_ID_BINKAUDIO_RDFT
;
204 } else if (smk
->aflags
[i
] & SMK_AUD_USEDCT
) {
205 ast
[i
]->codecpar
->codec_id
= AV_CODEC_ID_BINKAUDIO_DCT
;
206 } else if (smk
->aflags
[i
] & SMK_AUD_PACKED
){
207 ast
[i
]->codecpar
->codec_id
= AV_CODEC_ID_SMACKAUDIO
;
208 ast
[i
]->codecpar
->codec_tag
= MKTAG('S', 'M', 'K', 'A');
210 ast
[i
]->codecpar
->codec_id
= AV_CODEC_ID_PCM_U8
;
212 if (smk
->aflags
[i
] & SMK_AUD_STEREO
) {
213 ast
[i
]->codecpar
->channels
= 2;
214 ast
[i
]->codecpar
->channel_layout
= AV_CH_LAYOUT_STEREO
;
216 ast
[i
]->codecpar
->channels
= 1;
217 ast
[i
]->codecpar
->channel_layout
= AV_CH_LAYOUT_MONO
;
219 ast
[i
]->codecpar
->sample_rate
= smk
->rates
[i
];
220 ast
[i
]->codecpar
->bits_per_coded_sample
= (smk
->aflags
[i
] & SMK_AUD_16BITS
) ? 16 : 8;
221 if(ast
[i
]->codecpar
->bits_per_coded_sample
== 16 && ast
[i
]->codecpar
->codec_id
== AV_CODEC_ID_PCM_U8
)
222 ast
[i
]->codecpar
->codec_id
= AV_CODEC_ID_PCM_S16LE
;
223 avpriv_set_pts_info(ast
[i
], 64, 1, ast
[i
]->codecpar
->sample_rate
224 * ast
[i
]->codecpar
->channels
* ast
[i
]->codecpar
->bits_per_coded_sample
/ 8);
229 /* load trees to extradata, they will be unpacked by decoder */
230 if(ff_alloc_extradata(st
->codecpar
, smk
->treesize
+ 16)){
231 av_log(s
, AV_LOG_ERROR
,
232 "Cannot allocate %"PRIu32
" bytes of extradata\n",
234 av_freep(&smk
->frm_size
);
235 av_freep(&smk
->frm_flags
);
236 return AVERROR(ENOMEM
);
238 ret
= avio_read(pb
, st
->codecpar
->extradata
+ 16, st
->codecpar
->extradata_size
- 16);
239 if(ret
!= st
->codecpar
->extradata_size
- 16){
240 av_freep(&smk
->frm_size
);
241 av_freep(&smk
->frm_flags
);
244 ((int32_t*)st
->codecpar
->extradata
)[0] = av_le2ne32(smk
->mmap_size
);
245 ((int32_t*)st
->codecpar
->extradata
)[1] = av_le2ne32(smk
->mclr_size
);
246 ((int32_t*)st
->codecpar
->extradata
)[2] = av_le2ne32(smk
->full_size
);
247 ((int32_t*)st
->codecpar
->extradata
)[3] = av_le2ne32(smk
->type_size
);
250 smk
->nextpos
= avio_tell(pb
);
256 static int smacker_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
258 SmackerContext
*smk
= s
->priv_data
;
265 if (avio_feof(s
->pb
) || smk
->cur_frame
>= smk
->frames
)
268 /* if we demuxed all streams, pass another frame */
269 if(smk
->curstream
< 0) {
270 avio_seek(s
->pb
, smk
->nextpos
, 0);
271 frame_size
= smk
->frm_size
[smk
->cur_frame
] & (~3);
272 flags
= smk
->frm_flags
[smk
->cur_frame
];
273 /* handle palette change event */
274 if(flags
& SMACKER_PAL
){
275 int size
, sz
, t
, off
, j
, pos
;
276 uint8_t *pal
= smk
->pal
;
279 memcpy(oldpal
, pal
, 768);
280 size
= avio_r8(s
->pb
);
282 if(size
+ 1 > frame_size
)
283 return AVERROR_INVALIDDATA
;
287 pos
= avio_tell(s
->pb
) + size
;
290 if(t
& 0x80){ /* skip palette entries */
291 sz
+= (t
& 0x7F) + 1;
292 pal
+= ((t
& 0x7F) + 1) * 3;
293 } else if(t
& 0x40){ /* copy with offset */
294 off
= avio_r8(s
->pb
);
296 if (off
+ j
> 0x100) {
297 av_log(s
, AV_LOG_ERROR
,
298 "Invalid palette update, offset=%d length=%d extends beyond palette size\n",
300 return AVERROR_INVALIDDATA
;
303 while(j
-- && sz
< 256) {
304 *pal
++ = oldpal
[off
+ 0];
305 *pal
++ = oldpal
[off
+ 1];
306 *pal
++ = oldpal
[off
+ 2];
310 } else { /* new entries */
312 *pal
++ = smk_pal
[avio_r8(s
->pb
) & 0x3F];
313 *pal
++ = smk_pal
[avio_r8(s
->pb
) & 0x3F];
317 avio_seek(s
->pb
, pos
, 0);
322 /* if audio chunks are present, put them to stack and retrieve later */
323 for(i
= 0; i
< 7; i
++) {
328 size
= avio_rl32(s
->pb
) - 4;
329 if (!size
|| size
+ 4LL > frame_size
) {
330 av_log(s
, AV_LOG_ERROR
, "Invalid audio part size\n");
331 return AVERROR_INVALIDDATA
;
336 if ((err
= av_reallocp(&smk
->bufs
[smk
->curstream
], size
)) < 0) {
337 smk
->buf_sizes
[smk
->curstream
] = 0;
340 smk
->buf_sizes
[smk
->curstream
] = size
;
341 ret
= avio_read(s
->pb
, smk
->bufs
[smk
->curstream
], size
);
344 smk
->stream_id
[smk
->curstream
] = smk
->indexes
[i
];
348 if (frame_size
< 0 || frame_size
>= INT_MAX
/2)
349 return AVERROR_INVALIDDATA
;
350 if (av_new_packet(pkt
, frame_size
+ 769))
351 return AVERROR(ENOMEM
);
352 if(smk
->frm_size
[smk
->cur_frame
] & 1)
354 pkt
->data
[0] = palchange
;
355 memcpy(pkt
->data
+ 1, smk
->pal
, 768);
356 ret
= avio_read(s
->pb
, pkt
->data
+ 769, frame_size
);
357 if(ret
!= frame_size
)
359 pkt
->stream_index
= smk
->videoindex
;
360 pkt
->pts
= smk
->cur_frame
;
361 pkt
->size
= ret
+ 769;
363 smk
->nextpos
= avio_tell(s
->pb
);
365 if (smk
->stream_id
[smk
->curstream
] < 0 || !smk
->bufs
[smk
->curstream
])
366 return AVERROR_INVALIDDATA
;
367 if (av_new_packet(pkt
, smk
->buf_sizes
[smk
->curstream
]))
368 return AVERROR(ENOMEM
);
369 memcpy(pkt
->data
, smk
->bufs
[smk
->curstream
], smk
->buf_sizes
[smk
->curstream
]);
370 pkt
->size
= smk
->buf_sizes
[smk
->curstream
];
371 pkt
->stream_index
= smk
->stream_id
[smk
->curstream
];
372 pkt
->pts
= smk
->aud_pts
[smk
->curstream
];
373 smk
->aud_pts
[smk
->curstream
] += AV_RL32(pkt
->data
);
380 static int smacker_read_close(AVFormatContext
*s
)
382 SmackerContext
*smk
= s
->priv_data
;
385 for(i
= 0; i
< 7; i
++)
386 av_freep(&smk
->bufs
[i
]);
387 av_freep(&smk
->frm_size
);
388 av_freep(&smk
->frm_flags
);
393 AVInputFormat ff_smacker_demuxer
= {
395 .long_name
= NULL_IF_CONFIG_SMALL("Smacker"),
396 .priv_data_size
= sizeof(SmackerContext
),
397 .read_probe
= smacker_probe
,
398 .read_header
= smacker_read_header
,
399 .read_packet
= smacker_read_packet
,
400 .read_close
= smacker_read_close
,