libavformat/oggdec.c
Go to the documentation of this file.
00001 /*
00002  * Ogg bitstream support
00003  * Luca Barbato <lu_zero@gentoo.org>
00004  * Based on tcvp implementation
00005  */
00006 
00007 /*
00008     Copyright (C) 2005  Michael Ahlberg, Måns Rullgård
00009 
00010     Permission is hereby granted, free of charge, to any person
00011     obtaining a copy of this software and associated documentation
00012     files (the "Software"), to deal in the Software without
00013     restriction, including without limitation the rights to use, copy,
00014     modify, merge, publish, distribute, sublicense, and/or sell copies
00015     of the Software, and to permit persons to whom the Software is
00016     furnished to do so, subject to the following conditions:
00017 
00018     The above copyright notice and this permission notice shall be
00019     included in all copies or substantial portions of the Software.
00020 
00021     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00022     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00023     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00024     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
00025     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
00026     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00027     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00028     DEALINGS IN THE SOFTWARE.
00029  */
00030 
00031 
00032 #include <stdio.h>
00033 #include "oggdec.h"
00034 #include "avformat.h"
00035 #include "internal.h"
00036 #include "vorbiscomment.h"
00037 
00038 #define MAX_PAGE_SIZE 65307
00039 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
00040 
00041 static const struct ogg_codec * const ogg_codecs[] = {
00042     &ff_skeleton_codec,
00043     &ff_dirac_codec,
00044     &ff_speex_codec,
00045     &ff_vorbis_codec,
00046     &ff_theora_codec,
00047     &ff_flac_codec,
00048     &ff_celt_codec,
00049     &ff_old_dirac_codec,
00050     &ff_old_flac_codec,
00051     &ff_ogm_video_codec,
00052     &ff_ogm_audio_codec,
00053     &ff_ogm_text_codec,
00054     &ff_ogm_old_codec,
00055     NULL
00056 };
00057 
00058 //FIXME We could avoid some structure duplication
00059 static int ogg_save(AVFormatContext *s)
00060 {
00061     struct ogg *ogg = s->priv_data;
00062     struct ogg_state *ost =
00063         av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
00064     int i;
00065     ost->pos = avio_tell (s->pb);
00066     ost->curidx = ogg->curidx;
00067     ost->next = ogg->state;
00068     ost->nstreams = ogg->nstreams;
00069     memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
00070 
00071     for (i = 0; i < ogg->nstreams; i++){
00072         struct ogg_stream *os = ogg->streams + i;
00073         os->buf = av_malloc (os->bufsize);
00074         memset (os->buf, 0, os->bufsize);
00075         memcpy (os->buf, ost->streams[i].buf, os->bufpos);
00076     }
00077 
00078     ogg->state = ost;
00079 
00080     return 0;
00081 }
00082 
00083 static int ogg_restore(AVFormatContext *s, int discard)
00084 {
00085     struct ogg *ogg = s->priv_data;
00086     AVIOContext *bc = s->pb;
00087     struct ogg_state *ost = ogg->state;
00088     int i;
00089 
00090     if (!ost)
00091         return 0;
00092 
00093     ogg->state = ost->next;
00094 
00095     if (!discard){
00096         struct ogg_stream *old_streams = ogg->streams;
00097 
00098         for (i = 0; i < ogg->nstreams; i++)
00099             av_free (ogg->streams[i].buf);
00100 
00101         avio_seek (bc, ost->pos, SEEK_SET);
00102         ogg->curidx = ost->curidx;
00103         ogg->nstreams = ost->nstreams;
00104         ogg->streams = av_realloc (ogg->streams,
00105                                    ogg->nstreams * sizeof (*ogg->streams));
00106 
00107         if (ogg->streams) {
00108             memcpy(ogg->streams, ost->streams,
00109                    ost->nstreams * sizeof(*ogg->streams));
00110         } else {
00111             av_free(old_streams);
00112             ogg->nstreams = 0;
00113         }
00114     }
00115 
00116     av_free (ost);
00117 
00118     return 0;
00119 }
00120 
00121 static int ogg_reset(struct ogg *ogg)
00122 {
00123     int i;
00124 
00125     for (i = 0; i < ogg->nstreams; i++){
00126         struct ogg_stream *os = ogg->streams + i;
00127         os->bufpos = 0;
00128         os->pstart = 0;
00129         os->psize = 0;
00130         os->granule = -1;
00131         os->lastpts = AV_NOPTS_VALUE;
00132         os->lastdts = AV_NOPTS_VALUE;
00133         os->sync_pos = -1;
00134         os->page_pos = 0;
00135         os->nsegs = 0;
00136         os->segp = 0;
00137         os->incomplete = 0;
00138     }
00139 
00140     ogg->curidx = -1;
00141 
00142     return 0;
00143 }
00144 
00145 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
00146 {
00147     int i;
00148 
00149     for (i = 0; ogg_codecs[i]; i++)
00150         if (size >= ogg_codecs[i]->magicsize &&
00151             !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
00152             return ogg_codecs[i];
00153 
00154     return NULL;
00155 }
00156 
00157 static int ogg_new_stream(AVFormatContext *s, uint32_t serial, int new_avstream)
00158 {
00159 
00160     struct ogg *ogg = s->priv_data;
00161     int idx = ogg->nstreams++;
00162     AVStream *st;
00163     struct ogg_stream *os;
00164 
00165     ogg->streams = av_realloc (ogg->streams,
00166                                ogg->nstreams * sizeof (*ogg->streams));
00167     memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
00168     os = ogg->streams + idx;
00169     os->serial = serial;
00170     os->bufsize = DECODER_BUFFER_SIZE;
00171     os->buf = av_malloc(os->bufsize);
00172     os->header = -1;
00173 
00174     if (new_avstream) {
00175         st = avformat_new_stream(s, NULL);
00176         if (!st)
00177             return AVERROR(ENOMEM);
00178 
00179         st->id = idx;
00180         avpriv_set_pts_info(st, 64, 1, 1000000);
00181     }
00182 
00183     return idx;
00184 }
00185 
00186 static int ogg_new_buf(struct ogg *ogg, int idx)
00187 {
00188     struct ogg_stream *os = ogg->streams + idx;
00189     uint8_t *nb = av_malloc(os->bufsize);
00190     int size = os->bufpos - os->pstart;
00191     if(os->buf){
00192         memcpy(nb, os->buf + os->pstart, size);
00193         av_free(os->buf);
00194     }
00195     os->buf = nb;
00196     os->bufpos = size;
00197     os->pstart = 0;
00198 
00199     return 0;
00200 }
00201 
00202 static int ogg_read_page(AVFormatContext *s, int *str)
00203 {
00204     AVIOContext *bc = s->pb;
00205     struct ogg *ogg = s->priv_data;
00206     struct ogg_stream *os;
00207     int ret, i = 0;
00208     int flags, nsegs;
00209     uint64_t gp;
00210     uint32_t serial;
00211     int size, idx;
00212     uint8_t sync[4];
00213     int sp = 0;
00214 
00215     ret = avio_read(bc, sync, 4);
00216     if (ret < 4)
00217         return ret < 0 ? ret : AVERROR_EOF;
00218 
00219     do{
00220         int c;
00221 
00222         if (sync[sp & 3] == 'O' &&
00223             sync[(sp + 1) & 3] == 'g' &&
00224             sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
00225             break;
00226 
00227         c = avio_r8(bc);
00228         if (bc->eof_reached)
00229             return AVERROR_EOF;
00230         sync[sp++ & 3] = c;
00231     }while (i++ < MAX_PAGE_SIZE);
00232 
00233     if (i >= MAX_PAGE_SIZE){
00234         av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
00235         return AVERROR_INVALIDDATA;
00236     }
00237 
00238     if (avio_r8(bc) != 0)      /* version */
00239         return AVERROR_INVALIDDATA;
00240 
00241     flags = avio_r8(bc);
00242     gp = avio_rl64 (bc);
00243     serial = avio_rl32 (bc);
00244     avio_skip(bc, 8); /* seq, crc */
00245     nsegs = avio_r8(bc);
00246 
00247     idx = ogg_find_stream (ogg, serial);
00248     if (idx < 0){
00249         if (ogg->headers) {
00250             int n;
00251 
00252             for (n = 0; n < ogg->nstreams; n++) {
00253                 av_freep(&ogg->streams[n].buf);
00254                 if (!ogg->state || ogg->state->streams[n].private != ogg->streams[n].private)
00255                     av_freep(&ogg->streams[n].private);
00256             }
00257             ogg->curidx   = -1;
00258             ogg->nstreams = 0;
00259             idx = ogg_new_stream(s, serial, 0);
00260         } else {
00261             idx = ogg_new_stream(s, serial, 1);
00262         }
00263         if (idx < 0)
00264             return idx;
00265     }
00266 
00267     os = ogg->streams + idx;
00268     os->page_pos = avio_tell(bc) - 27;
00269 
00270     if(os->psize > 0)
00271         ogg_new_buf(ogg, idx);
00272 
00273     ret = avio_read(bc, os->segments, nsegs);
00274     if (ret < nsegs)
00275         return ret < 0 ? ret : AVERROR_EOF;
00276 
00277     os->nsegs = nsegs;
00278     os->segp = 0;
00279 
00280     size = 0;
00281     for (i = 0; i < nsegs; i++)
00282         size += os->segments[i];
00283 
00284     if (flags & OGG_FLAG_CONT || os->incomplete){
00285         if (!os->psize){
00286             while (os->segp < os->nsegs){
00287                 int seg = os->segments[os->segp++];
00288                 os->pstart += seg;
00289                 if (seg < 255)
00290                     break;
00291             }
00292             os->sync_pos = os->page_pos;
00293         }
00294     }else{
00295         os->psize = 0;
00296         os->sync_pos = os->page_pos;
00297     }
00298 
00299     if (os->bufsize - os->bufpos < size){
00300         uint8_t *nb = av_malloc (os->bufsize *= 2);
00301         memcpy (nb, os->buf, os->bufpos);
00302         av_free (os->buf);
00303         os->buf = nb;
00304     }
00305 
00306     ret = avio_read(bc, os->buf + os->bufpos, size);
00307     if (ret < size)
00308         return ret < 0 ? ret : AVERROR_EOF;
00309 
00310     os->bufpos += size;
00311     os->granule = gp;
00312     os->flags = flags;
00313 
00314     if (str)
00315         *str = idx;
00316 
00317     return 0;
00318 }
00319 
00320 static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize,
00321                       int64_t *fpos)
00322 {
00323     struct ogg *ogg = s->priv_data;
00324     int idx, i, ret;
00325     struct ogg_stream *os;
00326     int complete = 0;
00327     int segp = 0, psize = 0;
00328 
00329     av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx);
00330 
00331     do{
00332         idx = ogg->curidx;
00333 
00334         while (idx < 0){
00335             ret = ogg_read_page(s, &idx);
00336             if (ret < 0)
00337                 return ret;
00338         }
00339 
00340         os = ogg->streams + idx;
00341 
00342         av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
00343                 idx, os->pstart, os->psize, os->segp, os->nsegs);
00344 
00345         if (!os->codec){
00346             if (os->header < 0){
00347                 os->codec = ogg_find_codec (os->buf, os->bufpos);
00348                 if (!os->codec){
00349                     av_log(s, AV_LOG_WARNING, "Codec not found\n");
00350                     os->header = 0;
00351                     return 0;
00352                 }
00353             }else{
00354                 return 0;
00355             }
00356         }
00357 
00358         segp = os->segp;
00359         psize = os->psize;
00360 
00361         while (os->segp < os->nsegs){
00362             int ss = os->segments[os->segp++];
00363             os->psize += ss;
00364             if (ss < 255){
00365                 complete = 1;
00366                 break;
00367             }
00368         }
00369 
00370         if (!complete && os->segp == os->nsegs){
00371             ogg->curidx = -1;
00372             os->incomplete = 1;
00373         }
00374     }while (!complete);
00375 
00376     av_dlog(s, "ogg_packet: idx %i, frame size %i, start %i\n",
00377             idx, os->psize, os->pstart);
00378 
00379     if (os->granule == -1)
00380         av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos);
00381 
00382     ogg->curidx = idx;
00383     os->incomplete = 0;
00384 
00385     if (os->header) {
00386         os->header = os->codec->header (s, idx);
00387         if (!os->header){
00388             os->segp = segp;
00389             os->psize = psize;
00390 
00391             // We have reached the first non-header packet in this stream.
00392             // Unfortunately more header packets may still follow for others,
00393             // but if we continue with header parsing we may lose data packets.
00394             ogg->headers = 1;
00395 
00396             // Update the header state for all streams and
00397             // compute the data_offset.
00398             if (!s->data_offset)
00399                 s->data_offset = os->sync_pos;
00400             for (i = 0; i < ogg->nstreams; i++) {
00401                 struct ogg_stream *cur_os = ogg->streams + i;
00402 
00403                 // if we have a partial non-header packet, its start is
00404                 // obviously at or after the data start
00405                 if (cur_os->incomplete)
00406                     s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
00407             }
00408         }else{
00409             os->pstart += os->psize;
00410             os->psize = 0;
00411         }
00412     } else {
00413         os->pflags = 0;
00414         os->pduration = 0;
00415         if (os->codec && os->codec->packet)
00416             os->codec->packet (s, idx);
00417         if (str)
00418             *str = idx;
00419         if (dstart)
00420             *dstart = os->pstart;
00421         if (dsize)
00422             *dsize = os->psize;
00423         if (fpos)
00424             *fpos = os->sync_pos;
00425         os->pstart += os->psize;
00426         os->psize = 0;
00427         os->sync_pos = os->page_pos;
00428     }
00429 
00430     // determine whether there are more complete packets in this page
00431     // if not, the page's granule will apply to this packet
00432     os->page_end = 1;
00433     for (i = os->segp; i < os->nsegs; i++)
00434         if (os->segments[i] < 255) {
00435             os->page_end = 0;
00436             break;
00437         }
00438 
00439     if (os->segp == os->nsegs)
00440         ogg->curidx = -1;
00441 
00442     return 0;
00443 }
00444 
00445 static int ogg_get_headers(AVFormatContext *s)
00446 {
00447     struct ogg *ogg = s->priv_data;
00448     int ret;
00449 
00450     do{
00451         ret = ogg_packet(s, NULL, NULL, NULL, NULL);
00452         if (ret < 0)
00453             return ret;
00454     }while (!ogg->headers);
00455 
00456     av_dlog(s, "found headers\n");
00457 
00458     return 0;
00459 }
00460 
00461 static int ogg_get_length(AVFormatContext *s)
00462 {
00463     struct ogg *ogg = s->priv_data;
00464     int i;
00465     int64_t size, end;
00466 
00467     if(!s->pb->seekable)
00468         return 0;
00469 
00470 // already set
00471     if (s->duration != AV_NOPTS_VALUE)
00472         return 0;
00473 
00474     size = avio_size(s->pb);
00475     if(size < 0)
00476         return 0;
00477     end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
00478 
00479     ogg_save (s);
00480     avio_seek (s->pb, end, SEEK_SET);
00481 
00482     while (!ogg_read_page (s, &i)){
00483         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
00484             ogg->streams[i].codec) {
00485             s->streams[i]->duration =
00486                 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
00487             if (s->streams[i]->start_time != AV_NOPTS_VALUE)
00488                 s->streams[i]->duration -= s->streams[i]->start_time;
00489         }
00490     }
00491 
00492     ogg_restore (s, 0);
00493 
00494     return 0;
00495 }
00496 
00497 static int ogg_read_header(AVFormatContext *s, AVFormatParameters *ap)
00498 {
00499     struct ogg *ogg = s->priv_data;
00500     int ret, i;
00501     ogg->curidx = -1;
00502     //linear headers seek from start
00503     ret = ogg_get_headers(s);
00504     if (ret < 0)
00505         return ret;
00506 
00507     for (i = 0; i < ogg->nstreams; i++)
00508         if (ogg->streams[i].header < 0)
00509             ogg->streams[i].codec = NULL;
00510 
00511     //linear granulepos seek from end
00512     ogg_get_length (s);
00513 
00514     //fill the extradata in the per codec callbacks
00515     return 0;
00516 }
00517 
00518 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
00519 {
00520     struct ogg *ogg = s->priv_data;
00521     struct ogg_stream *os = ogg->streams + idx;
00522     int64_t pts = AV_NOPTS_VALUE;
00523 
00524     if (dts)
00525         *dts = AV_NOPTS_VALUE;
00526 
00527     if (os->lastpts != AV_NOPTS_VALUE) {
00528         pts = os->lastpts;
00529         os->lastpts = AV_NOPTS_VALUE;
00530     }
00531     if (os->lastdts != AV_NOPTS_VALUE) {
00532         if (dts)
00533             *dts = os->lastdts;
00534         os->lastdts = AV_NOPTS_VALUE;
00535     }
00536     if (os->page_end) {
00537         if (os->granule != -1LL) {
00538             if (os->codec && os->codec->granule_is_start)
00539                 pts = ogg_gptopts(s, idx, os->granule, dts);
00540             else
00541                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
00542             os->granule = -1LL;
00543         }
00544     }
00545     return pts;
00546 }
00547 
00548 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
00549 {
00550     struct ogg *ogg;
00551     struct ogg_stream *os;
00552     int idx = -1, ret;
00553     int pstart, psize;
00554     int64_t fpos, pts, dts;
00555 
00556     //Get an ogg packet
00557 retry:
00558     do{
00559         ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
00560         if (ret < 0)
00561             return ret;
00562     }while (idx < 0 || !s->streams[idx]);
00563 
00564     ogg = s->priv_data;
00565     os = ogg->streams + idx;
00566 
00567     // pflags might not be set until after this
00568     pts = ogg_calc_pts(s, idx, &dts);
00569 
00570     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
00571         goto retry;
00572     os->keyframe_seek = 0;
00573 
00574     //Alloc a pkt
00575     ret = av_new_packet(pkt, psize);
00576     if (ret < 0)
00577         return ret;
00578     pkt->stream_index = idx;
00579     memcpy (pkt->data, os->buf + pstart, psize);
00580 
00581     pkt->pts = pts;
00582     pkt->dts = dts;
00583     pkt->flags = os->pflags;
00584     pkt->duration = os->pduration;
00585     pkt->pos = fpos;
00586 
00587     return psize;
00588 }
00589 
00590 static int ogg_read_close(AVFormatContext *s)
00591 {
00592     struct ogg *ogg = s->priv_data;
00593     int i;
00594 
00595     for (i = 0; i < ogg->nstreams; i++){
00596         av_free (ogg->streams[i].buf);
00597         av_free (ogg->streams[i].private);
00598     }
00599     av_free (ogg->streams);
00600     return 0;
00601 }
00602 
00603 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
00604                                   int64_t *pos_arg, int64_t pos_limit)
00605 {
00606     struct ogg *ogg = s->priv_data;
00607     AVIOContext *bc = s->pb;
00608     int64_t pts = AV_NOPTS_VALUE;
00609     int i = -1;
00610     avio_seek(bc, *pos_arg, SEEK_SET);
00611     ogg_reset(ogg);
00612 
00613     while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
00614         if (i == stream_index) {
00615             struct ogg_stream *os = ogg->streams + stream_index;
00616             pts = ogg_calc_pts(s, i, NULL);
00617             if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
00618                 pts = AV_NOPTS_VALUE;
00619         }
00620         if (pts != AV_NOPTS_VALUE)
00621             break;
00622     }
00623     ogg_reset(ogg);
00624     return pts;
00625 }
00626 
00627 static int ogg_read_seek(AVFormatContext *s, int stream_index,
00628                          int64_t timestamp, int flags)
00629 {
00630     struct ogg *ogg = s->priv_data;
00631     struct ogg_stream *os = ogg->streams + stream_index;
00632     int ret;
00633 
00634     // Try seeking to a keyframe first. If this fails (very possible),
00635     // av_seek_frame will fall back to ignoring keyframes
00636     if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
00637         && !(flags & AVSEEK_FLAG_ANY))
00638         os->keyframe_seek = 1;
00639 
00640     ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
00641     os = ogg->streams + stream_index;
00642     if (ret < 0)
00643         os->keyframe_seek = 0;
00644     return ret;
00645 }
00646 
00647 static int ogg_probe(AVProbeData *p)
00648 {
00649     if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
00650         return AVPROBE_SCORE_MAX;
00651     return 0;
00652 }
00653 
00654 AVInputFormat ff_ogg_demuxer = {
00655     .name           = "ogg",
00656     .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
00657     .priv_data_size = sizeof(struct ogg),
00658     .read_probe     = ogg_probe,
00659     .read_header    = ogg_read_header,
00660     .read_packet    = ogg_read_packet,
00661     .read_close     = ogg_read_close,
00662     .read_seek      = ogg_read_seek,
00663     .read_timestamp = ogg_read_timestamp,
00664     .extensions     = "ogg",
00665     .flags          = AVFMT_GENERIC_INDEX,
00666 };