diff options
author | Paul B Mahol <onemda@gmail.com> | 2017-01-25 13:33:52 +0100 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2017-02-11 12:00:38 +0100 |
commit | 280a40dd2739e9a23bf6372752dcd133ff36e149 (patch) | |
tree | 95e116d64a70560c95d4c6979ef1af7edbecadf3 /libavformat | |
parent | d96ebc5ef88024869de06bcf92b2ad99b01d47e3 (diff) | |
download | ffmpeg-280a40dd2739e9a23bf6372752dcd133ff36e149.tar.gz |
avcodec: add ATRAC Advanced Lossless decoders
Only lossy part is decoded for now.
Signed-off-by: Paul B Mahol <onemda@gmail.com>
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/oma.c | 10 | ||||
-rw-r--r-- | libavformat/oma.h | 2 | ||||
-rw-r--r-- | libavformat/omadec.c | 139 |
3 files changed, 112 insertions, 39 deletions
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; |