decoder-ogg-stream.c
author nathan
Fri, 13 Nov 2009 19:27:36 +0800
branchtrunk
changeset 33 65ed49cbc08b
child 38 79b272a68eb4
permissions -rw-r--r--
add OGG streaming support
     1 /*
     2  * MP3/MPlayer plugin to VDR (C++)
     3  *
     4  * (C) 2001-2009 Stefan Huelswitt <s.huelswitt@gmx.de>
     5  *
     6  * OGG stream support initialy developed by Manuel Reimer <manuel.reimer@gmx.de>
     7  *
     8  * This code is free software; you can redistribute it and/or
     9  * modify it under the terms of the GNU General Public License
    10  * as published by the Free Software Foundation; either version 2
    11  * of the License, or (at your option) any later version.
    12  *
    13  * This code is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  *
    18  * You should have received a copy of the GNU General Public License
    19  * along with this program; if not, write to the Free Software
    20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    21  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
    22  */
    23 
    24 #include <stdlib.h>
    25 #include <stdio.h>
    26 
    27 #include "common.h"
    28 #include "decoder-ogg-stream.h"
    29 #include "stream.h"
    30 
    31 // --- Ogg callbacks -----------------------------------------------------------
    32 
    33 static size_t callback_read(void *ptr, size_t size, size_t nmemb, void *datasource)
    34 {
    35   cNetStream *nstr=(cNetStream*)datasource;
    36   unsigned char *sdata;
    37   unsigned long slen=0;
    38   // Read in loop until we either get data or function "Stream" fails
    39   do {
    40     if(!nstr->Stream(sdata,slen)) {
    41       d(printf("oggstream-callback-read: EOF?\n"))
    42       return 0;
    43       }
    44     } while(slen==0);
    45 
    46   size_t read_size=size*nmemb;
    47   if(slen>read_size) {
    48     // If someone ever gets this message, buffer handling has to be improved...
    49     d(printf("oggstream-callback-read: buffer size too small...\n"))
    50     slen=read_size;
    51     }
    52   memcpy(ptr,sdata,slen);
    53   return slen/size;
    54 }
    55 
    56 static int callback_close(void *datasource)
    57 {
    58   cNetStream *nstr=(cNetStream*)datasource;
    59   nstr->Close();
    60   return 0;
    61 }
    62 
    63 static const ov_callbacks callbacks = {
    64   callback_read,
    65   NULL,
    66   callback_close,
    67   NULL
    68   };
    69 
    70 // --- cNetOggFile -------------------------------------------------------------
    71 
    72 cNetOggFile::cNetOggFile(const char *Filename)
    73 :cOggFile(Filename)
    74 {
    75   nstr=new cNetStream(Filename);
    76 }
    77 
    78 bool cNetOggFile::Open(bool log)
    79 {
    80   if(opened) return true;
    81   if(!nstr->Open(log)) return false;
    82   int r=ov_open_callbacks(nstr,&vf,NULL,0,callbacks);
    83   if(!r) opened=true;
    84   else {
    85     nstr->Close();
    86     if(log) Error("open",r);
    87     }
    88   return opened;
    89 }
    90 
    91 // --- cNetOggInfo -------------------------------------------------------------
    92 
    93 cNetOggInfo::cNetOggInfo(cNetOggFile *File)
    94 :cOggInfo(File)
    95 {
    96   nfile=File;
    97   nstr=nfile->nstr;
    98 }
    99 
   100 bool cNetOggInfo::DoScan(bool KeepOpen)
   101 {
   102   Clear();
   103   IcyInfo();
   104   if(!Title) FakeTitle(nstr->Filename);
   105   Total=0;
   106   ChMode=3;
   107   DecoderID=DEC_OGGS;
   108   InfoDone();
   109   return true;
   110 }
   111 
   112 void cNetOggInfo::InfoHook()
   113 {
   114   if(nstr->IcyChanged()) IcyInfo();
   115   vorbis_info *vi=ov_info(&nfile->vf,-1);
   116   if(!vi) return;
   117   Channels=vi->channels;
   118   ChMode=Channels>1 ? 3:0;
   119   SampleFreq=vi->rate;
   120   if(vi->bitrate_upper>0 && vi->bitrate_lower>0) {
   121     Bitrate=vi->bitrate_lower;
   122     MaxBitrate=vi->bitrate_upper;
   123     }
   124   else
   125     Bitrate=vi->bitrate_nominal;
   126 
   127   Total=(int)ov_time_total(&nfile->vf,-1);
   128   Frames=-1;
   129 }
   130 
   131 void cNetOggInfo::IcyInfo(void)
   132 {
   133   const char *t=nstr->IcyTitle();
   134   const char *a;
   135   if(t) {
   136     a=nstr->IcyName();
   137     if(!a) a=nstr->IcyUrl();
   138     }
   139   else {
   140     t=nstr->IcyName();
   141     a=nstr->IcyUrl();
   142     }
   143   if(t && (!Title || strcmp(t,Title))) {
   144     free(Title);
   145     Title=strdup(t);
   146     }
   147   if(a && (!Album || strcmp(a,Album))) {
   148     free(Album);
   149     Album=strdup(a);
   150     }
   151 }
   152 
   153 // --- cOggStreamDecoder -------------------------------------------------------
   154 
   155 cOggStreamDecoder::cOggStreamDecoder(const char *Filename)
   156 :cOggDecoder(Filename,false)
   157 {
   158   nfile=new cNetOggFile(Filename);
   159   file=nfile;
   160   info=new cNetOggInfo(nfile);
   161 }