Ticket #892: ogg_get_length.patch

File ogg_get_length.patch, 2.8 KB (added by tstarling@…, 19 years ago)

Patch against r10293

  • libavformat/ogg2.c

     
    466466ogg_get_length (AVFormatContext * s)
    467467{
    468468    ogg_t *ogg = s->priv_data;
    469     int idx = -1, i;
    470     offset_t size, end;
     469    int i, streams_found;
     470    offset_t size, search_start, search_end;
     471        int64_t duration;
    471472
    472473    if(s->pb.is_streamed)
    473474        return 0;
     
    479480    size = url_fsize(&s->pb);
    480481    if(size < 0)
    481482        return 0;
    482     end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: size;
     483    search_start = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: size;
     484        search_end = size;
    483485
    484486    ogg_save (s);
    485     url_fseek (&s->pb, end, SEEK_SET);
    486487
    487     while (!ogg_read_page (s, &i)){
    488         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
    489             ogg->streams[i].codec)
    490             idx = i;
    491     }
     488        /* Seek back from the end of the file until we find the duration of all of the streams */
     489        streams_found = 0;
     490        while (streams_found < ogg->nstreams && search_start > 0) {
     491                url_fseek (&s->pb, search_start, SEEK_SET);
     492                while (!ogg_read_page (s, &i) && url_ftell (&s->pb) < search_end) {
     493                        if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
     494                                ogg->streams[i].codec)
     495                        {
     496                                duration = ogg_gptopts (s, i, ogg->streams[i].granule);
     497                                if (s->streams[i]->duration == AV_NOPTS_VALUE) {
     498                                        s->streams[i]->duration = duration;
     499                                        streams_found++;
     500                                } else if (duration > s->streams[i]->duration) {
     501                                        s->streams[i]->duration = duration;
     502                                }
     503                        }
     504                }
     505                search_start -= MAX_PAGE_SIZE;
     506                search_end -= MAX_PAGE_SIZE;
     507        }
    492508
    493     if (idx != -1){
    494         s->streams[idx]->duration =
    495             ogg_gptopts (s, idx, ogg->streams[idx].granule);
    496     }
     509    ogg->size = size;
    497510
    498     ogg->size = size;
     511        /* Go back to the start and find the start time for each stream */
    499512    ogg_restore (s, 0);
    500513    ogg_save (s);
    501     while (!ogg_read_page (s, &i)) {
    502         if (i == idx && ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0)
    503             break;
    504     }
    505     if (i == idx) {
    506         s->streams[idx]->start_time = ogg_gptopts (s, idx, ogg->streams[idx].granule);
    507         s->streams[idx]->duration -= s->streams[idx]->start_time;
    508     }
     514        streams_found = 0;
     515        /* Reset the start time to AV_NOPTS_VALUE, just in case it isn't already */
     516        for (i = 0; i < ogg->nstreams; i++) {
     517                s->streams[i]->start_time = AV_NOPTS_VALUE;
     518        }
     519    while (!ogg_read_page (s, &i) && streams_found < ogg->nstreams) {
     520                if (s->streams[i]->start_time == AV_NOPTS_VALUE && ogg->streams[i].granule != -1) {
     521                        streams_found++;
     522                        s->streams[i]->start_time = ogg_gptopts (s, i, ogg->streams[i].granule);
     523            s->streams[i]->duration -= s->streams[i]->start_time;
     524                }
     525        }
    509526    ogg_restore (s, 0);
    510527
    511528    return 0;