* Copyright (c) 2001 Fabrice Bellard
* Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
*
+ * first version by Francois Revol <revol@free.fr>
+ * seek function by Gael Chardon <gael.dev@4now.net>
+ *
* This file is part of Libav.
*
* Libav is free software; you can redistribute it and/or
#include <limits.h>
-//#define DEBUG
//#define MOV_EXPORT_ALL_METADATA
#include "libavutil/attributes.h"
-#include "libavutil/audioconvert.h"
+#include "libavutil/channel_layout.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/intfloat.h"
#include "libavutil/mathematics.h"
#include <zlib.h>
#endif
-/*
- * First version by Francois Revol revol@free.fr
- * Seek function by Gael Chardon gael.dev@4now.net
- */
-
#include "qtpalette.h"
return 0;
}
+#define MIN_DATA_ENTRY_BOX_SIZE 12
static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
AVStream *st;
avio_rb32(pb); // version + flags
entries = avio_rb32(pb);
- if (entries >= UINT_MAX / sizeof(*sc->drefs))
+ if (entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
+ entries >= UINT_MAX / sizeof(*sc->drefs))
return AVERROR_INVALIDDATA;
av_free(sc->drefs);
sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
version = avio_r8(pb);
if (version > 1) {
- av_log_ask_for_sample(c, "unsupported version %d\n", version);
+ avpriv_request_sample(c->fc, "Version %d", version);
return AVERROR_PATCHWELCOME;
}
avio_rb24(pb); /* flags */
*/
enum AVCodecID ff_mov_get_lpcm_codec_id(int bps, int flags)
{
- if (flags & 1) { // floating point
- if (flags & 2) { // big endian
- if (bps == 32) return AV_CODEC_ID_PCM_F32BE;
- else if (bps == 64) return AV_CODEC_ID_PCM_F64BE;
- } else {
- if (bps == 32) return AV_CODEC_ID_PCM_F32LE;
- else if (bps == 64) return AV_CODEC_ID_PCM_F64LE;
- }
- } else {
- if (flags & 2) {
- if (bps == 8)
- // signed integer
- if (flags & 4) return AV_CODEC_ID_PCM_S8;
- else return AV_CODEC_ID_PCM_U8;
- else if (bps == 16) return AV_CODEC_ID_PCM_S16BE;
- else if (bps == 24) return AV_CODEC_ID_PCM_S24BE;
- else if (bps == 32) return AV_CODEC_ID_PCM_S32BE;
- } else {
- if (bps == 8)
- if (flags & 4) return AV_CODEC_ID_PCM_S8;
- else return AV_CODEC_ID_PCM_U8;
- else if (bps == 16) return AV_CODEC_ID_PCM_S16LE;
- else if (bps == 24) return AV_CODEC_ID_PCM_S24LE;
- else if (bps == 32) return AV_CODEC_ID_PCM_S32LE;
- }
- }
- return AV_CODEC_ID_NONE;
+ /* lpcm flags:
+ * 0x1 = float
+ * 0x2 = big-endian
+ * 0x4 = signed
+ */
+ return ff_get_pcm_codec_id(bps, flags & 1, flags & 2, flags & 4 ? -1 : 0);
}
int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
/* codec_tag YV12 triggers an UV swap in rawdec.c */
if (!memcmp(st->codec->codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25))
st->codec->codec_tag=MKTAG('I', '4', '2', '0');
+ /* Flash Media Server uses tag H263 with Sorenson Spark */
+ if (format == MKTAG('H','2','6','3') &&
+ !memcmp(st->codec->codec_name, "Sorenson H263", 13))
+ st->codec->codec_id = AV_CODEC_ID_FLV1;
st->codec->bits_per_coded_sample = avio_rb16(pb); /* depth */
color_table_id = avio_rb16(pb); /* colortable id */
return 0;
}
+static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+ AVStream *st;
+ MOVStreamContext *sc;
+ unsigned int i, entries;
+ uint8_t version;
+ uint32_t grouping_type;
+
+ if (c->fc->nb_streams < 1)
+ return 0;
+ st = c->fc->streams[c->fc->nb_streams-1];
+ sc = st->priv_data;
+
+ version = avio_r8(pb); /* version */
+ avio_rb24(pb); /* flags */
+ grouping_type = avio_rl32(pb);
+ if (grouping_type != MKTAG( 'r','a','p',' '))
+ return 0; /* only support 'rap ' grouping */
+ if (version == 1)
+ avio_rb32(pb); /* grouping_type_parameter */
+
+ entries = avio_rb32(pb);
+ if (!entries)
+ return 0;
+ if (entries >= UINT_MAX / sizeof(*sc->rap_group))
+ return AVERROR_INVALIDDATA;
+ sc->rap_group = av_malloc(entries * sizeof(*sc->rap_group));
+ if (!sc->rap_group)
+ return AVERROR(ENOMEM);
+
+ for (i = 0; i < entries && !pb->eof_reached; i++) {
+ sc->rap_group[i].count = avio_rb32(pb); /* sample_count */
+ sc->rap_group[i].index = avio_rb32(pb); /* group_description_index */
+ }
+
+ sc->rap_group_count = i;
+
+ return pb->eof_reached ? AVERROR_EOF : 0;
+}
+
static void mov_build_index(MOVContext *mov, AVStream *st)
{
MOVStreamContext *sc = st->priv_data;
unsigned int stts_sample = 0;
unsigned int sample_size;
unsigned int distance = 0;
+ unsigned int rap_group_index = 0;
+ unsigned int rap_group_sample = 0;
+ int rap_group_present = sc->rap_group_count && sc->rap_group;
int key_off = (sc->keyframes && sc->keyframes[0] > 0) || (sc->stps_data && sc->stps_data[0] > 0);
current_dts -= sc->dts_shift;
if (stps_index + 1 < sc->stps_count)
stps_index++;
}
+ if (rap_group_present && rap_group_index < sc->rap_group_count) {
+ if (sc->rap_group[rap_group_index].index > 0)
+ keyframe = 1;
+ if (++rap_group_sample == sc->rap_group[rap_group_index].count) {
+ rap_group_sample = 0;
+ rap_group_index++;
+ }
+ }
if (keyframe)
distance = 0;
sample_size = sc->sample_size > 0 ? sc->sample_size : sc->sample_sizes[current_sample];
((double)st->codec->width * sc->height), INT_MAX);
}
- av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
- sc->time_scale*st->nb_frames, st->duration, INT_MAX);
-
-#if FF_API_R_FRAME_RATE
- if (sc->stts_count == 1 || (sc->stts_count == 2 && sc->stts_data[1].count == 1))
- av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
- sc->time_scale, sc->stts_data[0].duration, INT_MAX);
-#endif
+ if (st->duration != AV_NOPTS_VALUE)
+ av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
+ sc->time_scale*st->nb_frames, st->duration, INT_MAX);
}
switch (st->codec->codec_id) {
av_freep(&sc->keyframes);
av_freep(&sc->stts_data);
av_freep(&sc->stps_data);
+ av_freep(&sc->rap_group);
return 0;
}
{ MKTAG('c','m','o','v'), mov_read_cmov },
{ MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout */
{ MKTAG('d','v','c','1'), mov_read_dvc1 },
+{ MKTAG('s','b','g','p'), mov_read_sbgp },
{ 0, NULL }
};
case MKTAG('p','r','f','l'):
offset = AV_RB32(p->buf+offset) + offset;
/* if we only find those cause probedata is too small at least rate them */
- score = AVPROBE_SCORE_MAX - 50;
+ score = AVPROBE_SCORE_EXTENSION;
break;
default:
/* unrecognized tag */