#include "libavutil/mathematics.h"
#include "libavcodec/bytestream.h"
+#include "libavcodec/flac.h"
#include "libavcodec/mpeg4audio.h"
#include "avformat.h"
#include "internal.h"
#include "isom.h"
#include "matroska.h"
+#include "oggdec.h"
/* For ff_codec_get_id(). */
#include "riff.h"
#include "rmsipr.h"
av_dict_set(metadata, "creation_time", buffer, 0);
}
+static int matroska_parse_flac(AVFormatContext *s,
+ MatroskaTrack *track,
+ int *offset)
+{
+ AVStream *st = track->stream;
+ uint8_t *p = track->codec_priv.data;
+ int size = track->codec_priv.size;
+
+ if (size < 8 + FLAC_STREAMINFO_SIZE || p[4] & 0x7f) {
+ av_log(s, AV_LOG_WARNING, "Invalid FLAC private data\n");
+ track->codec_priv.size = 0;
+ return 0;
+ }
+ *offset = 8;
+ track->codec_priv.size = 8 + FLAC_STREAMINFO_SIZE;
+
+ p += track->codec_priv.size;
+ size -= track->codec_priv.size;
+
+ /* parse the remaining metadata blocks if present */
+ while (size >= 4) {
+ int block_last, block_type, block_size;
+
+ flac_parse_block_header(p, &block_last, &block_type, &block_size);
+
+ p += 4;
+ size -= 4;
+ if (block_size > size)
+ return 0;
+
+ /* check for the channel mask */
+ if (block_type == FLAC_METADATA_TYPE_VORBIS_COMMENT) {
+ AVDictionary *dict = NULL;
+ AVDictionaryEntry *chmask;
+
+ ff_vorbis_comment(s, &dict, p, block_size, 0);
+ chmask = av_dict_get(dict, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", NULL, 0);
+ if (chmask) {
+ uint64_t mask = strtol(chmask->value, NULL, 0);
+ if (!mask || mask & ~0x3ffffULL) {
+ av_log(s, AV_LOG_WARNING,
+ "Invalid value of WAVEFORMATEXTENSIBLE_CHANNEL_MASK\n");
+ } else
+ st->codec->channel_layout = mask;
+ }
+ av_dict_free(&dict);
+ }
+
+ p += block_size;
+ size -= block_size;
+ }
+
+ return 0;
+}
+
static int matroska_parse_tracks(AVFormatContext *s)
{
MatroskaDemuxContext *matroska = s->priv_data;
MatroskaTrack *tracks = matroska->tracks.elem;
AVStream *st;
- int i, j;
+ int i, j, ret;
int k;
for (i = 0; i < matroska->tracks.nb_elem; i++) {
st->codec->block_align = track->audio.sub_packet_size;
extradata_offset = 78;
}
+ } else if (codec_id == AV_CODEC_ID_FLAC && track->codec_priv.size) {
+ ret = matroska_parse_flac(s, track, &extradata_offset);
+ if (ret < 0)
+ return ret;
} else if (codec_id == AV_CODEC_ID_PRORES && track->codec_priv.size == 4) {
fourcc = AV_RL32(track->codec_priv.data);
}
tracks[i].stream, st->index_entries[index].timestamp,
AVSEEK_FLAG_BACKWARD);
while (index_sub >= 0 &&
- index_min >= 0 &&
+ index_min > 0 &&
tracks[i].stream->index_entries[index_sub].pos < st->index_entries[index_min].pos &&
st->index_entries[index].timestamp - tracks[i].stream->index_entries[index_sub].timestamp < 30000000000 / matroska->time_scale)
index_min--;