diff options
author | Paul B Mahol <onemda@gmail.com> | 2017-01-25 15:33:52 +0300 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2017-02-11 14:00:38 +0300 |
commit | 280a40dd2739e9a23bf6372752dcd133ff36e149 (patch) | |
tree | 95e116d64a70560c95d4c6979ef1af7edbecadf3 | |
parent | d96ebc5ef88024869de06bcf92b2ad99b01d47e3 (diff) |
avcodec: add ATRAC Advanced Lossless decoders
Only lossy part is decoded for now.
Signed-off-by: Paul B Mahol <onemda@gmail.com>
-rw-r--r-- | libavcodec/Makefile | 3 | ||||
-rw-r--r-- | libavcodec/allcodecs.c | 2 | ||||
-rw-r--r-- | libavcodec/atrac3.c | 77 | ||||
-rw-r--r-- | libavcodec/atrac3plusdec.c | 14 | ||||
-rw-r--r-- | libavcodec/avcodec.h | 2 | ||||
-rw-r--r-- | libavcodec/codec_desc.c | 14 | ||||
-rw-r--r-- | libavcodec/version.h | 2 | ||||
-rw-r--r-- | libavformat/oma.c | 10 | ||||
-rw-r--r-- | libavformat/oma.h | 2 | ||||
-rw-r--r-- | libavformat/omadec.c | 139 |
10 files changed, 223 insertions, 42 deletions
diff --git a/libavcodec/Makefile b/libavcodec/Makefile index c4e108665d..3427dff3eb 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -193,8 +193,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 4d9a98374b..1043930905 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 83bc9b65f3..f0a948e0d7 100644 --- a/libavcodec/atrac3.c +++ b/libavcodec/atrac3.c @@ -751,6 +751,40 @@ 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; + + /* 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; + while (i < avctx->channels && get_bits_left(&q->gb) > 6 && show_bits(&q->gb, 6) != 0x28) { + skip_bits(&q->gb, 1); + } + } + + /* 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) { @@ -791,6 +825,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; @@ -827,7 +883,12 @@ static av_cold int atrac3_decode_init(AVCodecContext *avctx) static_init_done = 1; /* Take care of the codec-specific extradata. */ - if (avctx->extradata_size == 14) { + if (avctx->codec_id == AV_CODEC_ID_ATRAC3AL) { + version = 4; + samples_per_frame = SAMPLES_PER_FRAME * avctx->channels; + delay = 0x88E; + q->coding_mode = SINGLE; + } else if (avctx->extradata_size == 14) { /* Parse the extradata, WAV format */ av_log(avctx, AV_LOG_DEBUG, "[0-1] %d\n", bytestream_get_le16(&edata_ptr)); // Unknown value always 1 @@ -959,3 +1020,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 ec2b1ad3b2..7a2ab3ef95 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 = "atrac3plusal", + .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 1e681e989b..8f69f1eb55 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 09d3c4809e..77c69a46fe 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/libavcodec/version.h b/libavcodec/version.h index a48cd5bc9e..c2d781b5f8 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 57 -#define LIBAVCODEC_VERSION_MINOR 77 +#define LIBAVCODEC_VERSION_MINOR 78 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavformat/oma.c b/libavformat/oma.c index 27028674db..f7ae3c9948 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 e2a187bacc..36fd0125e4 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 757ae5371a..076da78536 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,22 @@ 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: + st->codecpar->channels = 2; + st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->sample_rate = 44100; + avpriv_set_pts_info(st, 64, 1, 44100); + oc->read_packet = aal_read_packet; + framesize = 4096; + break; + case OMA_CODECID_ATRAC3PAL: + st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->channels = 2; + st->codecpar->sample_rate = 44100; + avpriv_set_pts_info(st, 64, 1, 44100); + 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 +523,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 +554,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; |