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_mallocz (os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
00074         memcpy (os->buf, ost->streams[i].buf, os->bufpos);
00075     }
00076 
00077     ogg->state = ost;
00078 
00079     return 0;
00080 }
00081 
00082 static int ogg_restore(AVFormatContext *s, int discard)
00083 {
00084     struct ogg *ogg = s->priv_data;
00085     AVIOContext *bc = s->pb;
00086     struct ogg_state *ost = ogg->state;
00087     int i;
00088 
00089     if (!ost)
00090         return 0;
00091 
00092     ogg->state = ost->next;
00093 
00094     if (!discard){
00095         struct ogg_stream *old_streams = ogg->streams;
00096 
00097         for (i = 0; i < ogg->nstreams; i++)
00098             av_free (ogg->streams[i].buf);
00099 
00100         avio_seek (bc, ost->pos, SEEK_SET);
00101         ogg->curidx = ost->curidx;
00102         ogg->nstreams = ost->nstreams;
00103         ogg->streams = av_realloc (ogg->streams,
00104                                    ogg->nstreams * sizeof (*ogg->streams));
00105 
00106         if (ogg->streams) {
00107             memcpy(ogg->streams, ost->streams,
00108                    ost->nstreams * sizeof(*ogg->streams));
00109         } else {
00110             av_free(old_streams);
00111             ogg->nstreams = 0;
00112         }
00113     }
00114 
00115     av_free (ost);
00116 
00117     return 0;
00118 }
00119 
00120 static int ogg_reset(struct ogg *ogg)
00121 {
00122     int i;
00123 
00124     for (i = 0; i < ogg->nstreams; i++){
00125         struct ogg_stream *os = ogg->streams + i;
00126         os->bufpos = 0;
00127         os->pstart = 0;
00128         os->psize = 0;
00129         os->granule = -1;
00130         os->lastpts = AV_NOPTS_VALUE;
00131         os->lastdts = AV_NOPTS_VALUE;
00132         os->sync_pos = -1;
00133         os->page_pos = 0;
00134         os->nsegs = 0;
00135         os->segp = 0;
00136         os->incomplete = 0;
00137     }
00138 
00139     ogg->curidx = -1;
00140 
00141     return 0;
00142 }
00143 
00144 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
00145 {
00146     int i;
00147 
00148     for (i = 0; ogg_codecs[i]; i++)
00149         if (size >= ogg_codecs[i]->magicsize &&
00150             !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
00151             return ogg_codecs[i];
00152 
00153     return NULL;
00154 }
00155 
00156 static int ogg_new_stream(AVFormatContext *s, uint32_t serial, int new_avstream)
00157 {
00158 
00159     struct ogg *ogg = s->priv_data;
00160     int idx = ogg->nstreams++;
00161     AVStream *st;
00162     struct ogg_stream *os;
00163 
00164     os = av_realloc (ogg->streams, ogg->nstreams * sizeof (*ogg->streams));
00165 
00166     if (!os)
00167         return AVERROR(ENOMEM);
00168 
00169     ogg->streams = os;
00170 
00171     memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
00172     os = ogg->streams + idx;
00173     os->serial = serial;
00174     os->bufsize = DECODER_BUFFER_SIZE;
00175     os->buf = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
00176     os->header = -1;
00177 
00178     if (new_avstream) {
00179         st = avformat_new_stream(s, NULL);
00180         if (!st)
00181             return AVERROR(ENOMEM);
00182 
00183         st->id = idx;
00184         avpriv_set_pts_info(st, 64, 1, 1000000);
00185     }
00186 
00187     return idx;
00188 }
00189 
00190 static int ogg_new_buf(struct ogg *ogg, int idx)
00191 {
00192     struct ogg_stream *os = ogg->streams + idx;
00193     uint8_t *nb = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
00194     int size = os->bufpos - os->pstart;
00195     if(os->buf){
00196         memcpy(nb, os->buf + os->pstart, size);
00197         av_free(os->buf);
00198     }
00199     os->buf = nb;
00200     os->bufpos = size;
00201     os->pstart = 0;
00202 
00203     return 0;
00204 }
00205 
00206 static int ogg_read_page(AVFormatContext *s, int *str)
00207 {
00208     AVIOContext *bc = s->pb;
00209     struct ogg *ogg = s->priv_data;
00210     struct ogg_stream *os;
00211     int ret, i = 0;
00212     int flags, nsegs;
00213     uint64_t gp;
00214     uint32_t serial;
00215     int size, idx;
00216     uint8_t sync[4];
00217     int sp = 0;
00218 
00219     ret = avio_read(bc, sync, 4);
00220     if (ret < 4)
00221         return ret < 0 ? ret : AVERROR_EOF;
00222 
00223     do{
00224         int c;
00225 
00226         if (sync[sp & 3] == 'O' &&
00227             sync[(sp + 1) & 3] == 'g' &&
00228             sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
00229             break;
00230 
00231         c = avio_r8(bc);
00232         if (bc->eof_reached)
00233             return AVERROR_EOF;
00234         sync[sp++ & 3] = c;
00235     }while (i++ < MAX_PAGE_SIZE);
00236 
00237     if (i >= MAX_PAGE_SIZE){
00238         av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
00239         return AVERROR_INVALIDDATA;
00240     }
00241 
00242     if (avio_r8(bc) != 0)      /* version */
00243         return AVERROR_INVALIDDATA;
00244 
00245     flags = avio_r8(bc);
00246     gp = avio_rl64 (bc);
00247     serial = avio_rl32 (bc);
00248     avio_skip(bc, 8); /* seq, crc */
00249     nsegs = avio_r8(bc);
00250 
00251     idx = ogg_find_stream (ogg, serial);
00252     if (idx < 0){
00253         if (ogg->headers) {
00254             int n;
00255 
00256             for (n = 0; n < ogg->nstreams; n++) {
00257                 av_freep(&ogg->streams[n].buf);
00258                 if (!ogg->state || ogg->state->streams[n].private != ogg->streams[n].private)
00259                     av_freep(&ogg->streams[n].private);
00260             }
00261             ogg->curidx   = -1;
00262             ogg->nstreams = 0;
00263             idx = ogg_new_stream(s, serial, 0);
00264         } else {
00265             idx = ogg_new_stream(s, serial, 1);
00266         }
00267         if (idx < 0)
00268             return idx;
00269     }
00270 
00271     os = ogg->streams + idx;
00272     os->page_pos = avio_tell(bc) - 27;
00273 
00274     if(os->psize > 0)
00275         ogg_new_buf(ogg, idx);
00276 
00277     ret = avio_read(bc, os->segments, nsegs);
00278     if (ret < nsegs)
00279         return ret < 0 ? ret : AVERROR_EOF;
00280 
00281     os->nsegs = nsegs;
00282     os->segp = 0;
00283 
00284     size = 0;
00285     for (i = 0; i < nsegs; i++)
00286         size += os->segments[i];
00287 
00288     if (flags & OGG_FLAG_CONT || os->incomplete){
00289         if (!os->psize){
00290             while (os->segp < os->nsegs){
00291                 int seg = os->segments[os->segp++];
00292                 os->pstart += seg;
00293                 if (seg < 255)
00294                     break;
00295             }
00296             os->sync_pos = os->page_pos;
00297         }
00298     }else{
00299         os->psize = 0;
00300         os->sync_pos = os->page_pos;
00301     }
00302 
00303     if (os->bufsize - os->bufpos < size){
00304         uint8_t *nb = av_malloc ((os->bufsize *= 2) + FF_INPUT_BUFFER_PADDING_SIZE);
00305         if (!nb)
00306             return AVERROR(ENOMEM);
00307         memcpy (nb, os->buf, os->bufpos);
00308         av_free (os->buf);
00309         os->buf = nb;
00310     }
00311 
00312     ret = avio_read(bc, os->buf + os->bufpos, size);
00313     if (ret < size)
00314         return ret < 0 ? ret : AVERROR_EOF;
00315 
00316     os->bufpos += size;
00317     os->granule = gp;
00318     os->flags = flags;
00319 
00320     memset(os->buf + os->bufpos, 0, FF_INPUT_BUFFER_PADDING_SIZE);
00321     if (str)
00322         *str = idx;
00323 
00324     return 0;
00325 }
00326 
00327 static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize,
00328                       int64_t *fpos)
00329 {
00330     struct ogg *ogg = s->priv_data;
00331     int idx, i, ret;
00332     struct ogg_stream *os;
00333     int complete = 0;
00334     int segp = 0, psize = 0;
00335 
00336     av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx);
00337 
00338     do{
00339         idx = ogg->curidx;
00340 
00341         while (idx < 0){
00342             ret = ogg_read_page(s, &idx);
00343             if (ret < 0)
00344                 return ret;
00345         }
00346 
00347         os = ogg->streams + idx;
00348 
00349         av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
00350                 idx, os->pstart, os->psize, os->segp, os->nsegs);
00351 
00352         if (!os->codec){
00353             if (os->header < 0){
00354                 os->codec = ogg_find_codec (os->buf, os->bufpos);
00355                 if (!os->codec){
00356                     av_log(s, AV_LOG_WARNING, "Codec not found\n");
00357                     os->header = 0;
00358                     return 0;
00359                 }
00360             }else{
00361                 return 0;
00362             }
00363         }
00364 
00365         segp = os->segp;
00366         psize = os->psize;
00367 
00368         while (os->segp < os->nsegs){
00369             int ss = os->segments[os->segp++];
00370             os->psize += ss;
00371             if (ss < 255){
00372                 complete = 1;
00373                 break;
00374             }
00375         }
00376 
00377         if (!complete && os->segp == os->nsegs){
00378             ogg->curidx = -1;
00379             os->incomplete = 1;
00380         }
00381     }while (!complete);
00382 
00383     av_dlog(s, "ogg_packet: idx %i, frame size %i, start %i\n",
00384             idx, os->psize, os->pstart);
00385 
00386     if (os->granule == -1)
00387         av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos);
00388 
00389     ogg->curidx = idx;
00390     os->incomplete = 0;
00391 
00392     if (os->header) {
00393         os->header = os->codec->header (s, idx);
00394         if (!os->header){
00395             os->segp = segp;
00396             os->psize = psize;
00397 
00398             // We have reached the first non-header packet in this stream.
00399             // Unfortunately more header packets may still follow for others,
00400             // but if we continue with header parsing we may lose data packets.
00401             ogg->headers = 1;
00402 
00403             // Update the header state for all streams and
00404             // compute the data_offset.
00405             if (!s->data_offset)
00406                 s->data_offset = os->sync_pos;
00407             for (i = 0; i < ogg->nstreams; i++) {
00408                 struct ogg_stream *cur_os = ogg->streams + i;
00409 
00410                 // if we have a partial non-header packet, its start is
00411                 // obviously at or after the data start
00412                 if (cur_os->incomplete)
00413                     s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
00414             }
00415         }else{
00416             os->pstart += os->psize;
00417             os->psize = 0;
00418         }
00419     } else {
00420         os->pflags = 0;
00421         os->pduration = 0;
00422         if (os->codec && os->codec->packet)
00423             os->codec->packet (s, idx);
00424         if (str)
00425             *str = idx;
00426         if (dstart)
00427             *dstart = os->pstart;
00428         if (dsize)
00429             *dsize = os->psize;
00430         if (fpos)
00431             *fpos = os->sync_pos;
00432         os->pstart += os->psize;
00433         os->psize = 0;
00434         os->sync_pos = os->page_pos;
00435     }
00436 
00437     // determine whether there are more complete packets in this page
00438     // if not, the page's granule will apply to this packet
00439     os->page_end = 1;
00440     for (i = os->segp; i < os->nsegs; i++)
00441         if (os->segments[i] < 255) {
00442             os->page_end = 0;
00443             break;
00444         }
00445 
00446     if (os->segp == os->nsegs)
00447         ogg->curidx = -1;
00448 
00449     return 0;
00450 }
00451 
00452 static int ogg_get_headers(AVFormatContext *s)
00453 {
00454     struct ogg *ogg = s->priv_data;
00455     int ret;
00456 
00457     do{
00458         ret = ogg_packet(s, NULL, NULL, NULL, NULL);
00459         if (ret < 0)
00460             return ret;
00461     }while (!ogg->headers);
00462 
00463     av_dlog(s, "found headers\n");
00464 
00465     return 0;
00466 }
00467 
00468 static int ogg_get_length(AVFormatContext *s)
00469 {
00470     struct ogg *ogg = s->priv_data;
00471     int i;
00472     int64_t size, end;
00473 
00474     if(!s->pb->seekable)
00475         return 0;
00476 
00477 // already set
00478     if (s->duration != AV_NOPTS_VALUE)
00479         return 0;
00480 
00481     size = avio_size(s->pb);
00482     if(size < 0)
00483         return 0;
00484     end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
00485 
00486     ogg_save (s);
00487     avio_seek (s->pb, end, SEEK_SET);
00488 
00489     while (!ogg_read_page (s, &i)){
00490         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
00491             ogg->streams[i].codec) {
00492             s->streams[i]->duration =
00493                 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
00494             if (s->streams[i]->start_time != AV_NOPTS_VALUE)
00495                 s->streams[i]->duration -= s->streams[i]->start_time;
00496         }
00497     }
00498 
00499     ogg_restore (s, 0);
00500 
00501     return 0;
00502 }
00503 
00504 static int ogg_read_close(AVFormatContext *s)
00505 {
00506     struct ogg *ogg = s->priv_data;
00507     int i;
00508 
00509     for (i = 0; i < ogg->nstreams; i++) {
00510         av_free(ogg->streams[i].buf);
00511         av_free(ogg->streams[i].private);
00512     }
00513     av_free(ogg->streams);
00514     return 0;
00515 }
00516 
00517 static int ogg_read_header(AVFormatContext *s)
00518 {
00519     struct ogg *ogg = s->priv_data;
00520     int ret, i;
00521     ogg->curidx = -1;
00522     //linear headers seek from start
00523     ret = ogg_get_headers(s);
00524     if (ret < 0) {
00525         ogg_read_close(s);
00526         return ret;
00527     }
00528 
00529     for (i = 0; i < ogg->nstreams; i++)
00530         if (ogg->streams[i].header < 0)
00531             ogg->streams[i].codec = NULL;
00532 
00533     //linear granulepos seek from end
00534     ogg_get_length (s);
00535 
00536     //fill the extradata in the per codec callbacks
00537     return 0;
00538 }
00539 
00540 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
00541 {
00542     struct ogg *ogg = s->priv_data;
00543     struct ogg_stream *os = ogg->streams + idx;
00544     int64_t pts = AV_NOPTS_VALUE;
00545 
00546     if (dts)
00547         *dts = AV_NOPTS_VALUE;
00548 
00549     if (os->lastpts != AV_NOPTS_VALUE) {
00550         pts = os->lastpts;
00551         os->lastpts = AV_NOPTS_VALUE;
00552     }
00553     if (os->lastdts != AV_NOPTS_VALUE) {
00554         if (dts)
00555             *dts = os->lastdts;
00556         os->lastdts = AV_NOPTS_VALUE;
00557     }
00558     if (os->page_end) {
00559         if (os->granule != -1LL) {
00560             if (os->codec && os->codec->granule_is_start)
00561                 pts = ogg_gptopts(s, idx, os->granule, dts);
00562             else
00563                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
00564             os->granule = -1LL;
00565         }
00566     }
00567     return pts;
00568 }
00569 
00570 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
00571 {
00572     struct ogg *ogg;
00573     struct ogg_stream *os;
00574     int idx = -1, ret;
00575     int pstart, psize;
00576     int64_t fpos, pts, dts;
00577 
00578     //Get an ogg packet
00579 retry:
00580     do{
00581         ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
00582         if (ret < 0)
00583             return ret;
00584     }while (idx < 0 || !s->streams[idx]);
00585 
00586     ogg = s->priv_data;
00587     os = ogg->streams + idx;
00588 
00589     // pflags might not be set until after this
00590     pts = ogg_calc_pts(s, idx, &dts);
00591 
00592     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
00593         goto retry;
00594     os->keyframe_seek = 0;
00595 
00596     //Alloc a pkt
00597     ret = av_new_packet(pkt, psize);
00598     if (ret < 0)
00599         return ret;
00600     pkt->stream_index = idx;
00601     memcpy (pkt->data, os->buf + pstart, psize);
00602 
00603     pkt->pts = pts;
00604     pkt->dts = dts;
00605     pkt->flags = os->pflags;
00606     pkt->duration = os->pduration;
00607     pkt->pos = fpos;
00608 
00609     return psize;
00610 }
00611 
00612 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
00613                                   int64_t *pos_arg, int64_t pos_limit)
00614 {
00615     struct ogg *ogg = s->priv_data;
00616     AVIOContext *bc = s->pb;
00617     int64_t pts = AV_NOPTS_VALUE;
00618     int i = -1;
00619     avio_seek(bc, *pos_arg, SEEK_SET);
00620     ogg_reset(ogg);
00621 
00622     while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
00623         if (i == stream_index) {
00624             struct ogg_stream *os = ogg->streams + stream_index;
00625             pts = ogg_calc_pts(s, i, NULL);
00626             if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
00627                 pts = AV_NOPTS_VALUE;
00628         }
00629         if (pts != AV_NOPTS_VALUE)
00630             break;
00631     }
00632     ogg_reset(ogg);
00633     return pts;
00634 }
00635 
00636 static int ogg_read_seek(AVFormatContext *s, int stream_index,
00637                          int64_t timestamp, int flags)
00638 {
00639     struct ogg *ogg = s->priv_data;
00640     struct ogg_stream *os = ogg->streams + stream_index;
00641     int ret;
00642 
00643     // Try seeking to a keyframe first. If this fails (very possible),
00644     // av_seek_frame will fall back to ignoring keyframes
00645     if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
00646         && !(flags & AVSEEK_FLAG_ANY))
00647         os->keyframe_seek = 1;
00648 
00649     ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
00650     os = ogg->streams + stream_index;
00651     if (ret < 0)
00652         os->keyframe_seek = 0;
00653     return ret;
00654 }
00655 
00656 static int ogg_probe(AVProbeData *p)
00657 {
00658     if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
00659         return AVPROBE_SCORE_MAX;
00660     return 0;
00661 }
00662 
00663 AVInputFormat ff_ogg_demuxer = {
00664     .name           = "ogg",
00665     .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
00666     .priv_data_size = sizeof(struct ogg),
00667     .read_probe     = ogg_probe,
00668     .read_header    = ogg_read_header,
00669     .read_packet    = ogg_read_packet,
00670     .read_close     = ogg_read_close,
00671     .read_seek      = ogg_read_seek,
00672     .read_timestamp = ogg_read_timestamp,
00673     .extensions     = "ogg",
00674     .flags          = AVFMT_GENERIC_INDEX,
00675 };