1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Smacker demuxer 3cabdff1aSopenharmony_ci * Copyright (c) 2006 Konstantin Shishkov 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci/* 23cabdff1aSopenharmony_ci * Based on http://wiki.multimedia.cx/index.php?title=Smacker 24cabdff1aSopenharmony_ci */ 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_ci#include <inttypes.h> 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_ci#include "libavutil/channel_layout.h" 29cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 30cabdff1aSopenharmony_ci#include "avformat.h" 31cabdff1aSopenharmony_ci#include "avio_internal.h" 32cabdff1aSopenharmony_ci#include "demux.h" 33cabdff1aSopenharmony_ci#include "internal.h" 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_ci#define SMACKER_PAL 0x01 36cabdff1aSopenharmony_ci#define SMACKER_FLAG_RING_FRAME 0x01 37cabdff1aSopenharmony_ci 38cabdff1aSopenharmony_cienum SAudFlags { 39cabdff1aSopenharmony_ci SMK_AUD_PACKED = 0x80, 40cabdff1aSopenharmony_ci SMK_AUD_16BITS = 0x20, 41cabdff1aSopenharmony_ci SMK_AUD_STEREO = 0x10, 42cabdff1aSopenharmony_ci SMK_AUD_BINKAUD = 0x08, 43cabdff1aSopenharmony_ci SMK_AUD_USEDCT = 0x04 44cabdff1aSopenharmony_ci}; 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_citypedef struct SmackerContext { 47cabdff1aSopenharmony_ci uint32_t frames; 48cabdff1aSopenharmony_ci /* frame info */ 49cabdff1aSopenharmony_ci uint32_t *frm_size; 50cabdff1aSopenharmony_ci uint8_t *frm_flags; 51cabdff1aSopenharmony_ci /* internal variables */ 52cabdff1aSopenharmony_ci int64_t next_frame_pos; 53cabdff1aSopenharmony_ci int cur_frame; 54cabdff1aSopenharmony_ci int videoindex; 55cabdff1aSopenharmony_ci int indexes[7]; 56cabdff1aSopenharmony_ci int duration_size[7]; 57cabdff1aSopenharmony_ci /* current frame for demuxing */ 58cabdff1aSopenharmony_ci uint32_t frame_size; 59cabdff1aSopenharmony_ci int flags; 60cabdff1aSopenharmony_ci int next_audio_index; 61cabdff1aSopenharmony_ci int new_palette; 62cabdff1aSopenharmony_ci uint8_t pal[768]; 63cabdff1aSopenharmony_ci int64_t aud_pts[7]; 64cabdff1aSopenharmony_ci} SmackerContext; 65cabdff1aSopenharmony_ci 66cabdff1aSopenharmony_ci/* palette used in Smacker */ 67cabdff1aSopenharmony_cistatic const uint8_t smk_pal[64] = { 68cabdff1aSopenharmony_ci 0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C, 69cabdff1aSopenharmony_ci 0x20, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C, 70cabdff1aSopenharmony_ci 0x41, 0x45, 0x49, 0x4D, 0x51, 0x55, 0x59, 0x5D, 71cabdff1aSopenharmony_ci 0x61, 0x65, 0x69, 0x6D, 0x71, 0x75, 0x79, 0x7D, 72cabdff1aSopenharmony_ci 0x82, 0x86, 0x8A, 0x8E, 0x92, 0x96, 0x9A, 0x9E, 73cabdff1aSopenharmony_ci 0xA2, 0xA6, 0xAA, 0xAE, 0xB2, 0xB6, 0xBA, 0xBE, 74cabdff1aSopenharmony_ci 0xC3, 0xC7, 0xCB, 0xCF, 0xD3, 0xD7, 0xDB, 0xDF, 75cabdff1aSopenharmony_ci 0xE3, 0xE7, 0xEB, 0xEF, 0xF3, 0xF7, 0xFB, 0xFF 76cabdff1aSopenharmony_ci}; 77cabdff1aSopenharmony_ci 78cabdff1aSopenharmony_ci 79cabdff1aSopenharmony_cistatic int smacker_probe(const AVProbeData *p) 80cabdff1aSopenharmony_ci{ 81cabdff1aSopenharmony_ci if ( AV_RL32(p->buf) != MKTAG('S', 'M', 'K', '2') 82cabdff1aSopenharmony_ci && AV_RL32(p->buf) != MKTAG('S', 'M', 'K', '4')) 83cabdff1aSopenharmony_ci return 0; 84cabdff1aSopenharmony_ci 85cabdff1aSopenharmony_ci if (AV_RL32(p->buf+4) > 32768U || AV_RL32(p->buf+8) > 32768U) 86cabdff1aSopenharmony_ci return AVPROBE_SCORE_MAX/4; 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci return AVPROBE_SCORE_MAX; 89cabdff1aSopenharmony_ci} 90cabdff1aSopenharmony_ci 91cabdff1aSopenharmony_cistatic int smacker_read_header(AVFormatContext *s) 92cabdff1aSopenharmony_ci{ 93cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 94cabdff1aSopenharmony_ci SmackerContext *smk = s->priv_data; 95cabdff1aSopenharmony_ci AVStream *st; 96cabdff1aSopenharmony_ci AVCodecParameters *par; 97cabdff1aSopenharmony_ci uint32_t magic, width, height, flags, treesize; 98cabdff1aSopenharmony_ci int64_t pos; 99cabdff1aSopenharmony_ci int i, ret, pts_inc; 100cabdff1aSopenharmony_ci int tbase; 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ci /* read and check header */ 103cabdff1aSopenharmony_ci magic = avio_rl32(pb); 104cabdff1aSopenharmony_ci if (magic != MKTAG('S', 'M', 'K', '2') && magic != MKTAG('S', 'M', 'K', '4')) 105cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 106cabdff1aSopenharmony_ci width = avio_rl32(pb); 107cabdff1aSopenharmony_ci height = avio_rl32(pb); 108cabdff1aSopenharmony_ci smk->frames = avio_rl32(pb); 109cabdff1aSopenharmony_ci pts_inc = avio_rl32(pb); 110cabdff1aSopenharmony_ci if (pts_inc > INT_MAX / 100 || pts_inc == INT_MIN) { 111cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "pts_inc %d is invalid\n", pts_inc); 112cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 113cabdff1aSopenharmony_ci } 114cabdff1aSopenharmony_ci 115cabdff1aSopenharmony_ci flags = avio_rl32(pb); 116cabdff1aSopenharmony_ci if (flags & SMACKER_FLAG_RING_FRAME) 117cabdff1aSopenharmony_ci smk->frames++; 118cabdff1aSopenharmony_ci if (smk->frames > 0xFFFFFF) { 119cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Too many frames: %"PRIu32"\n", smk->frames); 120cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 121cabdff1aSopenharmony_ci } 122cabdff1aSopenharmony_ci 123cabdff1aSopenharmony_ci avio_skip(pb, 28); /* Unused audio related data */ 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ci treesize = avio_rl32(pb); 126cabdff1aSopenharmony_ci if (treesize >= UINT_MAX/4) { 127cabdff1aSopenharmony_ci // treesize + 16 must not overflow (this check is probably redundant) 128cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "treesize too large\n"); 129cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 130cabdff1aSopenharmony_ci } 131cabdff1aSopenharmony_ci 132cabdff1aSopenharmony_ci st = avformat_new_stream(s, NULL); 133cabdff1aSopenharmony_ci if (!st) 134cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 135cabdff1aSopenharmony_ci 136cabdff1aSopenharmony_ci smk->videoindex = st->index; 137cabdff1aSopenharmony_ci /* Smacker uses 100000 as internal timebase */ 138cabdff1aSopenharmony_ci if (pts_inc < 0) 139cabdff1aSopenharmony_ci pts_inc = -pts_inc; 140cabdff1aSopenharmony_ci else 141cabdff1aSopenharmony_ci pts_inc *= 100; 142cabdff1aSopenharmony_ci tbase = 100000; 143cabdff1aSopenharmony_ci av_reduce(&tbase, &pts_inc, tbase, pts_inc, (1UL << 31) - 1); 144cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 33, pts_inc, tbase); 145cabdff1aSopenharmony_ci st->duration = smk->frames; 146cabdff1aSopenharmony_ci 147cabdff1aSopenharmony_ci /* init video codec */ 148cabdff1aSopenharmony_ci par = st->codecpar; 149cabdff1aSopenharmony_ci par->width = width; 150cabdff1aSopenharmony_ci par->height = height; 151cabdff1aSopenharmony_ci par->format = AV_PIX_FMT_PAL8; 152cabdff1aSopenharmony_ci par->codec_type = AVMEDIA_TYPE_VIDEO; 153cabdff1aSopenharmony_ci par->codec_id = AV_CODEC_ID_SMACKVIDEO; 154cabdff1aSopenharmony_ci par->codec_tag = magic; 155cabdff1aSopenharmony_ci 156cabdff1aSopenharmony_ci if ((ret = ff_alloc_extradata(par, treesize + 16)) < 0) { 157cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, 158cabdff1aSopenharmony_ci "Cannot allocate %"PRIu32" bytes of extradata\n", 159cabdff1aSopenharmony_ci treesize + 16); 160cabdff1aSopenharmony_ci return ret; 161cabdff1aSopenharmony_ci } 162cabdff1aSopenharmony_ci if ((ret = ffio_read_size(pb, par->extradata, 16)) < 0) 163cabdff1aSopenharmony_ci return ret; 164cabdff1aSopenharmony_ci 165cabdff1aSopenharmony_ci /* handle possible audio streams */ 166cabdff1aSopenharmony_ci for (i = 0; i < 7; i++) { 167cabdff1aSopenharmony_ci uint32_t rate = avio_rl24(pb); 168cabdff1aSopenharmony_ci uint8_t aflag = avio_r8(pb); 169cabdff1aSopenharmony_ci 170cabdff1aSopenharmony_ci smk->indexes[i] = -1; 171cabdff1aSopenharmony_ci 172cabdff1aSopenharmony_ci if (rate) { 173cabdff1aSopenharmony_ci AVStream *ast = avformat_new_stream(s, NULL); 174cabdff1aSopenharmony_ci AVCodecParameters *par; 175cabdff1aSopenharmony_ci if (!ast) 176cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 177cabdff1aSopenharmony_ci 178cabdff1aSopenharmony_ci smk->indexes[i] = ast->index; 179cabdff1aSopenharmony_ci par = ast->codecpar; 180cabdff1aSopenharmony_ci par->codec_type = AVMEDIA_TYPE_AUDIO; 181cabdff1aSopenharmony_ci if (aflag & SMK_AUD_BINKAUD) { 182cabdff1aSopenharmony_ci par->codec_id = AV_CODEC_ID_BINKAUDIO_RDFT; 183cabdff1aSopenharmony_ci } else if (aflag & SMK_AUD_USEDCT) { 184cabdff1aSopenharmony_ci par->codec_id = AV_CODEC_ID_BINKAUDIO_DCT; 185cabdff1aSopenharmony_ci } else if (aflag & SMK_AUD_PACKED) { 186cabdff1aSopenharmony_ci par->codec_id = AV_CODEC_ID_SMACKAUDIO; 187cabdff1aSopenharmony_ci par->codec_tag = MKTAG('S', 'M', 'K', 'A'); 188cabdff1aSopenharmony_ci } else { 189cabdff1aSopenharmony_ci par->codec_id = AV_CODEC_ID_PCM_U8; 190cabdff1aSopenharmony_ci } 191cabdff1aSopenharmony_ci av_channel_layout_default(&par->ch_layout, 192cabdff1aSopenharmony_ci !!(aflag & SMK_AUD_STEREO) + 1); 193cabdff1aSopenharmony_ci par->sample_rate = rate; 194cabdff1aSopenharmony_ci par->bits_per_coded_sample = (aflag & SMK_AUD_16BITS) ? 16 : 8; 195cabdff1aSopenharmony_ci if (par->bits_per_coded_sample == 16 && 196cabdff1aSopenharmony_ci par->codec_id == AV_CODEC_ID_PCM_U8) 197cabdff1aSopenharmony_ci par->codec_id = AV_CODEC_ID_PCM_S16LE; 198cabdff1aSopenharmony_ci else 199cabdff1aSopenharmony_ci smk->duration_size[i] = 4; 200cabdff1aSopenharmony_ci avpriv_set_pts_info(ast, 64, 1, par->sample_rate * par->ch_layout.nb_channels 201cabdff1aSopenharmony_ci * par->bits_per_coded_sample / 8); 202cabdff1aSopenharmony_ci } 203cabdff1aSopenharmony_ci } 204cabdff1aSopenharmony_ci 205cabdff1aSopenharmony_ci avio_rl32(pb); /* padding */ 206cabdff1aSopenharmony_ci 207cabdff1aSopenharmony_ci /* setup data */ 208cabdff1aSopenharmony_ci st->priv_data = av_malloc_array(smk->frames, sizeof(*smk->frm_size) + 209cabdff1aSopenharmony_ci sizeof(*smk->frm_flags)); 210cabdff1aSopenharmony_ci if (!st->priv_data) 211cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 212cabdff1aSopenharmony_ci smk->frm_size = st->priv_data; 213cabdff1aSopenharmony_ci smk->frm_flags = (void*)(smk->frm_size + smk->frames); 214cabdff1aSopenharmony_ci 215cabdff1aSopenharmony_ci /* read frame info */ 216cabdff1aSopenharmony_ci pos = 0; 217cabdff1aSopenharmony_ci for (i = 0; i < smk->frames; i++) { 218cabdff1aSopenharmony_ci smk->frm_size[i] = avio_rl32(pb); 219cabdff1aSopenharmony_ci if ((ret = av_add_index_entry(st, pos, i, smk->frm_size[i], 0, 220cabdff1aSopenharmony_ci (i == 0 || (smk->frm_size[i] & 1)) ? AVINDEX_KEYFRAME : 0)) < 0) 221cabdff1aSopenharmony_ci return ret; 222cabdff1aSopenharmony_ci pos += smk->frm_size[i]; 223cabdff1aSopenharmony_ci } 224cabdff1aSopenharmony_ci if ((ret = ffio_read_size(pb, smk->frm_flags, smk->frames)) < 0 || 225cabdff1aSopenharmony_ci /* load trees to extradata, they will be unpacked by decoder */ 226cabdff1aSopenharmony_ci (ret = ffio_read_size(pb, par->extradata + 16, 227cabdff1aSopenharmony_ci par->extradata_size - 16)) < 0) { 228cabdff1aSopenharmony_ci return ret; 229cabdff1aSopenharmony_ci } 230cabdff1aSopenharmony_ci 231cabdff1aSopenharmony_ci return 0; 232cabdff1aSopenharmony_ci} 233cabdff1aSopenharmony_ci 234cabdff1aSopenharmony_cistatic int smacker_read_packet(AVFormatContext *s, AVPacket *pkt) 235cabdff1aSopenharmony_ci{ 236cabdff1aSopenharmony_ci SmackerContext *smk = s->priv_data; 237cabdff1aSopenharmony_ci int flags; 238cabdff1aSopenharmony_ci int ret; 239cabdff1aSopenharmony_ci 240cabdff1aSopenharmony_ci if (avio_feof(s->pb) || smk->cur_frame >= smk->frames) 241cabdff1aSopenharmony_ci return AVERROR_EOF; 242cabdff1aSopenharmony_ci 243cabdff1aSopenharmony_ci /* if we demuxed all streams, pass another frame */ 244cabdff1aSopenharmony_ci if (!smk->next_audio_index) { 245cabdff1aSopenharmony_ci smk->frame_size = smk->frm_size[smk->cur_frame] & (~3); 246cabdff1aSopenharmony_ci smk->next_frame_pos = avio_tell(s->pb) + smk->frame_size; 247cabdff1aSopenharmony_ci flags = smk->frm_flags[smk->cur_frame]; 248cabdff1aSopenharmony_ci smk->flags = flags >> 1; 249cabdff1aSopenharmony_ci /* handle palette change event */ 250cabdff1aSopenharmony_ci if (flags & SMACKER_PAL) { 251cabdff1aSopenharmony_ci int size, sz, t, off, j, pos; 252cabdff1aSopenharmony_ci uint8_t *pal = smk->pal; 253cabdff1aSopenharmony_ci uint8_t oldpal[768]; 254cabdff1aSopenharmony_ci 255cabdff1aSopenharmony_ci memcpy(oldpal, pal, 768); 256cabdff1aSopenharmony_ci size = avio_r8(s->pb); 257cabdff1aSopenharmony_ci size = size * 4; 258cabdff1aSopenharmony_ci if (size > smk->frame_size) { 259cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 260cabdff1aSopenharmony_ci goto next_frame; 261cabdff1aSopenharmony_ci } 262cabdff1aSopenharmony_ci smk->frame_size -= size--; 263cabdff1aSopenharmony_ci sz = 0; 264cabdff1aSopenharmony_ci pos = avio_tell(s->pb) + size; 265cabdff1aSopenharmony_ci while (sz < 256) { 266cabdff1aSopenharmony_ci t = avio_r8(s->pb); 267cabdff1aSopenharmony_ci if (t & 0x80) { /* skip palette entries */ 268cabdff1aSopenharmony_ci sz += (t & 0x7F) + 1; 269cabdff1aSopenharmony_ci pal += ((t & 0x7F) + 1) * 3; 270cabdff1aSopenharmony_ci } else if (t & 0x40) { /* copy with offset */ 271cabdff1aSopenharmony_ci off = avio_r8(s->pb); 272cabdff1aSopenharmony_ci j = (t & 0x3F) + 1; 273cabdff1aSopenharmony_ci if (off + j > 0x100) { 274cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, 275cabdff1aSopenharmony_ci "Invalid palette update, offset=%d length=%d extends beyond palette size\n", 276cabdff1aSopenharmony_ci off, j); 277cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 278cabdff1aSopenharmony_ci goto next_frame; 279cabdff1aSopenharmony_ci } 280cabdff1aSopenharmony_ci off *= 3; 281cabdff1aSopenharmony_ci while (j-- && sz < 256) { 282cabdff1aSopenharmony_ci *pal++ = oldpal[off + 0]; 283cabdff1aSopenharmony_ci *pal++ = oldpal[off + 1]; 284cabdff1aSopenharmony_ci *pal++ = oldpal[off + 2]; 285cabdff1aSopenharmony_ci sz++; 286cabdff1aSopenharmony_ci off += 3; 287cabdff1aSopenharmony_ci } 288cabdff1aSopenharmony_ci } else { /* new entries */ 289cabdff1aSopenharmony_ci *pal++ = smk_pal[t]; 290cabdff1aSopenharmony_ci *pal++ = smk_pal[avio_r8(s->pb) & 0x3F]; 291cabdff1aSopenharmony_ci *pal++ = smk_pal[avio_r8(s->pb) & 0x3F]; 292cabdff1aSopenharmony_ci sz++; 293cabdff1aSopenharmony_ci } 294cabdff1aSopenharmony_ci } 295cabdff1aSopenharmony_ci avio_seek(s->pb, pos, 0); 296cabdff1aSopenharmony_ci smk->new_palette = 1; 297cabdff1aSopenharmony_ci } 298cabdff1aSopenharmony_ci } 299cabdff1aSopenharmony_ci 300cabdff1aSopenharmony_ci for (int i = smk->next_audio_index; i < 7; i++) { 301cabdff1aSopenharmony_ci if (smk->flags & (1 << i)) { 302cabdff1aSopenharmony_ci uint32_t size; 303cabdff1aSopenharmony_ci 304cabdff1aSopenharmony_ci size = avio_rl32(s->pb); 305cabdff1aSopenharmony_ci if ((int)size < 4 + smk->duration_size[i] || size > smk->frame_size) { 306cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Invalid audio part size\n"); 307cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 308cabdff1aSopenharmony_ci goto next_frame; 309cabdff1aSopenharmony_ci } 310cabdff1aSopenharmony_ci smk->frame_size -= size; 311cabdff1aSopenharmony_ci size -= 4; 312cabdff1aSopenharmony_ci 313cabdff1aSopenharmony_ci if (smk->indexes[i] < 0 || 314cabdff1aSopenharmony_ci s->streams[smk->indexes[i]]->discard >= AVDISCARD_ALL) { 315cabdff1aSopenharmony_ci smk->aud_pts[i] += smk->duration_size[i] ? avio_rl32(s->pb) 316cabdff1aSopenharmony_ci : size; 317cabdff1aSopenharmony_ci avio_skip(s->pb, size - smk->duration_size[i]); 318cabdff1aSopenharmony_ci continue; 319cabdff1aSopenharmony_ci } 320cabdff1aSopenharmony_ci if ((ret = av_get_packet(s->pb, pkt, size)) != size) { 321cabdff1aSopenharmony_ci ret = ret < 0 ? ret : AVERROR_INVALIDDATA; 322cabdff1aSopenharmony_ci goto next_frame; 323cabdff1aSopenharmony_ci } 324cabdff1aSopenharmony_ci pkt->stream_index = smk->indexes[i]; 325cabdff1aSopenharmony_ci pkt->pts = smk->aud_pts[i]; 326cabdff1aSopenharmony_ci pkt->duration = smk->duration_size[i] ? AV_RL32(pkt->data) 327cabdff1aSopenharmony_ci : size; 328cabdff1aSopenharmony_ci smk->aud_pts[i] += pkt->duration; 329cabdff1aSopenharmony_ci smk->next_audio_index = i + 1; 330cabdff1aSopenharmony_ci return 0; 331cabdff1aSopenharmony_ci } 332cabdff1aSopenharmony_ci } 333cabdff1aSopenharmony_ci 334cabdff1aSopenharmony_ci if (s->streams[smk->videoindex]->discard >= AVDISCARD_ALL) { 335cabdff1aSopenharmony_ci ret = FFERROR_REDO; 336cabdff1aSopenharmony_ci goto next_frame; 337cabdff1aSopenharmony_ci } 338cabdff1aSopenharmony_ci if (smk->frame_size >= INT_MAX/2) { 339cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 340cabdff1aSopenharmony_ci goto next_frame; 341cabdff1aSopenharmony_ci } 342cabdff1aSopenharmony_ci if ((ret = av_new_packet(pkt, smk->frame_size + 769)) < 0) 343cabdff1aSopenharmony_ci goto next_frame; 344cabdff1aSopenharmony_ci flags = smk->new_palette; 345cabdff1aSopenharmony_ci if ((smk->frm_size[smk->cur_frame] & 1) || smk->cur_frame == 0) 346cabdff1aSopenharmony_ci flags |= 2; 347cabdff1aSopenharmony_ci pkt->data[0] = flags; 348cabdff1aSopenharmony_ci memcpy(pkt->data + 1, smk->pal, 768); 349cabdff1aSopenharmony_ci ret = ffio_read_size(s->pb, pkt->data + 769, smk->frame_size); 350cabdff1aSopenharmony_ci if (ret < 0) 351cabdff1aSopenharmony_ci goto next_frame; 352cabdff1aSopenharmony_ci pkt->stream_index = smk->videoindex; 353cabdff1aSopenharmony_ci pkt->pts = smk->cur_frame; 354cabdff1aSopenharmony_ci pkt->duration = 1; 355cabdff1aSopenharmony_ci if (flags & 2) 356cabdff1aSopenharmony_ci pkt->flags |= AV_PKT_FLAG_KEY; 357cabdff1aSopenharmony_ci smk->next_audio_index = 0; 358cabdff1aSopenharmony_ci smk->new_palette = 0; 359cabdff1aSopenharmony_ci smk->cur_frame++; 360cabdff1aSopenharmony_ci 361cabdff1aSopenharmony_ci return 0; 362cabdff1aSopenharmony_cinext_frame: 363cabdff1aSopenharmony_ci avio_seek(s->pb, smk->next_frame_pos, SEEK_SET); 364cabdff1aSopenharmony_ci smk->next_audio_index = 0; 365cabdff1aSopenharmony_ci smk->cur_frame++; 366cabdff1aSopenharmony_ci return ret; 367cabdff1aSopenharmony_ci} 368cabdff1aSopenharmony_ci 369cabdff1aSopenharmony_cistatic int smacker_read_seek(AVFormatContext *s, int stream_index, 370cabdff1aSopenharmony_ci int64_t timestamp, int flags) 371cabdff1aSopenharmony_ci{ 372cabdff1aSopenharmony_ci AVStream *st = s->streams[stream_index]; 373cabdff1aSopenharmony_ci SmackerContext *smk = s->priv_data; 374cabdff1aSopenharmony_ci int64_t pos; 375cabdff1aSopenharmony_ci int ret; 376cabdff1aSopenharmony_ci 377cabdff1aSopenharmony_ci if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) 378cabdff1aSopenharmony_ci return -1; 379cabdff1aSopenharmony_ci 380cabdff1aSopenharmony_ci if (timestamp < 0 || timestamp >= smk->frames) 381cabdff1aSopenharmony_ci return AVERROR(EINVAL); 382cabdff1aSopenharmony_ci 383cabdff1aSopenharmony_ci ret = av_index_search_timestamp(st, timestamp, flags); 384cabdff1aSopenharmony_ci if (ret < 0) 385cabdff1aSopenharmony_ci return ret; 386cabdff1aSopenharmony_ci 387cabdff1aSopenharmony_ci pos = ffformatcontext(s)->data_offset; 388cabdff1aSopenharmony_ci pos += ffstream(st)->index_entries[ret].pos; 389cabdff1aSopenharmony_ci pos = avio_seek(s->pb, pos, SEEK_SET); 390cabdff1aSopenharmony_ci if (pos < 0) 391cabdff1aSopenharmony_ci return pos; 392cabdff1aSopenharmony_ci 393cabdff1aSopenharmony_ci smk->cur_frame = ret; 394cabdff1aSopenharmony_ci smk->next_audio_index = 0; 395cabdff1aSopenharmony_ci smk->new_palette = 0; 396cabdff1aSopenharmony_ci memset(smk->pal, 0, sizeof(smk->pal)); 397cabdff1aSopenharmony_ci memset(smk->aud_pts, 0, sizeof(smk->aud_pts)); 398cabdff1aSopenharmony_ci 399cabdff1aSopenharmony_ci return 0; 400cabdff1aSopenharmony_ci} 401cabdff1aSopenharmony_ci 402cabdff1aSopenharmony_ciconst AVInputFormat ff_smacker_demuxer = { 403cabdff1aSopenharmony_ci .name = "smk", 404cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("Smacker"), 405cabdff1aSopenharmony_ci .priv_data_size = sizeof(SmackerContext), 406cabdff1aSopenharmony_ci .read_probe = smacker_probe, 407cabdff1aSopenharmony_ci .read_header = smacker_read_header, 408cabdff1aSopenharmony_ci .read_packet = smacker_read_packet, 409cabdff1aSopenharmony_ci .read_seek = smacker_read_seek, 410cabdff1aSopenharmony_ci}; 411