1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Delphine Software International CIN File Demuxer 3cabdff1aSopenharmony_ci * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net) 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 * @file 24cabdff1aSopenharmony_ci * Delphine Software International CIN file demuxer 25cabdff1aSopenharmony_ci */ 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci#include "libavutil/channel_layout.h" 28cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 29cabdff1aSopenharmony_ci#include "avformat.h" 30cabdff1aSopenharmony_ci#include "internal.h" 31cabdff1aSopenharmony_ci#include "avio_internal.h" 32cabdff1aSopenharmony_ci 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_citypedef struct CinFileHeader { 35cabdff1aSopenharmony_ci int video_frame_size; 36cabdff1aSopenharmony_ci int video_frame_width; 37cabdff1aSopenharmony_ci int video_frame_height; 38cabdff1aSopenharmony_ci int audio_frequency; 39cabdff1aSopenharmony_ci int audio_bits; 40cabdff1aSopenharmony_ci int audio_stereo; 41cabdff1aSopenharmony_ci int audio_frame_size; 42cabdff1aSopenharmony_ci} CinFileHeader; 43cabdff1aSopenharmony_ci 44cabdff1aSopenharmony_citypedef struct CinFrameHeader { 45cabdff1aSopenharmony_ci int audio_frame_type; 46cabdff1aSopenharmony_ci int video_frame_type; 47cabdff1aSopenharmony_ci int pal_colors_count; 48cabdff1aSopenharmony_ci int audio_frame_size; 49cabdff1aSopenharmony_ci int video_frame_size; 50cabdff1aSopenharmony_ci} CinFrameHeader; 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_citypedef struct CinDemuxContext { 53cabdff1aSopenharmony_ci int audio_stream_index; 54cabdff1aSopenharmony_ci int video_stream_index; 55cabdff1aSopenharmony_ci CinFileHeader file_header; 56cabdff1aSopenharmony_ci int64_t audio_stream_pts; 57cabdff1aSopenharmony_ci int64_t video_stream_pts; 58cabdff1aSopenharmony_ci CinFrameHeader frame_header; 59cabdff1aSopenharmony_ci int audio_buffer_size; 60cabdff1aSopenharmony_ci} CinDemuxContext; 61cabdff1aSopenharmony_ci 62cabdff1aSopenharmony_ci 63cabdff1aSopenharmony_cistatic int cin_probe(const AVProbeData *p) 64cabdff1aSopenharmony_ci{ 65cabdff1aSopenharmony_ci /* header starts with this special marker */ 66cabdff1aSopenharmony_ci if (AV_RL32(&p->buf[0]) != 0x55AA0000) 67cabdff1aSopenharmony_ci return 0; 68cabdff1aSopenharmony_ci 69cabdff1aSopenharmony_ci /* for accuracy, check some header field values */ 70cabdff1aSopenharmony_ci if (AV_RL32(&p->buf[12]) != 22050 || p->buf[16] != 16 || p->buf[17] != 0) 71cabdff1aSopenharmony_ci return 0; 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ci return AVPROBE_SCORE_MAX; 74cabdff1aSopenharmony_ci} 75cabdff1aSopenharmony_ci 76cabdff1aSopenharmony_cistatic int cin_read_file_header(CinDemuxContext *cin, AVIOContext *pb) { 77cabdff1aSopenharmony_ci CinFileHeader *hdr = &cin->file_header; 78cabdff1aSopenharmony_ci 79cabdff1aSopenharmony_ci if (avio_rl32(pb) != 0x55AA0000) 80cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_ci hdr->video_frame_size = avio_rl32(pb); 83cabdff1aSopenharmony_ci hdr->video_frame_width = avio_rl16(pb); 84cabdff1aSopenharmony_ci hdr->video_frame_height = avio_rl16(pb); 85cabdff1aSopenharmony_ci hdr->audio_frequency = avio_rl32(pb); 86cabdff1aSopenharmony_ci hdr->audio_bits = avio_r8(pb); 87cabdff1aSopenharmony_ci hdr->audio_stereo = avio_r8(pb); 88cabdff1aSopenharmony_ci hdr->audio_frame_size = avio_rl16(pb); 89cabdff1aSopenharmony_ci 90cabdff1aSopenharmony_ci if (hdr->audio_frequency != 22050 || hdr->audio_bits != 16 || hdr->audio_stereo != 0) 91cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 92cabdff1aSopenharmony_ci 93cabdff1aSopenharmony_ci return 0; 94cabdff1aSopenharmony_ci} 95cabdff1aSopenharmony_ci 96cabdff1aSopenharmony_cistatic int cin_read_header(AVFormatContext *s) 97cabdff1aSopenharmony_ci{ 98cabdff1aSopenharmony_ci int rc; 99cabdff1aSopenharmony_ci CinDemuxContext *cin = s->priv_data; 100cabdff1aSopenharmony_ci CinFileHeader *hdr = &cin->file_header; 101cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 102cabdff1aSopenharmony_ci AVStream *st; 103cabdff1aSopenharmony_ci 104cabdff1aSopenharmony_ci rc = cin_read_file_header(cin, pb); 105cabdff1aSopenharmony_ci if (rc) 106cabdff1aSopenharmony_ci return rc; 107cabdff1aSopenharmony_ci 108cabdff1aSopenharmony_ci cin->video_stream_pts = 0; 109cabdff1aSopenharmony_ci cin->audio_stream_pts = 0; 110cabdff1aSopenharmony_ci cin->audio_buffer_size = 0; 111cabdff1aSopenharmony_ci 112cabdff1aSopenharmony_ci /* initialize the video decoder stream */ 113cabdff1aSopenharmony_ci st = avformat_new_stream(s, NULL); 114cabdff1aSopenharmony_ci if (!st) 115cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 116cabdff1aSopenharmony_ci 117cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 32, 1, 12); 118cabdff1aSopenharmony_ci cin->video_stream_index = st->index; 119cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; 120cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_DSICINVIDEO; 121cabdff1aSopenharmony_ci st->codecpar->codec_tag = 0; /* no fourcc */ 122cabdff1aSopenharmony_ci st->codecpar->width = hdr->video_frame_width; 123cabdff1aSopenharmony_ci st->codecpar->height = hdr->video_frame_height; 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ci /* initialize the audio decoder stream */ 126cabdff1aSopenharmony_ci st = avformat_new_stream(s, NULL); 127cabdff1aSopenharmony_ci if (!st) 128cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 129cabdff1aSopenharmony_ci 130cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 32, 1, 22050); 131cabdff1aSopenharmony_ci cin->audio_stream_index = st->index; 132cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; 133cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_DSICINAUDIO; 134cabdff1aSopenharmony_ci st->codecpar->codec_tag = 0; /* no tag */ 135cabdff1aSopenharmony_ci st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; 136cabdff1aSopenharmony_ci st->codecpar->sample_rate = 22050; 137cabdff1aSopenharmony_ci st->codecpar->bits_per_coded_sample = 8; 138cabdff1aSopenharmony_ci st->codecpar->bit_rate = st->codecpar->sample_rate * 139cabdff1aSopenharmony_ci st->codecpar->bits_per_coded_sample * 140cabdff1aSopenharmony_ci st->codecpar->ch_layout.nb_channels; 141cabdff1aSopenharmony_ci 142cabdff1aSopenharmony_ci return 0; 143cabdff1aSopenharmony_ci} 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_cistatic int cin_read_frame_header(CinDemuxContext *cin, AVIOContext *pb) { 146cabdff1aSopenharmony_ci CinFrameHeader *hdr = &cin->frame_header; 147cabdff1aSopenharmony_ci 148cabdff1aSopenharmony_ci hdr->video_frame_type = avio_r8(pb); 149cabdff1aSopenharmony_ci hdr->audio_frame_type = avio_r8(pb); 150cabdff1aSopenharmony_ci hdr->pal_colors_count = avio_rl16(pb); 151cabdff1aSopenharmony_ci hdr->video_frame_size = avio_rl32(pb); 152cabdff1aSopenharmony_ci hdr->audio_frame_size = avio_rl32(pb); 153cabdff1aSopenharmony_ci 154cabdff1aSopenharmony_ci if (avio_feof(pb) || pb->error) 155cabdff1aSopenharmony_ci return AVERROR(EIO); 156cabdff1aSopenharmony_ci 157cabdff1aSopenharmony_ci if (avio_rl32(pb) != 0xAA55AA55) 158cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 159cabdff1aSopenharmony_ci if (hdr->video_frame_size < 0 || hdr->audio_frame_size < 0) 160cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 161cabdff1aSopenharmony_ci 162cabdff1aSopenharmony_ci return 0; 163cabdff1aSopenharmony_ci} 164cabdff1aSopenharmony_ci 165cabdff1aSopenharmony_cistatic int cin_read_packet(AVFormatContext *s, AVPacket *pkt) 166cabdff1aSopenharmony_ci{ 167cabdff1aSopenharmony_ci CinDemuxContext *cin = s->priv_data; 168cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 169cabdff1aSopenharmony_ci CinFrameHeader *hdr = &cin->frame_header; 170cabdff1aSopenharmony_ci int rc, palette_type; 171cabdff1aSopenharmony_ci int64_t pkt_size; 172cabdff1aSopenharmony_ci int ret; 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_ci if (cin->audio_buffer_size == 0) { 175cabdff1aSopenharmony_ci rc = cin_read_frame_header(cin, pb); 176cabdff1aSopenharmony_ci if (rc) 177cabdff1aSopenharmony_ci return rc; 178cabdff1aSopenharmony_ci 179cabdff1aSopenharmony_ci if ((int16_t)hdr->pal_colors_count < 0) { 180cabdff1aSopenharmony_ci hdr->pal_colors_count = -(int16_t)hdr->pal_colors_count; 181cabdff1aSopenharmony_ci palette_type = 1; 182cabdff1aSopenharmony_ci } else { 183cabdff1aSopenharmony_ci palette_type = 0; 184cabdff1aSopenharmony_ci } 185cabdff1aSopenharmony_ci 186cabdff1aSopenharmony_ci /* palette and video packet */ 187cabdff1aSopenharmony_ci pkt_size = (palette_type + 3LL) * hdr->pal_colors_count + hdr->video_frame_size; 188cabdff1aSopenharmony_ci if (pkt_size + 4 > INT_MAX) 189cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 190cabdff1aSopenharmony_ci 191cabdff1aSopenharmony_ci pkt_size = ffio_limit(pb, pkt_size); 192cabdff1aSopenharmony_ci 193cabdff1aSopenharmony_ci ret = av_new_packet(pkt, 4 + pkt_size); 194cabdff1aSopenharmony_ci if (ret < 0) 195cabdff1aSopenharmony_ci return ret; 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_ci pkt->stream_index = cin->video_stream_index; 198cabdff1aSopenharmony_ci pkt->pts = cin->video_stream_pts++; 199cabdff1aSopenharmony_ci 200cabdff1aSopenharmony_ci pkt->data[0] = palette_type; 201cabdff1aSopenharmony_ci pkt->data[1] = hdr->pal_colors_count & 0xFF; 202cabdff1aSopenharmony_ci pkt->data[2] = hdr->pal_colors_count >> 8; 203cabdff1aSopenharmony_ci pkt->data[3] = hdr->video_frame_type; 204cabdff1aSopenharmony_ci 205cabdff1aSopenharmony_ci ret = avio_read(pb, &pkt->data[4], pkt_size); 206cabdff1aSopenharmony_ci if (ret < 0) { 207cabdff1aSopenharmony_ci return ret; 208cabdff1aSopenharmony_ci } 209cabdff1aSopenharmony_ci if (ret < pkt_size) 210cabdff1aSopenharmony_ci av_shrink_packet(pkt, 4 + ret); 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_ci /* sound buffer will be processed on next read_packet() call */ 213cabdff1aSopenharmony_ci cin->audio_buffer_size = hdr->audio_frame_size; 214cabdff1aSopenharmony_ci return 0; 215cabdff1aSopenharmony_ci } 216cabdff1aSopenharmony_ci 217cabdff1aSopenharmony_ci /* audio packet */ 218cabdff1aSopenharmony_ci ret = av_get_packet(pb, pkt, cin->audio_buffer_size); 219cabdff1aSopenharmony_ci if (ret < 0) 220cabdff1aSopenharmony_ci return ret; 221cabdff1aSopenharmony_ci 222cabdff1aSopenharmony_ci pkt->stream_index = cin->audio_stream_index; 223cabdff1aSopenharmony_ci pkt->pts = cin->audio_stream_pts; 224cabdff1aSopenharmony_ci pkt->duration = cin->audio_buffer_size - (pkt->pts == 0); 225cabdff1aSopenharmony_ci cin->audio_stream_pts += pkt->duration; 226cabdff1aSopenharmony_ci cin->audio_buffer_size = 0; 227cabdff1aSopenharmony_ci return 0; 228cabdff1aSopenharmony_ci} 229cabdff1aSopenharmony_ci 230cabdff1aSopenharmony_ciconst AVInputFormat ff_dsicin_demuxer = { 231cabdff1aSopenharmony_ci .name = "dsicin", 232cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN"), 233cabdff1aSopenharmony_ci .priv_data_size = sizeof(CinDemuxContext), 234cabdff1aSopenharmony_ci .read_probe = cin_probe, 235cabdff1aSopenharmony_ci .read_header = cin_read_header, 236cabdff1aSopenharmony_ci .read_packet = cin_read_packet, 237cabdff1aSopenharmony_ci}; 238