|
|
@ -59,6 +59,10 @@ |
|
|
|
/* in case you can't read a file, try commenting */ |
|
|
|
/* in case you can't read a file, try commenting */ |
|
|
|
#define MOV_SPLIT_CHUNKS |
|
|
|
#define MOV_SPLIT_CHUNKS |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Special handling for movies created with Minolta Dimaxe Xi*/ |
|
|
|
|
|
|
|
/* this fix should not interfere with other .mov files, but just in case*/ |
|
|
|
|
|
|
|
#define MOV_MINOLTA_FIX |
|
|
|
|
|
|
|
|
|
|
|
/* some streams in QT (and in MP4 mostly) aren't either video nor audio */ |
|
|
|
/* some streams in QT (and in MP4 mostly) aren't either video nor audio */ |
|
|
|
/* so we first list them as this, then clean up the list of streams we give back, */ |
|
|
|
/* so we first list them as this, then clean up the list of streams we give back, */ |
|
|
|
/* getting rid of these */ |
|
|
|
/* getting rid of these */ |
|
|
@ -768,9 +772,10 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
|
|
|
st->codec.bits_per_sample = get_be16(pb); /* depth */ |
|
|
|
st->codec.bits_per_sample = get_be16(pb); /* depth */ |
|
|
|
st->codec.color_table_id = get_be16(pb); /* colortable id */ |
|
|
|
st->codec.color_table_id = get_be16(pb); /* colortable id */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* These are set in mov_read_stts and might already be set!
|
|
|
|
st->codec.frame_rate = 25; |
|
|
|
st->codec.frame_rate = 25; |
|
|
|
st->codec.frame_rate_base = 1; |
|
|
|
st->codec.frame_rate_base = 1; |
|
|
|
|
|
|
|
*/ |
|
|
|
size -= (16+8*4+2+32+2*2); |
|
|
|
size -= (16+8*4+2+32+2*2); |
|
|
|
#if 0 |
|
|
|
#if 0 |
|
|
|
while (size >= 8) { |
|
|
|
while (size >= 8) { |
|
|
@ -878,7 +883,7 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
|
|
|
get_byte(pb); //frames_per_sample
|
|
|
|
get_byte(pb); //frames_per_sample
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
#ifdef DEBUG |
|
|
|
printf("Audio: damr_type=%c%c%c%c damr_size=%Ld damr_vendor=%c%c%c%c\n", |
|
|
|
printf("Audio: damr_type=%c%c%c%c damr_size=%d damr_vendor=%c%c%c%c\n", |
|
|
|
(damr_type >> 24) & 0xff, |
|
|
|
(damr_type >> 24) & 0xff, |
|
|
|
(damr_type >> 16) & 0xff, |
|
|
|
(damr_type >> 16) & 0xff, |
|
|
|
(damr_type >> 8) & 0xff, |
|
|
|
(damr_type >> 8) & 0xff, |
|
|
@ -898,9 +903,20 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
|
|
|
st->codec.bit_rate=0; /*It is not possible to tell this before we have
|
|
|
|
st->codec.bit_rate=0; /*It is not possible to tell this before we have
|
|
|
|
an audio frame and even then every frame can be different*/ |
|
|
|
an audio frame and even then every frame can be different*/ |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else if( st->codec.codec_tag == MKTAG( 'm', 'p', '4', 's' )) |
|
|
|
{ |
|
|
|
{ |
|
|
|
get_be16(pb); /* version */ |
|
|
|
//This is some stuff for the hint track, lets ignore it!
|
|
|
|
|
|
|
|
//Do some mp4 auto detect.
|
|
|
|
|
|
|
|
c->mp4=1; |
|
|
|
|
|
|
|
size-=(16); |
|
|
|
|
|
|
|
url_fskip(pb, size); /* The mp4s atom also contians a esds atom that we can skip*/ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if(size>=(16+20)) |
|
|
|
|
|
|
|
{//16 bytes read, reading atleast 20 more
|
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
|
|
|
|
printf("audio size=0x%X\n",size); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
uint16_t version = get_be16(pb); /* version */ |
|
|
|
get_be16(pb); /* revision level */ |
|
|
|
get_be16(pb); /* revision level */ |
|
|
|
get_be32(pb); /* vendor */ |
|
|
|
get_be32(pb); /* vendor */ |
|
|
|
|
|
|
|
|
|
|
@ -925,14 +941,51 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) |
|
|
|
default: |
|
|
|
default: |
|
|
|
; |
|
|
|
; |
|
|
|
} |
|
|
|
} |
|
|
|
get_be32(pb); /* samples per packet */ |
|
|
|
|
|
|
|
get_be32(pb); /* bytes per packet */ |
|
|
|
//Read QT version 1 fields. In version 0 theese dont exist
|
|
|
|
get_be32(pb); /* bytes per frame */ |
|
|
|
#ifdef DEBUG |
|
|
|
get_be32(pb); /* bytes per sample */ |
|
|
|
printf("version =%d mp4=%d\n",version,c->mp4); |
|
|
|
{ |
|
|
|
printf("size-(16+20+16)=%d\n",size-(16+20+16)); |
|
|
|
MOV_atom_t a = { format, url_ftell(pb), size - (16 + 20 + 16 + 8) }; |
|
|
|
#endif |
|
|
|
mov_read_default(c, pb, a); |
|
|
|
if((version==1) && size>=(16+20+16)) |
|
|
|
} |
|
|
|
{ |
|
|
|
|
|
|
|
get_be32(pb); /* samples per packet */ |
|
|
|
|
|
|
|
get_be32(pb); /* bytes per packet */ |
|
|
|
|
|
|
|
get_be32(pb); /* bytes per frame */ |
|
|
|
|
|
|
|
get_be32(pb); /* bytes per sample */ |
|
|
|
|
|
|
|
if(size>(16+20+16)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
//Optional, additional atom-based fields
|
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
|
|
|
|
printf("offest=0x%X, sizeleft=%d=0x%x,format=%c%c%c%c\n",(int)url_ftell(pb),size - (16 + 20 + 16 ),size - (16 + 20 + 16 ), |
|
|
|
|
|
|
|
(format >> 0) & 0xff, |
|
|
|
|
|
|
|
(format >> 8) & 0xff, |
|
|
|
|
|
|
|
(format >> 16) & 0xff, |
|
|
|
|
|
|
|
(format >> 24) & 0xff); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
MOV_atom_t a = { format, url_ftell(pb), size - (16 + 20 + 16 + 8) }; |
|
|
|
|
|
|
|
mov_read_default(c, pb, a); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
//We should be down to 0 bytes here, but lets make sure.
|
|
|
|
|
|
|
|
size-=(16+20); |
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
|
|
|
|
if(size>0) |
|
|
|
|
|
|
|
printf("skipping 0x%X bytes\n",size-(16+20)); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
url_fskip(pb, size); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
size-=16; |
|
|
|
|
|
|
|
//Unknown size, but lets do our best and skip the rest.
|
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
|
|
|
|
printf("Strange size, skipping 0x%X bytes\n",size); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
url_fskip(pb, size); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -1043,16 +1096,43 @@ printf("track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(st->codec.codec_type==CODEC_TYPE_VIDEO) |
|
|
|
#define MAX(a,b) a>b?a:b |
|
|
|
|
|
|
|
#define MIN(a,b) a>b?b:a |
|
|
|
|
|
|
|
/*The stsd atom which contain codec type sometimes comes after the stts so we cannot check for codec_type*/ |
|
|
|
|
|
|
|
if(duration>0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
//Find greatest common divisor to avoid overflow using the Euclidean Algorithm...
|
|
|
|
|
|
|
|
uint32_t max=MAX(duration,total_sample_count); |
|
|
|
|
|
|
|
uint32_t min=MIN(duration,total_sample_count); |
|
|
|
|
|
|
|
uint32_t spare=max%min; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while(spare!=0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
max=min; |
|
|
|
|
|
|
|
min=spare; |
|
|
|
|
|
|
|
spare=max%min; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
duration/=min; |
|
|
|
|
|
|
|
total_sample_count/=min; |
|
|
|
|
|
|
|
|
|
|
|
//Only support constant frame rate. But lets calculate the average. Needed by .mp4-files created with nec e606 3g phone.
|
|
|
|
//Only support constant frame rate. But lets calculate the average. Needed by .mp4-files created with nec e606 3g phone.
|
|
|
|
//Hmm, lets set base to 1
|
|
|
|
//To get better precision, we use the duration as frame_rate_base
|
|
|
|
st->codec.frame_rate_base=1; |
|
|
|
|
|
|
|
st->codec.frame_rate = st->codec.frame_rate_base * c->streams[c->total_streams]->time_scale * total_sample_count / duration; |
|
|
|
st->codec.frame_rate_base=duration; |
|
|
|
|
|
|
|
st->codec.frame_rate = c->streams[c->total_streams]->time_scale * total_sample_count; |
|
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
#ifdef DEBUG |
|
|
|
printf("VIDEO FRAME RATE average= %i (tot sample count= %i ,tot dur= %i)\n", st->codec.frame_rate,total_sample_count,duration); |
|
|
|
printf("FRAME RATE average (video or audio)= %f (tot sample count= %i ,tot dur= %i timescale=%d)\n", (float)st->codec.frame_rate/st->codec.frame_rate_base,total_sample_count,duration,c->streams[c->total_streams]->time_scale); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
st->codec.frame_rate_base = 1; |
|
|
|
|
|
|
|
st->codec.frame_rate = c->streams[c->total_streams]->time_scale; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#undef MAX |
|
|
|
|
|
|
|
#undef MIN |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1334,7 +1414,7 @@ static int mov_probe(AVProbeData *p) |
|
|
|
return AVPROBE_SCORE_MAX; |
|
|
|
return AVPROBE_SCORE_MAX; |
|
|
|
case MKTAG( 'f', 't', 'y', 'p' ): |
|
|
|
case MKTAG( 'f', 't', 'y', 'p' ): |
|
|
|
case MKTAG( 's', 'k', 'i', 'p' ): |
|
|
|
case MKTAG( 's', 'k', 'i', 'p' ): |
|
|
|
offset = to_be32(p->buf) + offset; |
|
|
|
offset = to_be32(p->buf+offset) + offset; |
|
|
|
break; |
|
|
|
break; |
|
|
|
default: |
|
|
|
default: |
|
|
|
/* unrecognized tag */ |
|
|
|
/* unrecognized tag */ |
|
|
|