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             // Do not set incomplete for empty packets.
00380             // Together with the code in ogg_read_page
00381             // that discards all continuation of empty packets
00382             // we would get an infinite loop.
00383             os->incomplete = !!os->psize;
00384         }
00385     }while (!complete);
00386 
00387     av_dlog(s, "ogg_packet: idx %i, frame size %i, start %i\n",
00388             idx, os->psize, os->pstart);
00389 
00390     if (os->granule == -1)
00391         av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos);
00392 
00393     ogg->curidx = idx;
00394     os->incomplete = 0;
00395 
00396     if (os->header) {
00397         os->header = os->codec->header (s, idx);
00398         if (!os->header){
00399             os->segp = segp;
00400             os->psize = psize;
00401 
00402             // We have reached the first non-header packet in this stream.
00403             // Unfortunately more header packets may still follow for others,
00404             // but if we continue with header parsing we may lose data packets.
00405             ogg->headers = 1;
00406 
00407             // Update the header state for all streams and
00408             // compute the data_offset.
00409             if (!s->data_offset)
00410                 s->data_offset = os->sync_pos;
00411             for (i = 0; i < ogg->nstreams; i++) {
00412                 struct ogg_stream *cur_os = ogg->streams + i;
00413 
00414                 // if we have a partial non-header packet, its start is
00415                 // obviously at or after the data start
00416                 if (cur_os->incomplete)
00417                     s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
00418             }
00419         }else{
00420             os->pstart += os->psize;
00421             os->psize = 0;
00422         }
00423     } else {
00424         os->pflags = 0;
00425         os->pduration = 0;
00426         if (os->codec && os->codec->packet)
00427             os->codec->packet (s, idx);
00428         if (str)
00429             *str = idx;
00430         if (dstart)
00431             *dstart = os->pstart;
00432         if (dsize)
00433             *dsize = os->psize;
00434         if (fpos)
00435             *fpos = os->sync_pos;
00436         os->pstart += os->psize;
00437         os->psize = 0;
00438         os->sync_pos = os->page_pos;
00439     }
00440 
00441     // determine whether there are more complete packets in this page
00442     // if not, the page's granule will apply to this packet
00443     os->page_end = 1;
00444     for (i = os->segp; i < os->nsegs; i++)
00445         if (os->segments[i] < 255) {
00446             os->page_end = 0;
00447             break;
00448         }
00449 
00450     if (os->segp == os->nsegs)
00451         ogg->curidx = -1;
00452 
00453     return 0;
00454 }
00455 
00456 static int ogg_get_headers(AVFormatContext *s)
00457 {
00458     struct ogg *ogg = s->priv_data;
00459     int ret;
00460 
00461     do{
00462         ret = ogg_packet(s, NULL, NULL, NULL, NULL);
00463         if (ret < 0)
00464             return ret;
00465     }while (!ogg->headers);
00466 
00467     av_dlog(s, "found headers\n");
00468 
00469     return 0;
00470 }
00471 
00472 static int ogg_get_length(AVFormatContext *s)
00473 {
00474     struct ogg *ogg = s->priv_data;
00475     int i;
00476     int64_t size, end;
00477 
00478     if(!s->pb->seekable)
00479         return 0;
00480 
00481 // already set
00482     if (s->duration != AV_NOPTS_VALUE)
00483         return 0;
00484 
00485     size = avio_size(s->pb);
00486     if(size < 0)
00487         return 0;
00488     end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
00489 
00490     ogg_save (s);
00491     avio_seek (s->pb, end, SEEK_SET);
00492 
00493     while (!ogg_read_page (s, &i)){
00494         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
00495             ogg->streams[i].codec) {
00496             s->streams[i]->duration =
00497                 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
00498             if (s->streams[i]->start_time != AV_NOPTS_VALUE)
00499                 s->streams[i]->duration -= s->streams[i]->start_time;
00500         }
00501     }
00502 
00503     ogg_restore (s, 0);
00504 
00505     return 0;
00506 }
00507 
00508 static int ogg_read_close(AVFormatContext *s)
00509 {
00510     struct ogg *ogg = s->priv_data;
00511     int i;
00512 
00513     for (i = 0; i < ogg->nstreams; i++) {
00514         av_free(ogg->streams[i].buf);
00515         if (ogg->streams[i].codec &&
00516             ogg->streams[i].codec->cleanup) {
00517             ogg->streams[i].codec->cleanup(s, i);
00518         }
00519         av_free(ogg->streams[i].private);
00520     }
00521     av_free(ogg->streams);
00522     return 0;
00523 }
00524 
00525 static int ogg_read_header(AVFormatContext *s)
00526 {
00527     struct ogg *ogg = s->priv_data;
00528     int ret, i;
00529     ogg->curidx = -1;
00530     //linear headers seek from start
00531     ret = ogg_get_headers(s);
00532     if (ret < 0) {
00533         ogg_read_close(s);
00534         return ret;
00535     }
00536 
00537     for (i = 0; i < ogg->nstreams; i++)
00538         if (ogg->streams[i].header < 0)
00539             ogg->streams[i].codec = NULL;
00540 
00541     //linear granulepos seek from end
00542     ogg_get_length (s);
00543 
00544     //fill the extradata in the per codec callbacks
00545     return 0;
00546 }
00547 
00548 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
00549 {
00550     struct ogg *ogg = s->priv_data;
00551     struct ogg_stream *os = ogg->streams + idx;
00552     int64_t pts = AV_NOPTS_VALUE;
00553 
00554     if (dts)
00555         *dts = AV_NOPTS_VALUE;
00556 
00557     if (os->lastpts != AV_NOPTS_VALUE) {
00558         pts = os->lastpts;
00559         os->lastpts = AV_NOPTS_VALUE;
00560     }
00561     if (os->lastdts != AV_NOPTS_VALUE) {
00562         if (dts)
00563             *dts = os->lastdts;
00564         os->lastdts = AV_NOPTS_VALUE;
00565     }
00566     if (os->page_end) {
00567         if (os->granule != -1LL) {
00568             if (os->codec && os->codec->granule_is_start)
00569                 pts = ogg_gptopts(s, idx, os->granule, dts);
00570             else
00571                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
00572             os->granule = -1LL;
00573         }
00574     }
00575     return pts;
00576 }
00577 
00578 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
00579 {
00580     struct ogg *ogg;
00581     struct ogg_stream *os;
00582     int idx = -1, ret;
00583     int pstart, psize;
00584     int64_t fpos, pts, dts;
00585 
00586     //Get an ogg packet
00587 retry:
00588     do{
00589         ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
00590         if (ret < 0)
00591             return ret;
00592     }while (idx < 0 || !s->streams[idx]);
00593 
00594     ogg = s->priv_data;
00595     os = ogg->streams + idx;
00596 
00597     // pflags might not be set until after this
00598     pts = ogg_calc_pts(s, idx, &dts);
00599 
00600     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
00601         goto retry;
00602     os->keyframe_seek = 0;
00603 
00604     //Alloc a pkt
00605     ret = av_new_packet(pkt, psize);
00606     if (ret < 0)
00607         return ret;
00608     pkt->stream_index = idx;
00609     memcpy (pkt->data, os->buf + pstart, psize);
00610 
00611     pkt->pts = pts;
00612     pkt->dts = dts;
00613     pkt->flags = os->pflags;
00614     pkt->duration = os->pduration;
00615     pkt->pos = fpos;
00616 
00617     return psize;
00618 }
00619 
00620 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
00621                                   int64_t *pos_arg, int64_t pos_limit)
00622 {
00623     struct ogg *ogg = s->priv_data;
00624     AVIOContext *bc = s->pb;
00625     int64_t pts = AV_NOPTS_VALUE;
00626     int i = -1;
00627     avio_seek(bc, *pos_arg, SEEK_SET);
00628     ogg_reset(ogg);
00629 
00630     while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
00631         if (i == stream_index) {
00632             struct ogg_stream *os = ogg->streams + stream_index;
00633             pts = ogg_calc_pts(s, i, NULL);
00634             if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
00635                 pts = AV_NOPTS_VALUE;
00636         }
00637         if (pts != AV_NOPTS_VALUE)
00638             break;
00639     }
00640     ogg_reset(ogg);
00641     return pts;
00642 }
00643 
00644 static int ogg_read_seek(AVFormatContext *s, int stream_index,
00645                          int64_t timestamp, int flags)
00646 {
00647     struct ogg *ogg = s->priv_data;
00648     struct ogg_stream *os = ogg->streams + stream_index;
00649     int ret;
00650 
00651     // Try seeking to a keyframe first. If this fails (very possible),
00652     // av_seek_frame will fall back to ignoring keyframes
00653     if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
00654         && !(flags & AVSEEK_FLAG_ANY))
00655         os->keyframe_seek = 1;
00656 
00657     ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
00658     os = ogg->streams + stream_index;
00659     if (ret < 0)
00660         os->keyframe_seek = 0;
00661     return ret;
00662 }
00663 
00664 static int ogg_probe(AVProbeData *p)
00665 {
00666     if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
00667         return AVPROBE_SCORE_MAX;
00668     return 0;
00669 }
00670 
00671 AVInputFormat ff_ogg_demuxer = {
00672     .name           = "ogg",
00673     .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
00674     .priv_data_size = sizeof(struct ogg),
00675     .read_probe     = ogg_probe,
00676     .read_header    = ogg_read_header,
00677     .read_packet    = ogg_read_packet,
00678     .read_close     = ogg_read_close,
00679     .read_seek      = ogg_read_seek,
00680     .read_timestamp = ogg_read_timestamp,
00681     .extensions     = "ogg",
00682     .flags          = AVFMT_GENERIC_INDEX,
00683 };