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         if (ogg->streams[i].codec &&
00512             ogg->streams[i].codec->cleanup) {
00513             ogg->streams[i].codec->cleanup(s, i);
00514         }
00515         av_free(ogg->streams[i].private);
00516     }
00517     av_free(ogg->streams);
00518     return 0;
00519 }
00520 
00521 static int ogg_read_header(AVFormatContext *s)
00522 {
00523     struct ogg *ogg = s->priv_data;
00524     int ret, i;
00525     ogg->curidx = -1;
00526     //linear headers seek from start
00527     ret = ogg_get_headers(s);
00528     if (ret < 0) {
00529         ogg_read_close(s);
00530         return ret;
00531     }
00532 
00533     for (i = 0; i < ogg->nstreams; i++)
00534         if (ogg->streams[i].header < 0)
00535             ogg->streams[i].codec = NULL;
00536 
00537     //linear granulepos seek from end
00538     ogg_get_length (s);
00539 
00540     //fill the extradata in the per codec callbacks
00541     return 0;
00542 }
00543 
00544 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
00545 {
00546     struct ogg *ogg = s->priv_data;
00547     struct ogg_stream *os = ogg->streams + idx;
00548     int64_t pts = AV_NOPTS_VALUE;
00549 
00550     if (dts)
00551         *dts = AV_NOPTS_VALUE;
00552 
00553     if (os->lastpts != AV_NOPTS_VALUE) {
00554         pts = os->lastpts;
00555         os->lastpts = AV_NOPTS_VALUE;
00556     }
00557     if (os->lastdts != AV_NOPTS_VALUE) {
00558         if (dts)
00559             *dts = os->lastdts;
00560         os->lastdts = AV_NOPTS_VALUE;
00561     }
00562     if (os->page_end) {
00563         if (os->granule != -1LL) {
00564             if (os->codec && os->codec->granule_is_start)
00565                 pts = ogg_gptopts(s, idx, os->granule, dts);
00566             else
00567                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
00568             os->granule = -1LL;
00569         }
00570     }
00571     return pts;
00572 }
00573 
00574 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
00575 {
00576     struct ogg *ogg;
00577     struct ogg_stream *os;
00578     int idx = -1, ret;
00579     int pstart, psize;
00580     int64_t fpos, pts, dts;
00581 
00582     //Get an ogg packet
00583 retry:
00584     do{
00585         ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
00586         if (ret < 0)
00587             return ret;
00588     }while (idx < 0 || !s->streams[idx]);
00589 
00590     ogg = s->priv_data;
00591     os = ogg->streams + idx;
00592 
00593     // pflags might not be set until after this
00594     pts = ogg_calc_pts(s, idx, &dts);
00595 
00596     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
00597         goto retry;
00598     os->keyframe_seek = 0;
00599 
00600     //Alloc a pkt
00601     ret = av_new_packet(pkt, psize);
00602     if (ret < 0)
00603         return ret;
00604     pkt->stream_index = idx;
00605     memcpy (pkt->data, os->buf + pstart, psize);
00606 
00607     pkt->pts = pts;
00608     pkt->dts = dts;
00609     pkt->flags = os->pflags;
00610     pkt->duration = os->pduration;
00611     pkt->pos = fpos;
00612 
00613     return psize;
00614 }
00615 
00616 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
00617                                   int64_t *pos_arg, int64_t pos_limit)
00618 {
00619     struct ogg *ogg = s->priv_data;
00620     AVIOContext *bc = s->pb;
00621     int64_t pts = AV_NOPTS_VALUE;
00622     int i = -1;
00623     avio_seek(bc, *pos_arg, SEEK_SET);
00624     ogg_reset(ogg);
00625 
00626     while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
00627         if (i == stream_index) {
00628             struct ogg_stream *os = ogg->streams + stream_index;
00629             pts = ogg_calc_pts(s, i, NULL);
00630             if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
00631                 pts = AV_NOPTS_VALUE;
00632         }
00633         if (pts != AV_NOPTS_VALUE)
00634             break;
00635     }
00636     ogg_reset(ogg);
00637     return pts;
00638 }
00639 
00640 static int ogg_read_seek(AVFormatContext *s, int stream_index,
00641                          int64_t timestamp, int flags)
00642 {
00643     struct ogg *ogg = s->priv_data;
00644     struct ogg_stream *os = ogg->streams + stream_index;
00645     int ret;
00646 
00647     // Try seeking to a keyframe first. If this fails (very possible),
00648     // av_seek_frame will fall back to ignoring keyframes
00649     if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
00650         && !(flags & AVSEEK_FLAG_ANY))
00651         os->keyframe_seek = 1;
00652 
00653     ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
00654     os = ogg->streams + stream_index;
00655     if (ret < 0)
00656         os->keyframe_seek = 0;
00657     return ret;
00658 }
00659 
00660 static int ogg_probe(AVProbeData *p)
00661 {
00662     if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
00663         return AVPROBE_SCORE_MAX;
00664     return 0;
00665 }
00666 
00667 AVInputFormat ff_ogg_demuxer = {
00668     .name           = "ogg",
00669     .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
00670     .priv_data_size = sizeof(struct ogg),
00671     .read_probe     = ogg_probe,
00672     .read_header    = ogg_read_header,
00673     .read_packet    = ogg_read_packet,
00674     .read_close     = ogg_read_close,
00675     .read_seek      = ogg_read_seek,
00676     .read_timestamp = ogg_read_timestamp,
00677     .extensions     = "ogg",
00678     .flags          = AVFMT_GENERIC_INDEX,
00679 };