From patchwork Wed Jan 25 16:20:18 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 2307 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.89.21 with SMTP id n21csp2286420vsb; Wed, 25 Jan 2017 08:28:35 -0800 (PST) X-Received: by 10.223.128.77 with SMTP id 71mr9447933wrk.163.1485361715678; Wed, 25 Jan 2017 08:28:35 -0800 (PST) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id v130si22940405wmd.161.2017.01.25.08.28.34; Wed, 25 Jan 2017 08:28:35 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id D59BA68A26F; Wed, 25 Jan 2017 18:28:31 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wj0-f194.google.com (mail-wj0-f194.google.com [209.85.210.194]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id E6D5368A05B for ; Wed, 25 Jan 2017 18:28:24 +0200 (EET) Received: by mail-wj0-f194.google.com with SMTP id ip10so3652150wjb.1 for ; Wed, 25 Jan 2017 08:28:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id; bh=XHFNKbJvILGznxxoFlkUS4jo/oK4mF9BgkFIW6gefnc=; b=Ssk8fyJDfBaXP0e7rTLyoz5Tu+MlKaAaozaqGW5Rk7EhvoadCY5ObqHOqUSX2bttJK P1rKDOUQqy4CNwqHzO1wSQD3/Ccl9n7Xe9ayBBRUX9hn2eubR/OwdkFfXTj1oqX4qmqL cV3NS8Zr8kkJJ6oJ6v781eHKUZJmNYu93/YLD1vWsw4mTI/BuDacMQ8nswfTbpMcxYPz PDlBdWvH1Q7iWXo5qwL6NFu7ZNVxSvGipCpJB9lDpiyUR/5Z1l2SvNWFqs4dUJqpqDdS RQiJLkBhHkro831PYe2VUD6K58rovj2vsBQvuDAoDPqb/b72s0NFy7JAh/0kMQFsZKca eyUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=XHFNKbJvILGznxxoFlkUS4jo/oK4mF9BgkFIW6gefnc=; b=uFCQ1kPQXBM3YfT1/THTX1Z/QDlo7WAyraPGbqMrfuLPYI80kJFyD9x2sYvCGs26It 7NqCTZjk37jTyA5daEcYD6i1qW801nTpWo5GT+7bNWzB1M9+Kbo0SIdsiEW0lHHFyRjL RWvrrHtT7+ljugA5SOE2uZFL8kLC5nqu5lC3Qmh5vif4NHp9Oc4qAVyF5mTIpBREhqTb VNqiNByk6dmukFg3v3EQSgszRQXiZgFY7WzCvwesnOVWlQby6nM1asOG9Tn58F90w4A4 8vXIDSL7n4AS55vUgD3STYrgYzRMN2CE6dfhAn+/8pYQjQ20Uy/THbJkip6fSFea5Q+Y ybxQ== X-Gm-Message-State: AIkVDXIGVhQ1pIFyMiN9++Yb6lKeSafF3By1C6xw5J6ktNOy2PVFMWTXBTUZMFlh7p8B6A== X-Received: by 10.223.166.181 with SMTP id t50mr34283458wrc.80.1485361232291; Wed, 25 Jan 2017 08:20:32 -0800 (PST) Received: from localhost.localdomain ([31.45.254.175]) by smtp.gmail.com with ESMTPSA id x25sm25743280wrx.27.2017.01.25.08.20.30 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 25 Jan 2017 08:20:31 -0800 (PST) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Wed, 25 Jan 2017 17:20:18 +0100 Message-Id: <20170125162018.1445-1-onemda@gmail.com> X-Mailer: git-send-email 2.9.3 Subject: [FFmpeg-devel] [PATCH] avcodec: add ATRAC Advanced Lossless decoders X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Only lossy part is decoded for now. Signed-off-by: Paul B Mahol --- libavcodec/Makefile | 3 + libavcodec/allcodecs.c | 2 + libavcodec/atrac3.c | 134 ++++++++++++++++++++++++++++++++++- libavcodec/atrac3plusdec.c | 14 +++- libavcodec/avcodec.h | 2 + libavcodec/codec_desc.c | 14 ++++ libavformat/oma.c | 10 +-- libavformat/oma.h | 2 + libavformat/omadec.c | 173 ++++++++++++++++++++++++++++++++++++--------- 9 files changed, 313 insertions(+), 41 deletions(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 43a6add..c5505db 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -191,8 +191,11 @@ OBJS-$(CONFIG_ASV2_DECODER) += asvdec.o asv.o mpeg12data.o OBJS-$(CONFIG_ASV2_ENCODER) += asvenc.o asv.o mpeg12data.o OBJS-$(CONFIG_ATRAC1_DECODER) += atrac1.o atrac.o OBJS-$(CONFIG_ATRAC3_DECODER) += atrac3.o atrac.o +OBJS-$(CONFIG_ATRAC3AL_DECODER) += atrac3.o atrac.o OBJS-$(CONFIG_ATRAC3P_DECODER) += atrac3plusdec.o atrac3plus.o \ atrac3plusdsp.o atrac.o +OBJS-$(CONFIG_ATRAC3PAL_DECODER) += atrac3plusdec.o atrac3plus.o \ + atrac3plusdsp.o atrac.o OBJS-$(CONFIG_AURA_DECODER) += cyuv.o OBJS-$(CONFIG_AURA2_DECODER) += aura.o OBJS-$(CONFIG_AVRN_DECODER) += avrndec.o mjpegdec.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index f92b2b7..7220864 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -403,7 +403,9 @@ void avcodec_register_all(void) REGISTER_DECODER(APE, ape); REGISTER_DECODER(ATRAC1, atrac1); REGISTER_DECODER(ATRAC3, atrac3); + REGISTER_DECODER(ATRAC3AL, atrac3al); REGISTER_DECODER(ATRAC3P, atrac3p); + REGISTER_DECODER(ATRAC3PAL, atrac3pal); REGISTER_DECODER(BINKAUDIO_DCT, binkaudio_dct); REGISTER_DECODER(BINKAUDIO_RDFT, binkaudio_rdft); REGISTER_DECODER(BMV_AUDIO, bmv_audio); diff --git a/libavcodec/atrac3.c b/libavcodec/atrac3.c index ffd93e4..5b8ede7 100644 --- a/libavcodec/atrac3.c +++ b/libavcodec/atrac3.c @@ -731,6 +731,101 @@ static int decode_frame(AVCodecContext *avctx, const uint8_t *databuf, return 0; } +static int al_decode_frame(AVCodecContext *avctx, const uint8_t *databuf, + int size, float **out_samples) +{ + ATRAC3Context *q = avctx->priv_data; + int ret, i; + uint8_t *ptr1; + + if (q->coding_mode == JOINT_STEREO) { + /* channel coupling mode */ + /* decode Sound Unit 1 */ + ret = init_get_bits8(&q->gb, databuf, size); + if (ret < 0) + return ret; + + ret = decode_channel_sound_unit(q, &q->gb, q->units, out_samples[0], 0, + JOINT_STEREO); + if (ret != 0) + return ret; + + /* Framedata of the su2 in the joint-stereo mode is encoded in + * reverse byte order so we need to swap it first. */ + if (databuf == q->decoded_bytes_buffer) { + uint8_t *ptr2 = q->decoded_bytes_buffer + size - 1; + ptr1 = q->decoded_bytes_buffer; + for (i = 0; i < size / 2; i++, ptr1++, ptr2--) + FFSWAP(uint8_t, *ptr1, *ptr2); + } else { + const uint8_t *ptr2 = databuf + size - 1; + for (i = 0; i < size; i++) + q->decoded_bytes_buffer[i] = *ptr2--; + } + + /* Skip the sync codes (0xF8). */ + ptr1 = q->decoded_bytes_buffer; + for (i = 4; *ptr1 == 0xF8; i++, ptr1++) { + if (i >= size) + return AVERROR_INVALIDDATA; + } + + + /* set the bitstream reader at the start of the second Sound Unit*/ + init_get_bits8(&q->gb, ptr1, q->decoded_bytes_buffer + size - ptr1); + + /* Fill the Weighting coeffs delay buffer */ + memmove(q->weighting_delay, &q->weighting_delay[2], + 4 * sizeof(*q->weighting_delay)); + q->weighting_delay[4] = get_bits1(&q->gb); + q->weighting_delay[5] = get_bits(&q->gb, 3); + + for (i = 0; i < 4; i++) { + q->matrix_coeff_index_prev[i] = q->matrix_coeff_index_now[i]; + q->matrix_coeff_index_now[i] = q->matrix_coeff_index_next[i]; + q->matrix_coeff_index_next[i] = get_bits(&q->gb, 2); + } + + /* Decode Sound Unit 2. */ + ret = decode_channel_sound_unit(q, &q->gb, &q->units[1], + out_samples[1], 1, JOINT_STEREO); + if (ret != 0) + return ret; + + /* Reconstruct the channel coefficients. */ + reverse_matrixing(out_samples[0], out_samples[1], + q->matrix_coeff_index_prev, + q->matrix_coeff_index_now); + + channel_weighting(out_samples[0], out_samples[1], q->weighting_delay); + } else { + /* Set the bitstream reader at the start of a channel sound unit. */ + init_get_bits(&q->gb, databuf, size * 8); + /* single channels */ + /* Decode the channel sound units. */ + for (i = 0; i < avctx->channels; i++) { + ret = decode_channel_sound_unit(q, &q->gb, &q->units[i], + out_samples[i], i, q->coding_mode); + if (ret != 0) + return ret; + align_get_bits(&q->gb); + } + } + + /* Apply the iQMF synthesis filter. */ + for (i = 0; i < avctx->channels; i++) { + float *p1 = out_samples[i]; + float *p2 = p1 + 256; + float *p3 = p2 + 256; + float *p4 = p3 + 256; + ff_atrac_iqmf(p1, p2, 256, p1, q->units[i].delay_buf1, q->temp_buf); + ff_atrac_iqmf(p4, p3, 256, p3, q->units[i].delay_buf2, q->temp_buf); + ff_atrac_iqmf(p1, p3, 512, p1, q->units[i].delay_buf3, q->temp_buf); + } + + return 0; +} + static int atrac3_decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *avpkt) { @@ -771,6 +866,28 @@ static int atrac3_decode_frame(AVCodecContext *avctx, void *data, return avctx->block_align; } +static int atrac3al_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + int ret; + + frame->nb_samples = SAMPLES_PER_FRAME; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + ret = al_decode_frame(avctx, avpkt->data, avpkt->size, + (float **)frame->extended_data); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Frame decoding error!\n"); + return ret; + } + + *got_frame_ptr = 1; + + return avpkt->size; +} + static av_cold void atrac3_init_static_data(void) { int i; @@ -826,7 +943,8 @@ static av_cold int atrac3_decode_init(AVCodecContext *avctx) q->coding_mode = q->coding_mode ? JOINT_STEREO : SINGLE; q->scrambled_stream = 0; - if (avctx->block_align != 96 * avctx->channels * frame_factor && + if (avctx->codec_id != AV_CODEC_ID_ATRAC3AL && + avctx->block_align != 96 * avctx->channels * frame_factor && avctx->block_align != 152 * avctx->channels * frame_factor && avctx->block_align != 192 * avctx->channels * frame_factor) { av_log(avctx, AV_LOG_ERROR, "Unknown frame/channel/frame_factor " @@ -937,3 +1055,17 @@ AVCodec ff_atrac3_decoder = { .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; + +AVCodec ff_atrac3al_decoder = { + .name = "atrac3al", + .long_name = NULL_IF_CONFIG_SMALL("ATRAC3 AL (Adaptive TRansform Acoustic Coding 3 Advanced Lossless)"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ATRAC3AL, + .priv_data_size = sizeof(ATRAC3Context), + .init = atrac3_decode_init, + .close = atrac3_decode_close, + .decode = atrac3al_decode_frame, + .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/libavcodec/atrac3plusdec.c b/libavcodec/atrac3plusdec.c index ec2b1ad..ea67d31 100644 --- a/libavcodec/atrac3plusdec.c +++ b/libavcodec/atrac3plusdec.c @@ -384,7 +384,7 @@ static int atrac3p_decode_frame(AVCodecContext *avctx, void *data, *got_frame_ptr = 1; - return FFMIN(avctx->block_align, avpkt->size); + return avctx->codec_id == AV_CODEC_ID_ATRAC3P ? FFMIN(avctx->block_align, avpkt->size) : avpkt->size; } AVCodec ff_atrac3p_decoder = { @@ -398,3 +398,15 @@ AVCodec ff_atrac3p_decoder = { .close = atrac3p_decode_close, .decode = atrac3p_decode_frame, }; + +AVCodec ff_atrac3pal_decoder = { + .name = "atrac3pal", + .long_name = NULL_IF_CONFIG_SMALL("ATRAC3+ AL (Adaptive TRansform Acoustic Coding 3+ Advanced Lossless)"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ATRAC3PAL, + .capabilities = AV_CODEC_CAP_DR1, + .priv_data_size = sizeof(ATRAC3PContext), + .init = atrac3p_decode_init, + .close = atrac3p_decode_close, + .decode = atrac3p_decode_frame, +}; diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 1e681e9..8f69f1e 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -603,6 +603,8 @@ enum AVCodecID { AV_CODEC_ID_XMA1, AV_CODEC_ID_XMA2, AV_CODEC_ID_DST, + AV_CODEC_ID_ATRAC3AL, + AV_CODEC_ID_ATRAC3PAL, /* subtitle codecs */ AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 09d3c48..77c69a4 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -2477,6 +2477,20 @@ static const AVCodecDescriptor codec_descriptors[] = { .props = AV_CODEC_PROP_LOSSY, }, { + .id = AV_CODEC_ID_ATRAC3PAL, + .type = AVMEDIA_TYPE_AUDIO, + .name = "atrac3pal", + .long_name = NULL_IF_CONFIG_SMALL("ATRAC3+ AL (Adaptive TRansform Acoustic Coding 3+ Advanced Lossless)"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_ATRAC3AL, + .type = AVMEDIA_TYPE_AUDIO, + .name = "atrac3al", + .long_name = NULL_IF_CONFIG_SMALL("ATRAC3 AL (Adaptive TRansform Acoustic Coding 3 Advanced Lossless)"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { .id = AV_CODEC_ID_EAC3, .type = AVMEDIA_TYPE_AUDIO, .name = "eac3", diff --git a/libavformat/oma.c b/libavformat/oma.c index 2702867..f7ae3c9 100644 --- a/libavformat/oma.c +++ b/libavformat/oma.c @@ -26,10 +26,12 @@ const uint16_t ff_oma_srate_tab[8] = { 320, 441, 480, 882, 960, 0 }; const AVCodecTag ff_oma_codec_tags[] = { - { AV_CODEC_ID_ATRAC3, OMA_CODECID_ATRAC3 }, - { AV_CODEC_ID_ATRAC3P, OMA_CODECID_ATRAC3P }, - { AV_CODEC_ID_MP3, OMA_CODECID_MP3 }, - { AV_CODEC_ID_PCM_S16BE, OMA_CODECID_LPCM }, + { AV_CODEC_ID_ATRAC3, OMA_CODECID_ATRAC3 }, + { AV_CODEC_ID_ATRAC3P, OMA_CODECID_ATRAC3P }, + { AV_CODEC_ID_MP3, OMA_CODECID_MP3 }, + { AV_CODEC_ID_PCM_S16BE, OMA_CODECID_LPCM }, + { AV_CODEC_ID_ATRAC3PAL, OMA_CODECID_ATRAC3PAL }, + { AV_CODEC_ID_ATRAC3AL, OMA_CODECID_ATRAC3AL }, { 0 }, }; diff --git a/libavformat/oma.h b/libavformat/oma.h index e2a187b..36fd012 100644 --- a/libavformat/oma.h +++ b/libavformat/oma.h @@ -35,6 +35,8 @@ enum { OMA_CODECID_MP3 = 3, OMA_CODECID_LPCM = 4, OMA_CODECID_WMA = 5, + OMA_CODECID_ATRAC3PAL = 33, + OMA_CODECID_ATRAC3AL = 34, }; extern const uint16_t ff_oma_srate_tab[8]; diff --git a/libavformat/omadec.c b/libavformat/omadec.c index 757ae53..036d998 100644 --- a/libavformat/omadec.c +++ b/libavformat/omadec.c @@ -75,6 +75,8 @@ typedef struct OMAContext { uint8_t e_val[8]; uint8_t iv[8]; struct AVDES *av_des; + + int (*read_packet)(AVFormatContext *s, AVPacket *pkt); } OMAContext; static void hex_log(AVFormatContext *s, int level, @@ -302,6 +304,82 @@ static int decrypt_init(AVFormatContext *s, ID3v2ExtraMeta *em, uint8_t *header) return 0; } +static int read_packet(AVFormatContext *s, AVPacket *pkt) +{ + OMAContext *oc = s->priv_data; + AVStream *st = s->streams[0]; + int packet_size = st->codecpar->block_align; + int byte_rate = st->codecpar->bit_rate >> 3; + int64_t pos = avio_tell(s->pb); + int ret = av_get_packet(s->pb, pkt, packet_size); + + if (ret < packet_size) + pkt->flags |= AV_PKT_FLAG_CORRUPT; + + if (ret < 0) + return ret; + if (!ret) + return AVERROR_EOF; + + pkt->stream_index = 0; + + if (pos >= oc->content_start && byte_rate > 0) { + pkt->pts = + pkt->dts = av_rescale(pos - oc->content_start, st->time_base.den, + byte_rate * (int64_t)st->time_base.num); + } + + if (oc->encrypted) { + /* previous unencrypted block saved in IV for + * the next packet (CBC mode) */ + if (ret == packet_size) + av_des_crypt(oc->av_des, pkt->data, pkt->data, + (packet_size >> 3), oc->iv, 1); + else + memset(oc->iv, 0, 8); + } + + return ret; +} + +static int aal_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + int64_t pos = avio_tell(s->pb); + int ret, type, pts; + int packet_size; + unsigned tag; + + if (avio_feof(s->pb)) + return AVERROR_EOF; + + tag = avio_rb24(s->pb); + if (tag == 0) + return AVERROR_EOF; + else if (tag != MKBETAG(0,'B','L','K')) + return AVERROR_INVALIDDATA; + + type = avio_r8(s->pb); + packet_size = avio_rb16(s->pb); + avio_skip(s->pb, 2); + pts = avio_rb32(s->pb); + avio_skip(s->pb, 12); + ret = av_get_packet(s->pb, pkt, packet_size); + if (ret < packet_size) + pkt->flags |= AV_PKT_FLAG_CORRUPT; + + if (ret < 0) + return ret; + if (!ret) + return AVERROR_EOF; + + pkt->stream_index = 0; + pkt->pos = pos; + pkt->pts = pts * 2048LL; + pkt->duration = 2048; + + return ret; +} + static int oma_read_header(AVFormatContext *s) { int ret, framesize, jsflag, samplerate; @@ -347,6 +425,8 @@ static int oma_read_header(AVFormatContext *s) st->codecpar->codec_id = ff_codec_get_id(ff_oma_codec_tags, st->codecpar->codec_tag); + oc->read_packet = read_packet; + switch (buf[32]) { case OMA_CODECID_ATRAC3: samplerate = ff_oma_srate_tab[(codec_params >> 13) & 7] * 100; @@ -417,6 +497,56 @@ static int oma_read_header(AVFormatContext *s) av_get_bits_per_sample(st->codecpar->codec_id); avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); break; + case OMA_CODECID_ATRAC3AL: + samplerate = ff_oma_srate_tab[codec_params & 7] * 100; + if (!samplerate) { + av_log(s, AV_LOG_ERROR, "Unsupported sample rate\n"); + return AVERROR_INVALIDDATA; + } + + /* get stereo coding mode, 1 for joint-stereo */ + jsflag = (codec_params >> 9) & 1; + + st->codecpar->channels = 2; + st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->sample_rate = samplerate; + + /* fake the ATRAC3 extradata + * (wav format, makes stream copy to wav work) */ + if (ff_alloc_extradata(st->codecpar, 14)) + return AVERROR(ENOMEM); + + edata = st->codecpar->extradata; + AV_WL16(&edata[0], 1); // always 1 + AV_WL32(&edata[2], samplerate); // samples rate + AV_WL16(&edata[6], jsflag); // coding mode + AV_WL16(&edata[8], jsflag); // coding mode + AV_WL16(&edata[10], 1); // always 1 + // AV_WL16(&edata[12], 0); // always 0 + + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); + oc->read_packet = aal_read_packet; + framesize = 4096; + break; + case OMA_CODECID_ATRAC3PAL: + channel_id = (codec_params >> 15) & 7; + if (!channel_id) { + av_log(s, AV_LOG_ERROR, + "Invalid ATRAC-AL channel id: %"PRIu32"\n", channel_id); + return AVERROR_INVALIDDATA; + } + st->codecpar->channel_layout = ff_oma_chid_to_native_layout[channel_id - 1]; + st->codecpar->channels = ff_oma_chid_to_num_channels[channel_id - 1]; + samplerate = ff_oma_srate_tab[(codec_params >> 6) & 7] * 100; + if (!samplerate) { + av_log(s, AV_LOG_ERROR, "Unsupported sample rate\n"); + return AVERROR_INVALIDDATA; + } + st->codecpar->sample_rate = samplerate; + avpriv_set_pts_info(st, 64, 1, samplerate); + oc->read_packet = aal_read_packet; + framesize = 4096; + break; default: av_log(s, AV_LOG_ERROR, "Unsupported codec %d!\n", buf[32]); return AVERROR(ENOSYS); @@ -427,43 +557,10 @@ static int oma_read_header(AVFormatContext *s) return 0; } - static int oma_read_packet(AVFormatContext *s, AVPacket *pkt) { OMAContext *oc = s->priv_data; - AVStream *st = s->streams[0]; - int packet_size = st->codecpar->block_align; - int byte_rate = st->codecpar->bit_rate >> 3; - int64_t pos = avio_tell(s->pb); - int ret = av_get_packet(s->pb, pkt, packet_size); - - if (ret < packet_size) - pkt->flags |= AV_PKT_FLAG_CORRUPT; - - if (ret < 0) - return ret; - if (!ret) - return AVERROR_EOF; - - pkt->stream_index = 0; - - if (pos >= oc->content_start && byte_rate > 0) { - pkt->pts = - pkt->dts = av_rescale(pos - oc->content_start, st->time_base.den, - byte_rate * (int64_t)st->time_base.num); - } - - if (oc->encrypted) { - /* previous unencrypted block saved in IV for - * the next packet (CBC mode) */ - if (ret == packet_size) - av_des_crypt(oc->av_des, pkt->data, pkt->data, - (packet_size >> 3), oc->iv, 1); - else - memset(oc->iv, 0, 8); - } - - return ret; + return oc->read_packet(s, pkt); } static int oma_read_probe(AVProbeData *p) @@ -491,8 +588,14 @@ static int oma_read_seek(struct AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { OMAContext *oc = s->priv_data; - int64_t err = ff_pcm_read_seek(s, stream_index, timestamp, flags); + AVStream *st = s->streams[0]; + int64_t err; + + if (st->codecpar->codec_id == AV_CODEC_ID_ATRAC3PAL || + st->codecpar->codec_id == AV_CODEC_ID_ATRAC3AL) + return -1; + err = ff_pcm_read_seek(s, stream_index, timestamp, flags); if (!oc->encrypted) return err;