1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * ACE demuxer 3cabdff1aSopenharmony_ci * Copyright (c) 2020 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/intreadwrite.h" 23cabdff1aSopenharmony_ci#include "avformat.h" 24cabdff1aSopenharmony_ci#include "internal.h" 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_cistatic int ace_probe(const AVProbeData *p) 27cabdff1aSopenharmony_ci{ 28cabdff1aSopenharmony_ci uint32_t asc; 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_ci if (AV_RB32(p->buf) != MKBETAG('A','A','C',' ')) 31cabdff1aSopenharmony_ci return 0; 32cabdff1aSopenharmony_ci if (p->buf_size < 0x44) 33cabdff1aSopenharmony_ci return 0; 34cabdff1aSopenharmony_ci asc = AV_RB32(p->buf + 0x40); 35cabdff1aSopenharmony_ci if (asc < 0x44 || asc > p->buf_size - 4) 36cabdff1aSopenharmony_ci return 0; 37cabdff1aSopenharmony_ci if (AV_RB32(p->buf + asc) != MKBETAG('A','S','C',' ')) 38cabdff1aSopenharmony_ci return 0; 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_ci return AVPROBE_SCORE_MAX / 2 + 1; 41cabdff1aSopenharmony_ci} 42cabdff1aSopenharmony_ci 43cabdff1aSopenharmony_cistatic int ace_read_header(AVFormatContext *s) 44cabdff1aSopenharmony_ci{ 45cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 46cabdff1aSopenharmony_ci AVCodecParameters *par; 47cabdff1aSopenharmony_ci int ret, codec, rate, nb_channels; 48cabdff1aSopenharmony_ci uint32_t asc_pos, size; 49cabdff1aSopenharmony_ci AVStream *st; 50cabdff1aSopenharmony_ci 51cabdff1aSopenharmony_ci avio_skip(pb, 0x40); 52cabdff1aSopenharmony_ci asc_pos = avio_rb32(pb); 53cabdff1aSopenharmony_ci if (asc_pos < 0x44) 54cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 55cabdff1aSopenharmony_ci avio_skip(pb, asc_pos - 0x44); 56cabdff1aSopenharmony_ci if (avio_rb32(pb) != MKBETAG('A','S','C',' ')) 57cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 58cabdff1aSopenharmony_ci avio_skip(pb, 0xec); 59cabdff1aSopenharmony_ci codec = avio_rb32(pb); 60cabdff1aSopenharmony_ci nb_channels = avio_rb32(pb); 61cabdff1aSopenharmony_ci if (nb_channels <= 0 || nb_channels > 8) 62cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 63cabdff1aSopenharmony_ci size = avio_rb32(pb); 64cabdff1aSopenharmony_ci if (size == 0) 65cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 66cabdff1aSopenharmony_ci rate = avio_rb32(pb); 67cabdff1aSopenharmony_ci if (rate <= 0) 68cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 69cabdff1aSopenharmony_ci avio_skip(pb, 16); 70cabdff1aSopenharmony_ci 71cabdff1aSopenharmony_ci st = avformat_new_stream(s, NULL); 72cabdff1aSopenharmony_ci if (!st) 73cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 74cabdff1aSopenharmony_ci st->start_time = 0; 75cabdff1aSopenharmony_ci par = st->codecpar; 76cabdff1aSopenharmony_ci par->codec_type = AVMEDIA_TYPE_AUDIO; 77cabdff1aSopenharmony_ci par->ch_layout.nb_channels = nb_channels; 78cabdff1aSopenharmony_ci par->sample_rate = rate; 79cabdff1aSopenharmony_ci par->block_align = (codec == 4 ? 0x60 : codec == 5 ? 0x98 : 0xC0) * nb_channels; 80cabdff1aSopenharmony_ci st->duration = (size / par->block_align) * 1024LL; 81cabdff1aSopenharmony_ci par->codec_id = AV_CODEC_ID_ATRAC3; 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_ci ret = ff_alloc_extradata(par, 14); 84cabdff1aSopenharmony_ci if (ret < 0) 85cabdff1aSopenharmony_ci return ret; 86cabdff1aSopenharmony_ci 87cabdff1aSopenharmony_ci AV_WL16(st->codecpar->extradata, 1); 88cabdff1aSopenharmony_ci AV_WL16(st->codecpar->extradata+2, 2048 * nb_channels); 89cabdff1aSopenharmony_ci AV_WL16(st->codecpar->extradata+4, 0); 90cabdff1aSopenharmony_ci AV_WL16(st->codecpar->extradata+6, codec == 4 ? 1 : 0); 91cabdff1aSopenharmony_ci AV_WL16(st->codecpar->extradata+8, codec == 4 ? 1 : 0); 92cabdff1aSopenharmony_ci AV_WL16(st->codecpar->extradata+10, 1); 93cabdff1aSopenharmony_ci AV_WL16(st->codecpar->extradata+12, 0); 94cabdff1aSopenharmony_ci 95cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 64, 1, par->sample_rate); 96cabdff1aSopenharmony_ci 97cabdff1aSopenharmony_ci return 0; 98cabdff1aSopenharmony_ci} 99cabdff1aSopenharmony_ci 100cabdff1aSopenharmony_cistatic int ace_read_packet(AVFormatContext *s, AVPacket *pkt) 101cabdff1aSopenharmony_ci{ 102cabdff1aSopenharmony_ci AVCodecParameters *par = s->streams[0]->codecpar; 103cabdff1aSopenharmony_ci 104cabdff1aSopenharmony_ci return av_get_packet(s->pb, pkt, par->block_align); 105cabdff1aSopenharmony_ci} 106cabdff1aSopenharmony_ci 107cabdff1aSopenharmony_ciconst AVInputFormat ff_ace_demuxer = { 108cabdff1aSopenharmony_ci .name = "ace", 109cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("tri-Ace Audio Container"), 110cabdff1aSopenharmony_ci .read_probe = ace_probe, 111cabdff1aSopenharmony_ci .read_header = ace_read_header, 112cabdff1aSopenharmony_ci .read_packet = ace_read_packet, 113cabdff1aSopenharmony_ci .flags = AVFMT_GENERIC_INDEX, 114cabdff1aSopenharmony_ci}; 115