changeset 15420:f3cf481bbcda

vorbis extradata is now passed from demuxer to decoder in matroska's way
author nicodvb
date Thu, 12 May 2005 17:35:58 +0000
parents da39fe11c872
children ae5e1b9e3c92
files libmpcodecs/ad_libvorbis.c libmpdemux/demux_mkv.c libmpdemux/demux_ogg.c
diffstat 3 files changed, 146 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/libmpcodecs/ad_libvorbis.c	Thu May 12 15:31:37 2005 +0000
+++ b/libmpcodecs/ad_libvorbis.c	Thu May 12 17:35:58 2005 +0000
@@ -60,6 +60,8 @@
 
 static int init(sh_audio_t *sh)
 {
+  unsigned int offset, i, length, hsizes[3], *headers[3];
+  unsigned char* extradata;
   ogg_packet op;
   vorbis_comment vc;
   struct ov_struct_st *ov;
@@ -69,31 +71,66 @@
     free(ov); \
     return 0; \
   }
+
+  if(! sh->wf) {
+    mp_msg(MSGT_DECAUDIO,MSGL_ERR,"ad_vorbis, extradata seems to be absent! exit\n");
+    ERROR();
+  }
+
+  if(! sh->wf->cbSize) {
+    mp_msg(MSGT_DECAUDIO,MSGL_ERR,"ad_vorbis, extradata seems to be absent!, exit\n");
+    ERROR();
+  }
+
+  mp_msg(MSGT_DECAUDIO,MSGL_V,"ad_vorbis, extradata seems is %d bytes long\n", sh->wf->cbSize);
+  extradata = (char*) (sh->wf+1);
+  if(!extradata) {
+    mp_msg(MSGT_DECAUDIO,MSGL_ERR,"ad_vorbis, extradata seems to be NULL!, exit\n");
+    ERROR();
+  }
+
+  if(*extradata != 2) {
+    mp_msg (MSGT_DEMUX, MSGL_WARN, "ad_vorbis: Vorbis track does not contain valid headers.\n");
+    ERROR();
+  }
+
+  offset = 1;
+  for (i=0; i < 2; i++) {
+    length = 0;
+    while ((extradata[offset] == (unsigned char) 0xFF) && length < sh->wf->cbSize) {
+      length += 255;
+      offset++;
+    }
+    if(offset >= (sh->wf->cbSize - 1)) {
+      mp_msg (MSGT_DEMUX, MSGL_WARN, "ad_vorbis: Vorbis track does not contain valid headers.\n");
+      ERROR();
+    }
+    length += extradata[offset];
+    offset++;
+    mp_msg (MSGT_DEMUX, MSGL_V, "ad_vorbis, offset: %u, length: %u\n", offset, length);
+    hsizes[i] = length;
+  }
+
+  headers[0] = &extradata[offset];
+  headers[1] = &extradata[offset + hsizes[0]];
+  headers[2] = &extradata[offset + hsizes[0] + hsizes[1]];
+  hsizes[2] = sh->wf->cbSize - offset - hsizes[0] - hsizes[1];
+  mp_msg (MSGT_DEMUX, MSGL_V, "ad_vorbis, header sizes: %d %d %d\n", hsizes[0], hsizes[1], hsizes[2]);
+
   /// Init the decoder with the 3 header packets
   ov = (struct ov_struct_st*)malloc(sizeof(struct ov_struct_st));
   vorbis_info_init(&ov->vi);
   vorbis_comment_init(&vc);
