switch (atom.type) {
case MKTAG(0xa9,'n','a','m'): key = "title"; break;
case MKTAG(0xa9,'a','u','t'):
- case MKTAG(0xa9,'A','R','T'):
- case MKTAG(0xa9,'w','r','t'): key = "author"; break;
+ case MKTAG(0xa9,'A','R','T'): key = "author"; break;
+ case MKTAG(0xa9,'w','r','t'): key = "composer"; break;
+ case MKTAG( 'c','p','r','t'):
case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
case MKTAG(0xa9,'c','m','t'):
case MKTAG(0xa9,'i','n','f'): key = "comment"; break;
case MKTAG(0xa9,'d','a','y'): key = "year"; break;
case MKTAG(0xa9,'g','e','n'): key = "genre"; break;
case MKTAG(0xa9,'t','o','o'):
- case MKTAG(0xa9,'e','n','c'): key = "muxer"; break;
+ case MKTAG(0xa9,'e','n','c'): key = "encoder"; break;
+ case MKTAG( 'd','e','s','c'): key = "description";break;
+ case MKTAG( 'l','d','e','s'): key = "synopsis"; break;
+ case MKTAG( 't','v','s','h'): key = "show"; break;
+ case MKTAG( 't','v','e','n'): key = "episode_id";break;
+ case MKTAG( 't','v','n','n'): key = "network"; break;
case MKTAG( 't','r','k','n'): key = "track";
parse = mov_metadata_trkn; break;
}
int64_t total_size = 0;
MOVAtom a;
int i;
- int err = 0;
-
- a.offset = atom.offset;
if (atom.size < 0)
atom.size = INT64_MAX;
- while(((total_size + 8) < atom.size) && !url_feof(pb) && !err) {
+ while (total_size + 8 < atom.size && !url_feof(pb)) {
int (*parse)(MOVContext*, ByteIOContext*, MOVAtom) = NULL;
a.size = atom.size;
a.type=0;
a.type = get_le32(pb);
}
total_size += 8;
- a.offset += 8;
dprintf(c->fc, "type: %08x %.4s sz: %"PRIx64" %"PRIx64" %"PRIx64"\n",
a.type, (char*)&a.type, a.size, atom.size, total_size);
if (a.size == 1) { /* 64 bit extended size */
a.size = get_be64(pb) - 8;
- a.offset += 8;
total_size += 8;
}
if (a.size == 0) {
} else {
int64_t start_pos = url_ftell(pb);
int64_t left;
- err = parse(c, pb, a);
- if (url_is_streamed(pb) && c->found_moov && c->found_mdat)
- break;
+ int err = parse(c, pb, a);
+ if (err < 0)
+ return err;
+ if (c->found_moov && c->found_mdat &&
+ (url_is_streamed(pb) || start_pos + a.size == url_fsize(pb)))
+ return 0;
left = a.size - url_ftell(pb) + start_pos;
if (left > 0) /* skip garbage at atom end */
url_fskip(pb, left);
}
- a.offset += a.size;
total_size += a.size;
}
- if (!err && total_size < atom.size && atom.size < 0x7ffff)
+ if (total_size < atom.size && atom.size < 0x7ffff)
url_fskip(pb, atom.size - total_size);
- return err;
+ return 0;
}
static int mov_read_dref(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
if (dref->type == MKTAG('a','l','i','s') && size > 150) {
/* macintosh alias record */
uint16_t volume_len, len;
- char volume[28];
int16_t type;
url_fskip(pb, 10);
volume_len = get_byte(pb);
volume_len = FFMIN(volume_len, 27);
- get_buffer(pb, volume, 27);
- volume[volume_len] = 0;
- av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", volume, volume_len);
+ get_buffer(pb, dref->volume, 27);
+ dref->volume[volume_len] = 0;
+ av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len);
+
+ url_fskip(pb, 12);
+
+ len = get_byte(pb);
+ len = FFMIN(len, 63);
+ get_buffer(pb, dref->filename, 63);
+ dref->filename[len] = 0;
+ av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len);
- url_fskip(pb, 112);
+ url_fskip(pb, 16);
+
+ /* read next level up_from_alias/down_to_target */
+ dref->nlvl_from = get_be16(pb);
+ dref->nlvl_to = get_be16(pb);
+ av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n",
+ dref->nlvl_from, dref->nlvl_to);
+
+ url_fskip(pb, 16);
for (type = 0; type != -1 && url_ftell(pb) < next; ) {
type = get_be16(pb);
if (!dref->path)
return AVERROR(ENOMEM);
get_buffer(pb, dref->path, len);
- if (len > volume_len && !strncmp(dref->path, volume, volume_len)) {
+ if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) {
len -= volume_len;
memmove(dref->path, dref->path+volume_len, len);
dref->path[len] = 0;
if (dref->path[j] == ':')
dref->path[j] = '/';
av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
+ } else if (type == 0) { // directory name
+ av_free(dref->dir);
+ dref->dir = av_malloc(len+1);
+ if (!dref->dir)
+ return AVERROR(ENOMEM);
+ get_buffer(pb, dref->dir, len);
+ dref->dir[len] = 0;
+ for (j = 0; j < len; j++)
+ if (dref->dir[j] == ':')
+ dref->dir[j] = '/';
+ av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir);
} else
url_fskip(pb, len);
}
get_be32(pb); /* component flags */
get_be32(pb); /* component flags mask */
- if(atom.size <= 24)
- return 0; /* nothing left to read */
-
- url_fskip(pb, atom.size - (url_ftell(pb) - atom.offset));
return 0;
}
-static int mp4_read_descr_len(ByteIOContext *pb)
+int ff_mp4_read_descr_len(ByteIOContext *pb)
{
int len = 0;
int count = 4;
return len;
}
-static int mp4_read_descr(MOVContext *c, ByteIOContext *pb, int *tag)
+int mp4_read_descr(AVFormatContext *fc, ByteIOContext *pb, int *tag)
{
int len;
*tag = get_byte(pb);
- len = mp4_read_descr_len(pb);
- dprintf(c->fc, "MPEG4 description: tag=0x%02x len=%d\n", *tag, len);
+ len = ff_mp4_read_descr_len(pb);
+ dprintf(fc, "MPEG4 description: tag=0x%02x len=%d\n", *tag, len);
return len;
}
{ CODEC_ID_NONE, AOT_NULL },
};
-static int mov_read_esds(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
+int ff_mov_read_esds(AVFormatContext *fc, ByteIOContext *pb, MOVAtom atom)
{
AVStream *st;
int tag, len;
- if (c->fc->nb_streams < 1)
+ if (fc->nb_streams < 1)
return 0;
- st = c->fc->streams[c->fc->nb_streams-1];
+ st = fc->streams[fc->nb_streams-1];
get_be32(pb); /* version + flags */
- len = mp4_read_descr(c, pb, &tag);
+ len = mp4_read_descr(fc, pb, &tag);
if (tag == MP4ESDescrTag) {
get_be16(pb); /* ID */
get_byte(pb); /* priority */
} else
get_be16(pb); /* ID */
- len = mp4_read_descr(c, pb, &tag);
+ len = mp4_read_descr(fc, pb, &tag);
if (tag == MP4DecConfigDescrTag) {
int object_type_id = get_byte(pb);
get_byte(pb); /* stream type */
get_be32(pb); /* avg bitrate */
st->codec->codec_id= ff_codec_get_id(ff_mp4_obj_type, object_type_id);
- dprintf(c->fc, "esds object type id %d\n", object_type_id);
- len = mp4_read_descr(c, pb, &tag);
+ dprintf(fc, "esds object type id 0x%02x\n", object_type_id);
+ len = mp4_read_descr(fc, pb, &tag);
if (tag == MP4DecSpecificDescrTag) {
- dprintf(c->fc, "Specific MPEG4 header len=%d\n", len);
+ dprintf(fc, "Specific MPEG4 header len=%d\n", len);
if((uint64_t)len > (1<<30))
return -1;
st->codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
MPEG4AudioConfig cfg;
ff_mpeg4audio_get_config(&cfg, st->codec->extradata,
st->codec->extradata_size);
- if (cfg.chan_config > 7)
- return -1;
- st->codec->channels = ff_mpeg4audio_channels[cfg.chan_config];
+ st->codec->channels = cfg.channels;
if (cfg.object_type == 29 && cfg.sampling_index < 3) // old mp3on4
st->codec->sample_rate = ff_mpa_freq_tab[cfg.sampling_index];
else
st->codec->sample_rate = cfg.sample_rate; // ext sample rate ?
- dprintf(c->fc, "mp4a config channels %d obj %d ext obj %d "
+ dprintf(fc, "mp4a config channels %d obj %d ext obj %d "
"sample rate %d ext sample rate %d\n", st->codec->channels,
cfg.object_type, cfg.ext_object_type,
cfg.sample_rate, cfg.ext_sample_rate);
return 0;
}
+static int mov_read_esds(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
+{
+ return ff_mov_read_esds(c->fc, pb, atom);
+}
+
static int mov_read_pasp(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
const int num = get_be32(pb);
return 0; /* now go for moov */
}
+/* read major brand, minor version and compatible brands and store them as metadata */
static int mov_read_ftyp(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
- uint32_t type = get_le32(pb);
-
- if (type != MKTAG('q','t',' ',' '))
+ uint32_t minor_ver;
+ int comp_brand_size;
+ char minor_ver_str[11]; /* 32 bit integer -> 10 digits + null */
+ char* comp_brands_str;
+ uint8_t type[5] = {0};
+
+ get_buffer(pb, type, 4);
+ if (strcmp(type, "qt "))
c->isom = 1;
av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
- get_be32(pb); /* minor version */
- url_fskip(pb, atom.size - 8);
+ av_metadata_set(&c->fc->metadata, "major_brand", type);
+ minor_ver = get_be32(pb); /* minor version */
+ snprintf(minor_ver_str, sizeof(minor_ver_str), "%d", minor_ver);
+ av_metadata_set(&c->fc->metadata, "minor_version", minor_ver_str);
+
+ comp_brand_size = atom.size - 8;
+ if (comp_brand_size < 0)
+ return -1;
+ comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */
+ if (!comp_brands_str)
+ return AVERROR(ENOMEM);
+ get_buffer(pb, comp_brands_str, comp_brand_size);
+ comp_brands_str[comp_brand_size] = 0;
+ av_metadata_set(&c->fc->metadata, "compatible_brands", comp_brands_str);
+ av_freep(&comp_brands_str);
+
return 0;
}
* Compute codec id for 'lpcm' tag.
* See CoreAudioTypes and AudioStreamBasicDescription at Apple.
*/
-static enum CodecID mov_get_lpcm_codec_id(int bps, int flags)
+enum CodecID ff_mov_get_lpcm_codec_id(int bps, int flags)
{
if (flags & 1) { // floating point
if (flags & 2) { // big endian
//Parsing Sample description table
enum CodecID id;
int dref_id = 1;
- MOVAtom a = { 0, 0, 0 };
+ MOVAtom a = { 0 };
int64_t start_pos = url_ftell(pb);
int size = get_be32(pb); /* size */
uint32_t format = get_le32(pb); /* data format */
st->codec->width = get_be16(pb); /* width */
st->codec->height = get_be16(pb); /* height */
+ if (st->codec->width != sc->width || st->codec->height != sc->height) {
+ AVRational r = av_d2q(
+ ((double)st->codec->height * sc->width) /
+ ((double)st->codec->width * sc->height), INT_MAX);
+ if (st->sample_aspect_ratio.num)
+ st->sample_aspect_ratio = av_mul_q(st->sample_aspect_ratio, r);
+ else
+ st->sample_aspect_ratio = r;
+ }
+
get_be32(pb); /* horiz resolution */
get_be32(pb); /* vert resolution */
get_be32(pb); /* data size, always 0 */
get_buffer(pb, codec_name, 32); /* codec name, pascal string */
if (codec_name[0] <= 31) {
- memcpy(st->codec->codec_name, &codec_name[1],codec_name[0]);
- st->codec->codec_name[codec_name[0]] = 0;
+ int i;
+ int pos = 0;
+ for (i = 0; i < codec_name[0] && pos < sizeof(st->codec->codec_name) - 3; i++) {
+ uint8_t tmp;
+ PUT_UTF8(codec_name[i+1], tmp, st->codec->codec_name[pos++] = tmp;)
+ }
+ st->codec->codec_name[pos] = 0;
}
st->codec->bits_per_coded_sample = get_be16(pb); /* depth */
st->codec->channels = get_be32(pb);
get_be32(pb); /* always 0x7F000000 */
st->codec->bits_per_coded_sample = get_be32(pb); /* bits per channel if sound is uncompressed */
- flags = get_be32(pb); /* lcpm format specific flag */
+ flags = get_be32(pb); /* lpcm format specific flag */
sc->bytes_per_frame = get_be32(pb); /* bytes per audio packet if constant */
sc->samples_per_frame = get_be32(pb); /* lpcm frames per audio packet if constant */
if (format == MKTAG('l','p','c','m'))
- st->codec->codec_id = mov_get_lpcm_codec_id(st->codec->bits_per_coded_sample, flags);
+ st->codec->codec_id = ff_mov_get_lpcm_codec_id(st->codec->bits_per_coded_sample, flags);
}
}
return -1;
}
- if(entries >= UINT_MAX / sizeof(int))
+ if (entries >= UINT_MAX / sizeof(int) || entries >= (UINT_MAX - 4) / field_size)
return -1;
sc->sample_sizes = av_malloc(entries * sizeof(int));
if (!sc->sample_sizes)
return 0;
}
-static int mov_read_cslg(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
-{
- AVStream *st;
- MOVStreamContext *sc;
-
- if (c->fc->nb_streams < 1)
- return 0;
- st = c->fc->streams[c->fc->nb_streams-1];
- sc = st->priv_data;
-
- get_be32(pb); // version + flags
-
- sc->dts_shift = get_be32(pb);
- dprintf(c->fc, "dts shift %d\n", sc->dts_shift);
-
- get_be32(pb); // least dts to pts delta
- get_be32(pb); // greatest dts to pts delta
- get_be32(pb); // pts start
- get_be32(pb); // pts end
-
- return 0;
-}
-
static int mov_read_ctts(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
AVStream *st;
sc->ctts_data[i].count = count;
sc->ctts_data[i].duration= duration;
+ if (duration < 0)
+ sc->dts_shift = FFMAX(sc->dts_shift, -duration);
}
+
+ dprintf(c->fc, "dts shift %d\n", sc->dts_shift);
+
return 0;
}
unsigned int stss_index = 0;
unsigned int stps_index = 0;
unsigned int i, j;
+ uint64_t stream_size = 0;
/* adjust first dts according to edit list */
if (sc->time_offset) {
current_dts -= sc->dts_shift;
- st->nb_frames = sc->sample_count;
for (i = 0; i < sc->chunk_count; i++) {
current_offset = sc->chunk_offsets[i];
if (stsc_index + 1 < sc->stsc_count &&
}
current_offset += sample_size;
+ stream_size += sample_size;
current_dts += sc->stts_data[stts_index].duration;
distance++;
stts_sample++;
}
}
}
+ if (st->duration > 0)
+ st->codec->bit_rate = stream_size*8*sc->time_scale/st->duration;
} else {
for (i = 0; i < sc->chunk_count; i++) {
unsigned chunk_samples;
}
}
+static int mov_open_dref(ByteIOContext **pb, char *src, MOVDref *ref)
+{
+ /* try absolute path */
+ if (!url_fopen(pb, ref->path, URL_RDONLY))
+ return 0;
+
+ /* try relative path */
+ if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
+ char filename[1024];
+ char *src_path;
+ int i, l;
+
+ /* find a source dir */
+ src_path = strrchr(src, '/');
+ if (src_path)
+ src_path++;
+ else
+ src_path = src;
+
+ /* find a next level down to target */
+ for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
+ if (ref->path[l] == '/') {
+ if (i == ref->nlvl_to - 1)
+ break;
+ else
+ i++;
+ }
+
+ /* compose filename if next level down to target was found */
+ if (i == ref->nlvl_to - 1) {
+ memcpy(filename, src, src_path - src);
+ filename[src_path - src] = 0;
+
+ for (i = 1; i < ref->nlvl_from; i++)
+ av_strlcat(filename, "../", 1024);
+
+ av_strlcat(filename, ref->path + l + 1, 1024);
+
+ if (!url_fopen(pb, filename, URL_RDONLY))
+ return 0;
+ }
+ }
+
+ return AVERROR(ENOENT);
+};
+
static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
AVStream *st;
return 0;
}
- if (!sc->time_scale)
+ if (!sc->time_scale) {
+ av_log(c->fc, AV_LOG_WARNING, "stream %d, timescale not set\n", st->index);
sc->time_scale = c->time_scale;
+ if (!sc->time_scale)
+ sc->time_scale = 1;
+ }
av_set_pts_info(st, 64, 1, sc->time_scale);
mov_build_index(c, st);
if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
- if (url_fopen(&sc->pb, sc->drefs[sc->dref_id-1].path, URL_RDONLY) < 0)
- av_log(c->fc, AV_LOG_ERROR, "stream %d, error opening file %s: %s\n",
- st->index, sc->drefs[sc->dref_id-1].path, strerror(errno));
+ MOVDref *dref = &sc->drefs[sc->dref_id - 1];
+ if (mov_open_dref(&sc->pb, c->fc->filename, dref) < 0)
+ av_log(c->fc, AV_LOG_ERROR,
+ "stream %d, error opening alias: path='%s', dir='%s', "
+ "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
+ st->index, dref->path, dref->dir, dref->filename,
+ dref->volume, dref->nlvl_from, dref->nlvl_to);
} else
sc->pb = c->fc->pb;
sc->width = width >> 16;
sc->height = height >> 16;
- //transform the display width/height according to the matrix
+ // transform the display width/height according to the matrix
// skip this if the display matrix is the default identity matrix
+ // or if it is rotating the picture, ex iPhone 3GS
// to keep the same scale, use [width height 1<<16]
if (width && height &&
- (display_matrix[0][0] != 65536 || display_matrix[0][1] ||
- display_matrix[1][0] || display_matrix[1][1] != 65536 ||
- display_matrix[2][0] || display_matrix[2][1])) {
+ ((display_matrix[0][0] != 65536 ||
+ display_matrix[1][1] != 65536) &&
+ !display_matrix[0][1] &&
+ !display_matrix[1][0] &&
+ !display_matrix[2][0] && !display_matrix[2][1])) {
for (i = 0; i < 2; i++)
disp_transform[i] =
(int64_t) width * display_matrix[0][i] +
return 0;
}
atom.type = get_le32(pb);
- atom.offset += 8;
atom.size -= 8;
if (atom.type != MKTAG('m','d','a','t')) {
url_fskip(pb, atom.size);
if(init_put_byte(&ctx, moov_data, moov_len, 0, NULL, NULL, NULL, NULL) != 0)
goto free_and_return;
atom.type = MKTAG('m','o','o','v');
- atom.offset = 0;
atom.size = moov_len;
#ifdef DEBUG
// { int fd = open("/tmp/uncompheader.mov", O_WRONLY | O_CREAT); write(fd, moov_data, moov_len); close(fd); }
/* edit list atom */
static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
- MOVStreamContext *sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
+ MOVStreamContext *sc;
int i, edit_count;
+ if (c->fc->nb_streams < 1)
+ return 0;
+ sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
+
get_byte(pb); /* version */
get_be24(pb); /* flags */
edit_count = get_be32(pb); /* entries */
static const MOVParseTableEntry mov_default_parse_table[] = {
{ MKTAG('a','v','s','s'), mov_read_extradata },
{ MKTAG('c','o','6','4'), mov_read_stco },
-{ MKTAG('c','s','l','g'), mov_read_cslg },
{ MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
{ MKTAG('d','i','n','f'), mov_read_default },
{ MKTAG('d','r','e','f'), mov_read_dref },
MOVContext *mov = s->priv_data;
ByteIOContext *pb = s->pb;
int err;
- MOVAtom atom = { 0, 0, 0 };
+ MOVAtom atom = { 0 };
mov->fc = s;
/* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
return 0;
}
-static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
+static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
{
- MOVContext *mov = s->priv_data;
- MOVStreamContext *sc = 0;
- AVIndexEntry *sample = 0;
- AVStream *st = NULL;
+ AVIndexEntry *sample = NULL;
int64_t best_dts = INT64_MAX;
- int i, ret;
- retry:
+ int i;
for (i = 0; i < s->nb_streams; i++) {
AVStream *avst = s->streams[i];
MOVStreamContext *msc = avst->priv_data;
- if (avst->discard != AVDISCARD_ALL && msc->pb && msc->current_sample < avst->nb_index_entries) {
+ if (msc->pb && msc->current_sample < avst->nb_index_entries) {
AVIndexEntry *current_sample = &avst->index_entries[msc->current_sample];
int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
dprintf(s, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
(FFABS(best_dts - dts) > AV_TIME_BASE && dts < best_dts)))))) {
sample = current_sample;
best_dts = dts;
- st = avst;
+ *st = avst;
}
}
}
+ return sample;
+}
+
+static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ MOVContext *mov = s->priv_data;
+ MOVStreamContext *sc;
+ AVIndexEntry *sample;
+ AVStream *st = NULL;
+ int ret;
+ retry:
+ sample = mov_find_next_sample(s, &st);
if (!sample) {
mov->found_mdat = 0;
if (!url_is_streamed(s->pb) ||
- mov_read_default(mov, s->pb, (MOVAtom){ 0, 0, INT64_MAX }) < 0 ||
+ mov_read_default(mov, s->pb, (MOVAtom){ 0, INT64_MAX }) < 0 ||
url_feof(s->pb))
return AVERROR_EOF;
dprintf(s, "read fragments, offset 0x%llx\n", url_ftell(s->pb));
sc = st->priv_data;
/* must be done just before reading, to avoid infinite loop on sample */
sc->current_sample++;
- if (url_fseek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
- av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
- sc->ffindex, sample->pos);
- return -1;
- }
- ret = av_get_packet(sc->pb, pkt, sample->size);
- if (ret < 0)
- return ret;
-#if CONFIG_DV_DEMUXER
- if (mov->dv_demux && sc->dv_audio_container) {
- dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size);
- av_free(pkt->data);
- pkt->size = 0;
- if (dv_get_packet(mov->dv_demux, pkt) < 0)
+
+ if (st->discard != AVDISCARD_ALL) {
+ if (url_fseek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
+ av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n",
+ sc->ffindex, sample->pos);
return -1;
- }
+ }
+ ret = av_get_packet(sc->pb, pkt, sample->size);
+ if (ret < 0)
+ return ret;
+#if CONFIG_DV_DEMUXER
+ if (mov->dv_demux && sc->dv_audio_container) {
+ dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size);
+ av_free(pkt->data);
+ pkt->size = 0;
+ ret = dv_get_packet(mov->dv_demux, pkt);
+ if (ret < 0)
+ return ret;
+ }
#endif
+ }
+
pkt->stream_index = sc->ffindex;
pkt->dts = sample->timestamp;
if (sc->ctts_data) {
pkt->duration = next_dts - pkt->dts;
pkt->pts = pkt->dts;
}
+ if (st->discard == AVDISCARD_ALL)
+ goto retry;
pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? PKT_FLAG_KEY : 0;
pkt->pos = sample->pos;
dprintf(s, "stream %d, pts %"PRId64", dts %"PRId64", pos 0x%"PRIx64", duration %d\n",
return 0;
}
-static int mov_seek_stream(AVStream *st, int64_t timestamp, int flags)
+static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
{
MOVStreamContext *sc = st->priv_data;
int sample, time_sample;
int i;
sample = av_index_search_timestamp(st, timestamp, flags);
- dprintf(st->codec, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
+ dprintf(s, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
if (sample < 0) /* not sure what to do */
return -1;
sc->current_sample = sample;
- dprintf(st->codec, "stream %d, found sample %d\n", st->index, sc->current_sample);
+ dprintf(s, "stream %d, found sample %d\n", st->index, sc->current_sample);
/* adjust ctts index */
if (sc->ctts_data) {
time_sample = 0;
sample_time = 0;
st = s->streams[stream_index];
- sample = mov_seek_stream(st, sample_time, flags);
+ sample = mov_seek_stream(s, st, sample_time, flags);
if (sample < 0)
return -1;
for (i = 0; i < s->nb_streams; i++) {
st = s->streams[i];
- if (stream_index == i || st->discard == AVDISCARD_ALL)
+ if (stream_index == i)
continue;
timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
- mov_seek_stream(st, timestamp, flags);
+ mov_seek_stream(s, st, timestamp, flags);
}
return 0;
}
MOVStreamContext *sc = st->priv_data;
av_freep(&sc->ctts_data);
- for (j = 0; j < sc->drefs_count; j++)
+ for (j = 0; j < sc->drefs_count; j++) {
av_freep(&sc->drefs[j].path);
+ av_freep(&sc->drefs[j].dir);
+ }
av_freep(&sc->drefs);
if (sc->pb && sc->pb != s->pb)
url_fclose(sc->pb);