changeset 147:2f924727fd96 libavformat

* missing part of the 3gp patch by Johannes Carlsson
author kabi
date Fri, 06 Jun 2003 11:46:25 +0000
parents b9703b3c10b6
children 31d7c9a8678c
files mov.c
diffstat 1 files changed, 100 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/mov.c	Thu Jun 05 14:30:52 2003 +0000
+++ b/mov.c	Fri Jun 06 11:46:25 2003 +0000
@@ -59,6 +59,10 @@
 /* in case you can't read a file, try commenting */
 #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 */
 /* so we first list them as this, then clean up the list of streams we give back, */
 /* getting rid of these */
@@ -768,9 +772,10 @@
 	    st->codec.bits_per_sample = get_be16(pb); /* depth */
             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_base = 1;
-
+*/
 	    size -= (16+8*4+2+32+2*2);
 #if 0
 	    while (size >= 8) {
@@ -878,7 +883,7 @@
                get_byte(pb); //frames_per_sample
 
 #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 >> 16) & 0xff,
                        (damr_type >> 8) & 0xff,
@@ -890,7 +895,7 @@
                        (damr_vendor >> 0) & 0xff
 		       );
 #endif
-                
+
                st->time_length=0;//Not possible to get from this info, must count number of AMR frames
                st->codec.sample_rate=8000;
                st->codec.channels=1;
@@ -898,9 +903,20 @@
                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*/
 	    }
-	    else
-	    {
-                get_be16(pb); /* version */
+            else if( st->codec.codec_tag == MKTAG( 'm', 'p', '4', 's' ))
+            {
+                //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_be32(pb); /* vendor */
 
@@ -925,14 +941,51 @@
 	        default:
                     ;
 	        }
-	        get_be32(pb); /* samples per packet */
-	        get_be32(pb); /* bytes per packet */
-                get_be32(pb); /* bytes per frame */
-                get_be32(pb); /* bytes per sample */
-	        {
-		    MOV_atom_t a = { format, url_ftell(pb), size - (16 + 20 + 16 + 8) };
-		    mov_read_default(c, pb, a);
-	        }
+
+                //Read QT version 1 fields. In version 0 theese dont exist
+#ifdef DEBUG
+                printf("version =%d mp4=%d\n",version,c->mp4);
+                printf("size-(16+20+16)=%d\n",size-(16+20+16));
+#endif
+                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 @@
 #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.
-        //Hmm, lets set base to 1
-        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;
+        //To get better precision, we use the duration as frame_rate_base
+
+        st->codec.frame_rate_base=duration;
+        st->codec.frame_rate = c->streams[c->total_streams]->time_scale * total_sample_count;
+
 #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
     }
+    else
+    {
+        st->codec.frame_rate_base = 1;
+        st->codec.frame_rate = c->streams[c->total_streams]->time_scale;
+    }
+#undef MAX
+#undef MIN
     return 0;
 }
 
@@ -1334,7 +1414,7 @@
             return AVPROBE_SCORE_MAX;
         case MKTAG( 'f', 't', 'y', 'p' ):
         case MKTAG( 's', 'k', 'i', 'p' ):
-            offset = to_be32(p->buf) + offset;
+            offset = to_be32(p->buf+offset) + offset;
             break;
         default:
             /* unrecognized tag */