|
|
|
@ -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; |
|
|
|
|
|
|
|
|
|