aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAurelien Jacobs <aurel@gnuage.org>2007-06-04 22:19:17 +0000
committerAurelien Jacobs <aurel@gnuage.org>2007-06-04 22:19:17 +0000
commiteabb8ba4454147b5bb2c38332143bbfea8a57503 (patch)
tree4eb3b14e0ca29277cf55842c5f11819cad108d01
parent407a3d94f566a68c7a862fcdac812bf53741af94 (diff)
downloadffmpeg-eabb8ba4454147b5bb2c38332143bbfea8a57503.tar.gz
add support for real audio in matroska
Originally committed as revision 9217 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r--libavformat/matroska.c5
-rw-r--r--libavformat/matroskadec.c85
2 files changed, 90 insertions, 0 deletions
diff --git a/libavformat/matroska.c b/libavformat/matroska.c
index 3748a59ea2..d593dea50e 100644
--- a/libavformat/matroska.c
+++ b/libavformat/matroska.c
@@ -53,6 +53,11 @@ CodecTags ff_mkv_codec_tags[]={
{"A_FLAC" , CODEC_ID_FLAC},
{"A_WAVPACK4" , CODEC_ID_WAVPACK},
{"A_TTA1" , CODEC_ID_TTA},
+ {"A_REAL/14_4" , CODEC_ID_RA_144},
+ {"A_REAL/28_8" , CODEC_ID_RA_288},
+ {"A_REAL/ATRC" , CODEC_ID_ATRAC3},
+ {"A_REAL/COOK" , CODEC_ID_COOK},
+// {"A_REAL/SIPR" , CODEC_ID_SIPRO},
{NULL , CODEC_ID_NONE}
/* TODO: AC3-9/10 (?), Real, Musepack, Quicktime */
};
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 6397e04352..f99de66e5a 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -79,6 +79,16 @@ typedef struct MatroskaAudioTrack {
bitdepth,
internal_samplerate,
samplerate;
+ int block_align;
+
+ /* real audio header */
+ int coded_framesize;
+ int sub_packet_h;
+ int frame_size;
+ int sub_packet_size;
+ int sub_packet_cnt;
+ int pkt_cnt;
+ uint8_t *buf;
//..
} MatroskaAudioTrack;
@@ -2103,6 +2113,37 @@ matroska_read_header (AVFormatContext *s,
track->flags |= MATROSKA_TRACK_REAL_V;
}
+ else if (codec_id == CODEC_ID_RA_144) {
+ MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)track;
+ audiotrack->samplerate = 8000;
+ audiotrack->channels = 1;
+ }
+
+ else if (codec_id == CODEC_ID_RA_288 ||
+ codec_id == CODEC_ID_COOK ||
+ codec_id == CODEC_ID_ATRAC3) {
+ MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)track;
+ ByteIOContext b;
+
+ init_put_byte(&b, track->codec_priv, track->codec_priv_size, 0,
+ NULL, NULL, NULL, NULL);
+ url_fskip(&b, 24);
+ audiotrack->coded_framesize = get_be32(&b);
+ url_fskip(&b, 12);
+ audiotrack->sub_packet_h = get_be16(&b);
+ audiotrack->frame_size = get_be16(&b);
+ audiotrack->sub_packet_size = get_be16(&b);
+ audiotrack->buf = av_malloc(audiotrack->frame_size * audiotrack->sub_packet_h);
+ if (codec_id == CODEC_ID_RA_288) {
+ audiotrack->block_align = audiotrack->coded_framesize;
+ track->codec_priv_size = 0;
+ } else {
+ audiotrack->block_align = audiotrack->sub_packet_size;
+ extradata_offset = 78;
+ track->codec_priv_size -= extradata_offset;
+ }
+ }
+
if (codec_id == CODEC_ID_NONE) {
av_log(matroska->ctx, AV_LOG_INFO,
"Unknown/unsupported CodecID %s.\n",
@@ -2159,6 +2200,7 @@ matroska_read_header (AVFormatContext *s,
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->sample_rate = audiotrack->samplerate;
st->codec->channels = audiotrack->channels;
+ st->codec->block_align = audiotrack->block_align;
} else if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE) {
st->codec->codec_type = CODEC_TYPE_SUBTITLE;
}
@@ -2347,6 +2389,43 @@ matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, int size,
slice_size = lace_size[n] - slice_offset;
else
slice_size = rv_offset(data, slice+1, slices) - slice_offset;
+
+ if (st->codec->codec_id == CODEC_ID_RA_288 ||
+ st->codec->codec_id == CODEC_ID_COOK ||
+ st->codec->codec_id == CODEC_ID_ATRAC3) {
+ MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)matroska->tracks[track];
+ int a = st->codec->block_align;
+ int sps = audiotrack->sub_packet_size;
+ int cfs = audiotrack->coded_framesize;
+ int h = audiotrack->sub_packet_h;
+ int y = audiotrack->sub_packet_cnt;
+ int w = audiotrack->frame_size;
+ int x;
+
+ if (!audiotrack->pkt_cnt) {
+ if (st->codec->codec_id == CODEC_ID_RA_288)
+ for (x=0; x<h/2; x++)
+ memcpy(audiotrack->buf+x*2*w+y*cfs,
+ data+x*cfs, cfs);
+ else
+ for (x=0; x<w/sps; x++)
+ memcpy(audiotrack->buf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), data+x*sps, sps);
+
+ if (++audiotrack->sub_packet_cnt >= h) {
+ audiotrack->sub_packet_cnt = 0;
+ audiotrack->pkt_cnt = h*w / a;
+ }
+ }
+ while (audiotrack->pkt_cnt) {
+ pkt = av_mallocz(sizeof(AVPacket));
+ av_new_packet(pkt, a);
+ memcpy(pkt->data, audiotrack->buf
+ + a * (h*w / a - audiotrack->pkt_cnt--), a);
+ pkt->pos = pos;
+ pkt->stream_index = matroska->tracks[track]->stream_index;
+ matroska_queue_packet(matroska, pkt);
+ }
+ } else {
pkt = av_mallocz(sizeof(AVPacket));
/* XXX: prevent data copy... */
if (av_new_packet(pkt, slice_size) < 0) {
@@ -2365,6 +2444,7 @@ matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, int size,
pkt->duration = duration;
matroska_queue_packet(matroska, pkt);
+ }
if (timecode != AV_NOPTS_VALUE)
timecode = duration ? timecode + duration : AV_NOPTS_VALUE;
@@ -2625,6 +2705,11 @@ matroska_read_close (AVFormatContext *s)
av_free(track->name);
av_free(track->language);
+ if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
+ MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)track;
+ av_free(audiotrack->buf);
+ }
+
av_free(track);
}