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