-  op.bytes = ds_get_packet(sh->ds,&op.packet);
-  op.b_o_s  = 1;
-  /// Header
-  if(vorbis_synthesis_headerin(&ov->vi,&vc,&op) <0) {
-    mp_msg(MSGT_DECAUDIO,MSGL_ERR,"OggVorbis: initial (identification) header broken!\n");
-    ERROR();
-  }
-  op.bytes = ds_get_packet(sh->ds,&op.packet);
-  op.b_o_s  = 0;
-  /// Comments
-  if(vorbis_synthesis_headerin(&ov->vi,&vc,&op) <0) {
-    mp_msg(MSGT_DECAUDIO,MSGL_ERR,"OggVorbis: comment header broken!\n");
-    ERROR();
-  }
-  op.bytes = ds_get_packet(sh->ds,&op.packet);
-  //// Codebook
-  if(vorbis_synthesis_headerin(&ov->vi,&vc,&op)<0) {
-    mp_msg(MSGT_DECAUDIO,MSGL_WARN,"OggVorbis: codebook header broken!\n");
-    ERROR();
-  } else { /// Print the infos
-    float rg_gain=0.f, rg_peak=0.f;
+  for(i=0; i<3; i++) {
+    op.bytes = hsizes[i];
+    op.packet = headers[i];
+    op.b_o_s  = (i == 0);
+    if(vorbis_synthesis_headerin(&ov->vi,&vc,&op) <0) {
+      mp_msg(MSGT_DECAUDIO,MSGL_ERR,"OggVorbis: header n. %d broken! len=%d\n", i, op.bytes);
+      ERROR();
+    }
+    if(i == 2) {
+      float rg_gain=0.f, rg_peak=0.f;
     char **ptr=vc.user_comments;
     while(*ptr){
       mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbisComment: %s\n",*ptr);
@@ -130,7 +167,9 @@
     if(rg_gain || rg_peak)
       mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Gain = %+.2f dB, Peak = %.4f, Scale = %.2f\n", rg_gain, rg_peak, ov->rg_scale);
     mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Encoded by: %s\n",vc.vendor);
+    }
   }
+
   vorbis_comment_clear(&vc);
 
 //  printf("lower=%d  upper=%d  \n",(int)ov->vi.bitrate_lower,(int)ov->vi.bitrate_upper);
--- a/libmpdemux/demux_mkv.c	Thu May 12 15:31:37 2005 +0000
+++ b/libmpdemux/demux_mkv.c	Thu May 12 17:35:58 2005 +0000
@@ -1781,48 +1781,8 @@
         track->a_formattag = mmioFOURCC('M', 'P', '4', 'A');
       else if (!strcmp(track->codec_id, MKV_A_VORBIS))
         {
-          unsigned char *c;
-          uint32_t offset, length;
-
           if (track->private_data == NULL)
             return 1;
-
-          c = (unsigned char *) track->private_data;
-          if (*c != 2)
-            {
-              mp_msg (MSGT_DEMUX, MSGL_WARN, "[mkv] Vorbis track does not "
-                      "contain valid headers.\n");
-              return 1;
-            }
-
-          offset = 1;
-          for (i=0; i < 2; i++)
-            {
-              length = 0;
-              while (c[offset] == (unsigned char) 0xFF
-                     && length < track->private_size)
-                {
-                  length += 255;
-                  offset++;
-                }
-              if (offset >= (track->private_size - 1))
-                {
-                  mp_msg (MSGT_DEMUX, MSGL_WARN, "[mkv] Vorbis track "
-                          "does not contain valid headers.\n");
-                  return 1;
-                }
-              length += c[offset];
-              offset++;
-              track->header_sizes[i] = length;
-            }
-
-          track->headers[0] = &c[offset];
-          track->headers[1] = &c[offset + track->header_sizes[0]];
-          track->headers[2] = &c[offset + track->header_sizes[0] +
-                                 track->header_sizes[1]];
-          track->header_sizes[2] = track->private_size - offset
-            - track->header_sizes[0] - track->header_sizes[1];
-
           track->a_formattag = mmioFOURCC('v', 'r', 'b', 's');
         }
       else if (!strcmp(track->codec_id, MKV_A_QDMC))
@@ -1954,14 +1914,9 @@
     }
   else if (track->a_formattag == mmioFOURCC('v', 'r', 'b', 's'))  /* VORBIS */
     {
-      for (i=0; i < 3; i++)
-        {
-          dp = new_demux_packet (track->header_sizes[i]);
-          memcpy (dp->buffer,track->headers[i],track->header_sizes[i]);
-          dp->pts = 0;
-          dp->flags = 0;
-          ds_add_packet (demuxer->audio, dp);
-        }
+      sh_a->wf->cbSize = track->private_size;
+      sh_a->wf = (WAVEFORMATEX*)realloc(sh_a->wf, sizeof(WAVEFORMATEX) + sh_a->wf->cbSize);
+      memcpy((unsigned char *) (sh_a->wf+1), track->private_data, sh_a->wf->cbSize);
     }
   else if (track->private_size >= sizeof(real_audio_v4_props_t)
            && !strncmp (track->codec_id, MKV_A_REALATRC, 7))
--- a/libmpdemux/demux_ogg.c	Thu May 12 15:31:37 2005 +0000
+++ b/libmpdemux/demux_ogg.c	Thu May 12 17:35:58 2005 +0000
@@ -736,6 +736,86 @@
 
 void demux_close_ogg(demuxer_t* demuxer);
 
+static inline unsigned int store_ughvlc(unsigned char *s, unsigned int v)
+{
+  unsigned int n = 0;
+
+  while(v >= 0xff)
+  {
+    *s++ = 0xff;
+    v -= 0xff;
+    n++;
+  }
+  *s = v;
+  n++;
+
+  return n;
+}
+
+static void fixup_vorbis_wf(sh_audio_t *sh)
+{
+  int i, k, offset;
+  ogg_packet op[3];
+  unsigned char *buf[3];
+  unsigned char *ptr;
+
+  for(i = 0; i < 3; i++) {
+    op[i].bytes = ds_get_packet(sh->ds, &(op[i].packet));
+    mp_msg(MSGT_DEMUX,MSGL_V, "fixup_vorbis_wf: i=%d, size=%d\n", i, op[i].bytes);
+    if(op[i].bytes < 0) {
+       mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer error!, fixup_vorbis_wf: bad packet n. %d\n", i);
+       return;
+    }
+    buf[i] = malloc(op[i].bytes);
+    if(!buf[i])
+      return;
+    memcpy(buf[i], op[i].packet, op[i].bytes);
+  }
+
+  sh->wf = (WAVEFORMATEX*)calloc(1, sizeof(WAVEFORMATEX) + op[0].bytes + op[1].bytes + op[2].bytes + 64);
+  ptr = (unsigned char*) (sh->wf+1);
+
+  ptr[0] = 2;
+  offset = 1;
+  offset += store_ughvlc(&ptr[offset], op[0].bytes);
+  mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, offset after 1st len = %d\n", offset);
+  offset += store_ughvlc(&ptr[offset], op[1].bytes);
+  mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, offset after 2nd len = %d\n", offset);
+  for(i = 0; i < 3; i++) {
+    mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, i=%d\n", op[i].bytes, offset, i);
+    memcpy(&ptr[offset], buf[i], op[i].bytes);
+    offset += op[i].bytes;
+  }
+  sh->wf->cbSize = offset;
+  mp_msg(MSGT_DEMUX,MSGL_V, "demux_ogg, extradata size: %d\n", sh->wf->cbSize);
+  sh->wf = (WAVEFORMATEX*)realloc(sh->wf, sizeof(WAVEFORMATEX) + sh->wf->cbSize);
+
+  if(op[0].bytes >= 29) {
+    unsigned int br, nombr, minbr, maxbr;
+    ptr = buf[0];
+    sh->channels = ptr[11];
+    sh->samplerate = sh->wf->nSamplesPerSec = get_uint32(&ptr[12]);
+    maxbr = get_uint32(&ptr[16]);  //max
+    nombr = get_uint32(&ptr[20]);  //nominal
+    minbr = get_uint32(&ptr[24]);  //minimum
+    br = maxbr / 8;
+    if(!br)
+      br = nombr / 8;
+    if(!br)
+      br = minbr / 8;
+    sh->wf->nAvgBytesPerSec = br;
+    sh->wf->wBitsPerSample = 16;
+    sh->samplesize = (sh->wf->wBitsPerSample+7)/8;
+
+    mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, vorbis stream features are: channels: %d, srate: %d, bitrate: %d, max: %u, nominal: %u, min: %u\n", 
+      sh->channels, sh->samplerate, sh->wf->nAvgBytesPerSec, maxbr, nombr, minbr);
+  }
+  free(buf[2]);
+  free(buf[1]);
+  free(buf[0]);
+}
+
+
 /// Open an ogg physical stream
 int demux_ogg_open(demuxer_t* demuxer) {
   ogg_demuxer_t* ogg_d;
@@ -1107,6 +1187,9 @@
 
   mp_msg(MSGT_DEMUX,MSGL_V,"Ogg demuxer : found %d audio stream%s, %d video stream%s and %d text stream%s\n",n_audio,n_audio>1?"s":"",n_video,n_video>1?"s":"",ogg_d->n_text,ogg_d->n_text>1?"s":"");
 
+  if(sh_a->format == FOURCC_VORBIS)
+    fixup_vorbis_wf(sh_a);
+
   return 1;
 
 err_out: