1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * GENH demuxer 3cabdff1aSopenharmony_ci * Copyright (c) 2015 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 "libavutil/intreadwrite.h" 24cabdff1aSopenharmony_ci#include "avformat.h" 25cabdff1aSopenharmony_ci#include "internal.h" 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_citypedef struct GENHDemuxContext { 28cabdff1aSopenharmony_ci unsigned dsp_int_type; 29cabdff1aSopenharmony_ci unsigned interleave_size; 30cabdff1aSopenharmony_ci} GENHDemuxContext; 31cabdff1aSopenharmony_ci 32cabdff1aSopenharmony_cistatic int genh_probe(const AVProbeData *p) 33cabdff1aSopenharmony_ci{ 34cabdff1aSopenharmony_ci if (AV_RL32(p->buf) != MKTAG('G','E','N','H')) 35cabdff1aSopenharmony_ci return 0; 36cabdff1aSopenharmony_ci if (AV_RL32(p->buf+4) <= 0 || AV_RL32(p->buf+4) > 0xFFFF) // channels 37cabdff1aSopenharmony_ci return 0; 38cabdff1aSopenharmony_ci 39cabdff1aSopenharmony_ci return AVPROBE_SCORE_MAX / 3 * 2; 40cabdff1aSopenharmony_ci} 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_cistatic int genh_read_header(AVFormatContext *s) 43cabdff1aSopenharmony_ci{ 44cabdff1aSopenharmony_ci unsigned start_offset, header_size, codec, coef_type, coef[2]; 45cabdff1aSopenharmony_ci GENHDemuxContext *c = s->priv_data; 46cabdff1aSopenharmony_ci av_unused unsigned coef_splitted[2]; 47cabdff1aSopenharmony_ci int align, ch, ret; 48cabdff1aSopenharmony_ci AVStream *st; 49cabdff1aSopenharmony_ci 50cabdff1aSopenharmony_ci avio_skip(s->pb, 4); 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_ci st = avformat_new_stream(s, NULL); 53cabdff1aSopenharmony_ci if (!st) 54cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 55cabdff1aSopenharmony_ci 56cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; 57cabdff1aSopenharmony_ci st->codecpar->ch_layout.nb_channels = avio_rl32(s->pb); 58cabdff1aSopenharmony_ci if (st->codecpar->ch_layout.nb_channels <= 0) 59cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 60cabdff1aSopenharmony_ci if (st->codecpar->ch_layout.nb_channels == 1) 61cabdff1aSopenharmony_ci st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; 62cabdff1aSopenharmony_ci else if (st->codecpar->ch_layout.nb_channels == 2) 63cabdff1aSopenharmony_ci st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; 64cabdff1aSopenharmony_ci align = 65cabdff1aSopenharmony_ci c->interleave_size = avio_rl32(s->pb); 66cabdff1aSopenharmony_ci if (align < 0 || align > INT_MAX / st->codecpar->ch_layout.nb_channels) 67cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 68cabdff1aSopenharmony_ci st->codecpar->block_align = align * st->codecpar->ch_layout.nb_channels; 69cabdff1aSopenharmony_ci st->codecpar->sample_rate = avio_rl32(s->pb); 70cabdff1aSopenharmony_ci if (st->codecpar->sample_rate < 0) 71cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ci avio_skip(s->pb, 4); 74cabdff1aSopenharmony_ci st->duration = avio_rl32(s->pb); 75cabdff1aSopenharmony_ci 76cabdff1aSopenharmony_ci codec = avio_rl32(s->pb); 77cabdff1aSopenharmony_ci switch (codec) { 78cabdff1aSopenharmony_ci case 0: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_PSX; break; 79cabdff1aSopenharmony_ci case 1: 80cabdff1aSopenharmony_ci case 11: st->codecpar->bits_per_coded_sample = 4; 81cabdff1aSopenharmony_ci if (st->codecpar->ch_layout.nb_channels > INT_MAX / 36) 82cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 83cabdff1aSopenharmony_ci st->codecpar->block_align = 36 * st->codecpar->ch_layout.nb_channels; 84cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_WAV; break; 85cabdff1aSopenharmony_ci case 2: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_DTK; break; 86cabdff1aSopenharmony_ci case 3: st->codecpar->codec_id = st->codecpar->block_align > 0 ? 87cabdff1aSopenharmony_ci AV_CODEC_ID_PCM_S16BE_PLANAR : 88cabdff1aSopenharmony_ci AV_CODEC_ID_PCM_S16BE; break; 89cabdff1aSopenharmony_ci case 4: st->codecpar->codec_id = st->codecpar->block_align > 0 ? 90cabdff1aSopenharmony_ci AV_CODEC_ID_PCM_S16LE_PLANAR : 91cabdff1aSopenharmony_ci AV_CODEC_ID_PCM_S16LE; break; 92cabdff1aSopenharmony_ci case 5: st->codecpar->codec_id = st->codecpar->block_align > 0 ? 93cabdff1aSopenharmony_ci AV_CODEC_ID_PCM_S8_PLANAR : 94cabdff1aSopenharmony_ci AV_CODEC_ID_PCM_S8; break; 95cabdff1aSopenharmony_ci case 6: if (st->codecpar->block_align > INT_MAX/1024) 96cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 97cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_SDX2_DPCM; break; 98cabdff1aSopenharmony_ci case 7: ret = ff_alloc_extradata(st->codecpar, 2); 99cabdff1aSopenharmony_ci if (ret < 0) 100cabdff1aSopenharmony_ci return ret; 101cabdff1aSopenharmony_ci AV_WL16(st->codecpar->extradata, 3); 102cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_WS; break; 103cabdff1aSopenharmony_ci case 10: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_AICA; break; 104cabdff1aSopenharmony_ci case 12: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_THP; break; 105cabdff1aSopenharmony_ci case 13: st->codecpar->codec_id = AV_CODEC_ID_PCM_U8; break; 106cabdff1aSopenharmony_ci case 17: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_QT; break; 107cabdff1aSopenharmony_ci default: 108cabdff1aSopenharmony_ci avpriv_request_sample(s, "codec %d", codec); 109cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 110cabdff1aSopenharmony_ci } 111cabdff1aSopenharmony_ci 112cabdff1aSopenharmony_ci start_offset = avio_rl32(s->pb); 113cabdff1aSopenharmony_ci header_size = avio_rl32(s->pb); 114cabdff1aSopenharmony_ci 115cabdff1aSopenharmony_ci if (header_size > start_offset) 116cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 117cabdff1aSopenharmony_ci 118cabdff1aSopenharmony_ci if (header_size == 0) 119cabdff1aSopenharmony_ci start_offset = 0x800; 120cabdff1aSopenharmony_ci 121cabdff1aSopenharmony_ci coef[0] = avio_rl32(s->pb); 122cabdff1aSopenharmony_ci coef[1] = avio_rl32(s->pb); 123cabdff1aSopenharmony_ci c->dsp_int_type = avio_rl32(s->pb); 124cabdff1aSopenharmony_ci coef_type = avio_rl32(s->pb); 125cabdff1aSopenharmony_ci coef_splitted[0] = avio_rl32(s->pb); 126cabdff1aSopenharmony_ci coef_splitted[1] = avio_rl32(s->pb); 127cabdff1aSopenharmony_ci 128cabdff1aSopenharmony_ci if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_THP) { 129cabdff1aSopenharmony_ci if (st->codecpar->ch_layout.nb_channels > 2) { 130cabdff1aSopenharmony_ci avpriv_request_sample(s, "channels %d>2", st->codecpar->ch_layout.nb_channels); 131cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 132cabdff1aSopenharmony_ci } 133cabdff1aSopenharmony_ci 134cabdff1aSopenharmony_ci ff_alloc_extradata(st->codecpar, 32 * st->codecpar->ch_layout.nb_channels); 135cabdff1aSopenharmony_ci for (ch = 0; ch < st->codecpar->ch_layout.nb_channels; ch++) { 136cabdff1aSopenharmony_ci if (coef_type & 1) { 137cabdff1aSopenharmony_ci avpriv_request_sample(s, "coef_type & 1"); 138cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 139cabdff1aSopenharmony_ci } else { 140cabdff1aSopenharmony_ci avio_seek(s->pb, coef[ch], SEEK_SET); 141cabdff1aSopenharmony_ci avio_read(s->pb, st->codecpar->extradata + 32 * ch, 32); 142cabdff1aSopenharmony_ci } 143cabdff1aSopenharmony_ci } 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_ci if (c->dsp_int_type == 1) { 146cabdff1aSopenharmony_ci st->codecpar->block_align = 8 * st->codecpar->ch_layout.nb_channels; 147cabdff1aSopenharmony_ci if (c->interleave_size != 1 && 148cabdff1aSopenharmony_ci c->interleave_size != 2 && 149cabdff1aSopenharmony_ci c->interleave_size != 4) 150cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 151cabdff1aSopenharmony_ci } 152cabdff1aSopenharmony_ci } 153cabdff1aSopenharmony_ci 154cabdff1aSopenharmony_ci if (st->codecpar->block_align <= 0) 155cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 156cabdff1aSopenharmony_ci 157cabdff1aSopenharmony_ci avio_skip(s->pb, start_offset - avio_tell(s->pb)); 158cabdff1aSopenharmony_ci 159cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); 160cabdff1aSopenharmony_ci 161cabdff1aSopenharmony_ci return 0; 162cabdff1aSopenharmony_ci} 163cabdff1aSopenharmony_ci 164cabdff1aSopenharmony_cistatic int genh_read_packet(AVFormatContext *s, AVPacket *pkt) 165cabdff1aSopenharmony_ci{ 166cabdff1aSopenharmony_ci AVCodecParameters *par = s->streams[0]->codecpar; 167cabdff1aSopenharmony_ci GENHDemuxContext *c = s->priv_data; 168cabdff1aSopenharmony_ci int ret; 169cabdff1aSopenharmony_ci 170cabdff1aSopenharmony_ci if (c->dsp_int_type == 1 && par->codec_id == AV_CODEC_ID_ADPCM_THP && 171cabdff1aSopenharmony_ci par->ch_layout.nb_channels > 1) { 172cabdff1aSopenharmony_ci int i, ch; 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_ci if (avio_feof(s->pb)) 175cabdff1aSopenharmony_ci return AVERROR_EOF; 176cabdff1aSopenharmony_ci ret = av_new_packet(pkt, 8 * par->ch_layout.nb_channels); 177cabdff1aSopenharmony_ci if (ret < 0) 178cabdff1aSopenharmony_ci return ret; 179cabdff1aSopenharmony_ci for (i = 0; i < 8 / c->interleave_size; i++) { 180cabdff1aSopenharmony_ci for (ch = 0; ch < par->ch_layout.nb_channels; ch++) { 181cabdff1aSopenharmony_ci pkt->data[ch * 8 + i*c->interleave_size+0] = avio_r8(s->pb); 182cabdff1aSopenharmony_ci pkt->data[ch * 8 + i*c->interleave_size+1] = avio_r8(s->pb); 183cabdff1aSopenharmony_ci } 184cabdff1aSopenharmony_ci } 185cabdff1aSopenharmony_ci ret = 0; 186cabdff1aSopenharmony_ci } else if (par->codec_id == AV_CODEC_ID_SDX2_DPCM) { 187cabdff1aSopenharmony_ci ret = av_get_packet(s->pb, pkt, par->block_align * 1024); 188cabdff1aSopenharmony_ci 189cabdff1aSopenharmony_ci } else { 190cabdff1aSopenharmony_ci ret = av_get_packet(s->pb, pkt, par->block_align ? par->block_align : 191cabdff1aSopenharmony_ci 1024 * par->ch_layout.nb_channels); 192cabdff1aSopenharmony_ci } 193cabdff1aSopenharmony_ci 194cabdff1aSopenharmony_ci pkt->stream_index = 0; 195cabdff1aSopenharmony_ci return ret; 196cabdff1aSopenharmony_ci} 197cabdff1aSopenharmony_ci 198cabdff1aSopenharmony_ciconst AVInputFormat ff_genh_demuxer = { 199cabdff1aSopenharmony_ci .name = "genh", 200cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("GENeric Header"), 201cabdff1aSopenharmony_ci .priv_data_size = sizeof(GENHDemuxContext), 202cabdff1aSopenharmony_ci .read_probe = genh_probe, 203cabdff1aSopenharmony_ci .read_header = genh_read_header, 204cabdff1aSopenharmony_ci .read_packet = genh_read_packet, 205cabdff1aSopenharmony_ci .extensions = "genh", 206cabdff1aSopenharmony_ci}; 207