]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/ogg2.c
allocate 32 extra bytes at the end of the probe buffer and remove most probe buf_size...
[ffmpeg] / libavformat / ogg2.c
index 9cb3d8ca62458020a3f4466c040b4cdbec54610f..a3739556e4412b66596a16be5ae0b2b1f8183256 100644 (file)
@@ -65,10 +65,10 @@ ogg_write_trailer (AVFormatContext * avfcontext)
 }
 
 
-static AVOutputFormat ogg_oformat = {
+AVOutputFormat ogg_muxer = {
     "ogg",
-    "Ogg Vorbis",
-    "audio/x-vorbis",
+    "Ogg format",
+    "application/ogg",
     "ogg",
     sizeof (OggContext),
     CODEC_ID_VORBIS,
@@ -90,6 +90,7 @@ ogg_save (AVFormatContext * s)
     ost->pos = url_ftell (&s->pb);;
     ost->curidx = ogg->curidx;
     ost->next = ogg->state;
+    ost->nstreams = ogg->nstreams;
     memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
 
     for (i = 0; i < ogg->nstreams; i++){
@@ -123,8 +124,9 @@ ogg_restore (AVFormatContext * s, int discard)
 
         url_fseek (bc, ost->pos, SEEK_SET);
         ogg->curidx = ost->curidx;
-        memcpy (ogg->streams, ost->streams,
-        ogg->nstreams * sizeof (*ogg->streams));
+        ogg->nstreams = ost->nstreams;
+        memcpy(ogg->streams, ost->streams,
+               ost->nstreams * sizeof(*ogg->streams));
     }
 
     av_free (ost);
@@ -193,6 +195,7 @@ ogg_new_stream (AVFormatContext * s, uint32_t serial)
     os = ogg->streams + idx;
     os->serial = serial;
     os->bufsize = DECODER_BUFFER_SIZE;
+    os->buf = av_malloc(os->bufsize);
     os->header = -1;
 
     st = av_new_stream (s, idx);
@@ -200,7 +203,6 @@ ogg_new_stream (AVFormatContext * s, uint32_t serial)
         return AVERROR_NOMEM;
 
     av_set_pts_info(st, 64, 1, 1000000);
-    st->start_time = 0;
 
     return idx;
 }
@@ -209,7 +211,7 @@ static int
 ogg_new_buf(ogg_t *ogg, int idx)
 {
     ogg_stream_t *os = ogg->streams + idx;
-    u_char *nb = av_malloc(os->bufsize);
+    uint8_t *nb = av_malloc(os->bufsize);
     int size = os->bufpos - os->pstart;
     if(os->buf){
         memcpy(nb, os->buf + os->pstart, size);
@@ -235,7 +237,7 @@ ogg_read_page (AVFormatContext * s, int *str)
     uint32_t seq;
     uint32_t crc;
     int size, idx;
-    char sync[4];
+    uint8_t sync[4];
     int sp = 0;
 
     if (get_buffer (bc, sync, 4) < 4)
@@ -279,7 +281,7 @@ ogg_read_page (AVFormatContext * s, int *str)
 
     os = ogg->streams + idx;
 
-    if(os->segp == os->nsegs)
+    if(os->psize > 0)
         ogg_new_buf(ogg, idx);
 
     if (get_buffer (bc, os->segments, nsegs) < nsegs)
@@ -307,7 +309,6 @@ ogg_read_page (AVFormatContext * s, int *str)
 
     if (os->bufsize - os->bufpos < size){
         uint8_t *nb = av_malloc (os->bufsize *= 2);
-        memset (nb, 0, os->bufsize);
         memcpy (nb, os->buf, os->bufpos);
         av_free (os->buf);
         os->buf = nb;
@@ -483,7 +484,8 @@ ogg_get_length (AVFormatContext * s)
     url_fseek (&s->pb, end, SEEK_SET);
 
     while (!ogg_read_page (s, &i)){
-        if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0)
+        if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
+            ogg->streams[i].codec)
             idx = i;
     }
 
@@ -494,6 +496,16 @@ ogg_get_length (AVFormatContext * s)
 
     ogg->size = size;
     ogg_restore (s, 0);
+    ogg_save (s);
+    while (!ogg_read_page (s, &i)) {
+        if (i == idx && ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0)
+            break;
+    }
+    if (i == idx) {
+        s->streams[idx]->start_time = ogg_gptopts (s, idx, ogg->streams[idx].granule);
+        s->streams[idx]->duration -= s->streams[idx]->start_time;
+    }
+    ogg_restore (s, 0);
 
     return 0;
 }
@@ -571,12 +583,14 @@ ogg_read_seek (AVFormatContext * s, int stream_index, int64_t target_ts,
     ogg_t *ogg = s->priv_data;
     ByteIOContext *bc = &s->pb;
     uint64_t min = 0, max = ogg->size;
-    uint64_t tmin = 0, tmax = st->duration;
+    uint64_t tmin = st->start_time, tmax = st->start_time + st->duration;
     int64_t pts = AV_NOPTS_VALUE;
 
     ogg_save (s);
 
-    while (min <= max){
+    if ((uint64_t)target_ts < tmin || target_ts < 0)
+        target_ts = tmin;
+    while (min <= max && tmin < tmax){
         uint64_t p = min + (max - min) * (target_ts - tmin) / (tmax - tmin);
         int i = -1;
 
@@ -594,19 +608,35 @@ ogg_read_seek (AVFormatContext * s, int stream_index, int64_t target_ts,
         pts = ogg_gptopts (s, i, ogg->streams[i].granule);
         p = url_ftell (bc);
 
-        if (ABS (pts - target_ts) * st->time_base.num < st->time_base.den)
+        if (FFABS (pts - target_ts) * st->time_base.num < st->time_base.den)
             break;
 
         if (pts > target_ts){
+            if (max == p && tmax == pts) {
+                // probably our tmin is wrong, causing us to always end up too late in the file
+                tmin = (target_ts + tmin + 1) / 2;
+                if (tmin == target_ts) {
+                    url_fseek(bc, min, SEEK_SET);
+                    break;
+                }
+            }
             max = p;
             tmax = pts;
         }else{
+            if (min == p && tmin == pts) {
+                // probably our tmax is wrong, causing us to always end up too early in the file
+                tmax = (target_ts + tmax) / 2;
+                if (tmax == target_ts) {
+                    url_fseek(bc, max, SEEK_SET);
+                    break;
+                }
+            }
             min = p;
             tmin = pts;
         }
     }
 
-    if (ABS (pts - target_ts) * st->time_base.num < st->time_base.den){
+    if (FFABS (pts - target_ts) * st->time_base.num < st->time_base.den){
         ogg_restore (s, 1);
         ogg_reset (ogg);
     }else{
@@ -614,7 +644,8 @@ ogg_read_seek (AVFormatContext * s, int stream_index, int64_t target_ts,
         pts = AV_NOPTS_VALUE;
     }
 
-    return pts;
+    av_update_cur_dts(s, st, pts);
+    return 0;
 
 #if 0
     //later...
@@ -645,8 +676,6 @@ ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
 
 static int ogg_probe(AVProbeData *p)
 {
-    if (p->buf_size < 6)
-        return 0;
     if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
         p->buf[2] == 'g' && p->buf[3] == 'S' &&
         p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
@@ -655,7 +684,7 @@ static int ogg_probe(AVProbeData *p)
         return 0;
 }
 
-static AVInputFormat ogg_iformat = {
+AVInputFormat ogg_demuxer = {
     "ogg",
     "Ogg",
     sizeof (ogg_t),
@@ -667,13 +696,3 @@ static AVInputFormat ogg_iformat = {
 // ogg_read_timestamp,
     .extensions = "ogg",
 };
-
-int
-ogg_init (void)
-{
-#if 0 // CONFIG_MUXERS
-    av_register_output_format (&ogg_oformat);
-#endif
-    av_register_input_format (&ogg_iformat);
-    return 0;
-}