gug-bg-herd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xine-lib] Помощ при миграци я libmpcdec3 -> libmpcdec6


From: Yavor Doganov
Subject: [xine-lib] Помощ при миграци я libmpcdec3 -> libmpcdec6
Date: Thu, 04 Jun 2009 14:24:12 +0300

Още една кръпка за xine-lib (#476374).  Тук ударих много здраво на камък
с поддръжката за SV8.

При отваряне на файл тип Musepack първо се зарежда приставката
xineplug_dmx_audio.so, където се извлича необходимата информация от
заглавната част на файла.  След проверката на сигнатурата в
`open_mpc_file' (src/demuxers/demux_mpc.c, това специално е лесно да се
пригоди за SV8) следват неща като

  /* Get frame count */
  this->current_frame = 0;
  this->frames = _X_LE_32(&this->header[4]);

Броят на "рамките" при SV7 си имат специална секция с дължина 32 бита в
заглавната част, докато при SV8 [1] е съвсем различно -- там присъстват
само "samples" (което, грубо казано, е frames / 1152, доколкото
разбирам) и размера е променлив.

След това става по-интересно:

  /* Get sample rate */
  switch ((_X_LE_32(&this->header[8]) >> 16) & 0x3) {
    case 0:
      this->samplerate = 44.1;
      break;
    case 1:
      this->samplerate = 48.0;
    ...

Това пак е 100% само за SV7 -- при SV8 това е в пакета "Stream Header".
Нататък се извършват най-различни изчисления и demux_mpc_send_chunk
подава на хапки потока за декодиране.  В demux_mpc.c не могат да се
ползват никакви функции на libmpcdec, всичко трябва да става чрез
анализиране на заглавната част на файла.  (Подозирам, без да съм гледал
кода, че именно заради това TagLib::File::MPC не работи за SV8 и не
показва никаква информация за файла при kid3 и тем подобни.)

Това са (за мен специално) сложни операции на ниско ниво, и след
няколкодневна борба все още не ми е ясно как да извлека аналогичната
информация от файл във формат SV8.  Програмист си требе тука.

Тествах с totem-xine, gxine и amarok-engine-xine.  SV7 се възпроизвежда
без проблем (което поне според мен е почти сигурна индикация, че
промените по декодера са читави), като при totem-xine се получава един
ефект, който ме притеснява.  При натискане на "Пауза" и възобновяване се
чува околко 5-10 сек много гаден скърцащ шум, подобен на този издаващ от
дисководещите.  Чак след това продължава песента.  Допускам, че това е
нещо свързано с начина, по който Totem ползва xine.  При gNS направо
умира със SIGFPE (дори и със xine без кръпката).  Ефектът не се
наблюдава при gxine и amarok.

По принцип приложената кръпка не е регресия, защото в момента xine не
поддържа 1) извличане на времетраенето на песента; 2) превъртане; 3)
SV8.  Все пак, поне последното определено си струва да бъде реализирано.
Ще се радвам на насоки, съвети и тестване.

Заб.: Адресът в полето Vcs-Hg не е правилен и `debcheckout' връща
грешка, ползвам директно това хранилище:

http://hg.debian.org/hg/xine-lib/pkg/xine-lib-1.1.8-deb/

[1] http://trac.musepack.net/trac/wiki/SV8Specification
diff -r dd91981c4d48 configure.ac
--- a/configure.ac      Tue Apr 07 22:34:53 2009 +0100
+++ b/configure.ac      Thu Jun 04 13:29:58 2009 +0300
@@ -1341,8 +1341,10 @@
 if test "x$enable_musepack" = "xno"; then
    AC_MSG_RESULT([musepack support disabled])
 elif test "x$with_external_libmpcdec" = "xyes"; then
-   AC_CHECK_LIB([mpcdec], [mpc_decoder_decode], [have_mpcdec=yes])
-   AC_CHECK_HEADERS([mpcdec/mpcdec.h], , [have_mpcdec=no])
+   AC_CHECK_LIB([mpcdec], [mpc_demux_decode], [have_mpcdec=yes],
+   [AC_CHECK_LIB([mpcdec], [mpc_decoder_decode], [have_mpcdec=yes])])
+   AC_CHECK_HEADERS([mpc/mpcdec.h], [],
+   [AC_CHECK_HEADERS([mpcdec/mpcdec.h], [], [have_mpcdec=no])])
    if test "x$have_mpcdec" != "xyes"; then
       AC_MSG_ERROR([Unable to find mpcdec])
    fi
diff -r dd91981c4d48 src/libmusepack/xine_musepack_decoder.c
--- a/src/libmusepack/xine_musepack_decoder.c   Tue Apr 07 22:34:53 2009 +0100
+++ b/src/libmusepack/xine_musepack_decoder.c   Thu Jun 04 13:29:58 2009 +0300
@@ -47,6 +47,8 @@
 
 #ifdef HAVE_MPCDEC_MPCDEC_H
 # include <mpcdec/mpcdec.h>
+#elif defined(HAVE_MPC_MPCDEC_H)
+# include <mpc/mpcdec.h>
 #else
 # include "musepack/musepack.h"
 #endif
@@ -78,7 +80,11 @@
 
   mpc_reader       reader;
   mpc_streaminfo   streaminfo;
+#ifndef HAVE_MPC_MPCDEC_H
   mpc_decoder      decoder;
+#else
+  mpc_demux       *decoder;
+#endif
   
   int              decoder_ok;
   unsigned int     current_frame;
@@ -93,8 +99,13 @@
  *************************************************************************/
     
 /* Reads size bytes of data into buffer at ptr. */
+#ifndef HAVE_MPC_MPCDEC_H
 static int32_t mpc_reader_read(void *data, void *ptr, int size) {
   mpc_decoder_t *this = (mpc_decoder_t *) data;
+#else
+static int32_t mpc_reader_read(mpc_reader *data, void *ptr, int size) {
+  mpc_decoder_t *this = (mpc_decoder_t *) data->data;
+#endif
   
   lprintf("mpc_reader_read: size=%d\n", size);
   
@@ -112,8 +123,13 @@
 }
  
 /* Seeks to byte position offset. */
+#ifndef HAVE_MPC_MPCDEC_H
 static mpc_bool_t mpc_reader_seek(void *data, int32_t offset) {
   mpc_decoder_t *this = (mpc_decoder_t *) data;
+#else
+static mpc_bool_t mpc_reader_seek(mpc_reader *data, int32_t offset) {
+  mpc_decoder_t *this = (mpc_decoder_t *) data->data;
+#endif
   
   lprintf("mpc_reader_seek: offset=%d\n", offset);
   
@@ -121,11 +137,19 @@
    * that the buffer starts at the start of the file */
   this->read = offset;
   
+#ifndef HAVE_MPC_MPCDEC_H
   return TRUE;
+#else
+  return MPC_TRUE;
+#endif
 }
 
 /* Returns the current byte offset in the stream. */
+#ifndef HAVE_MPC_MPCDEC_H
 static int32_t mpc_reader_tell(void *data) {
+#else
+static int32_t mpc_reader_tell(mpc_reader *data) {
+#endif
   lprintf("mpc_reader_tell\n");
   
   /* Tell isn't used so just return 0 */
@@ -133,8 +157,13 @@
 }
 
 /* Returns the total length of the source stream, in bytes. */
+#ifndef HAVE_MPC_MPCDEC_H
 static int32_t mpc_reader_get_size(void *data) {
   mpc_decoder_t *this = (mpc_decoder_t *) data;
+#else
+static int32_t mpc_reader_get_size(mpc_reader *data) {
+  mpc_decoder_t *this = (mpc_decoder_t *) data->data;
+#endif
   
   lprintf("mpc_reader_get_size\n");
   
@@ -142,10 +171,17 @@
 }
 
 /* True if the stream is a seekable stream. */
+#ifndef HAVE_MPC_MPCDEC_H
 static mpc_bool_t mpc_reader_canseek(void *data) {
   lprintf("mpc_reader_canseek\n");
   
   return TRUE;
+#else
+static mpc_bool_t mpc_reader_canseek(mpc_reader *data) {
+
+  lprintf("mpc_reader_canseek\n");
+  return MPC_TRUE;
+#endif
 }
 
 /* Convert 32bit float samples into 16bit int samples */
@@ -165,10 +201,19 @@
 static int mpc_decode_frame (mpc_decoder_t *this) {
   float buffer[MPC_DECODER_BUFFER_LENGTH];
   uint32_t frames;
+#ifdef HAVE_MPC_MPCDEC_H
+  mpc_frame_info frame;
+#endif
   
   lprintf("mpd_decode_frame\n");
   
+#ifndef HAVE_MPC_MPCDEC_H
   frames = mpc_decoder_decode(&this->decoder, buffer, 0, 0);
+#else
+  frame.buffer = buffer;
+  mpc_demux_decode(this->decoder, &frame);
+  frames = frame.samples;
+#endif
   
   if (frames > 0) {
     audio_buffer_t *audio_buffer;  
@@ -235,6 +280,16 @@
     xine_fast_memcpy(this->buf, buf->content, buf->size);
     this->size = buf->size;
     
+#ifdef HAVE_MPC_MPCDEC_H
+    this->decoder = mpc_demux_init(&this->reader);
+    if (!this->decoder) {
+      xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+             _("libmusepack: mpc_demux_init failed.\n"));
+      _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0);
+      return;
+    }
+    mpc_demux_get_info(this->decoder, &this->streaminfo);
+#else
     /* Initialise and read stream info */
     mpc_streaminfo_init(&this->streaminfo);
     
@@ -245,6 +300,7 @@
       _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0);
       return;
     }
+#endif
     
     this->sample_rate     = this->streaminfo.sample_freq;
     this->channels        = this->streaminfo.channels;
@@ -259,7 +315,9 @@
     this->current_frame = 0;
         
     /* Setup the decoder */
+#ifndef HAVE_MPC_MPCDEC_H
     mpc_decoder_setup(&this->decoder, &this->reader);
+#endif
     this->decoder_ok = 0;
 
     /* Take this opportunity to initialize stream/meta information */
@@ -312,7 +370,11 @@
   /* Time to decode */
   if (buf->decoder_flags & BUF_FLAG_FRAME_END)  {
     /* Increment frame count */
+#ifndef HAVE_MPC_MPCDEC_H
     if (this->current_frame++ == this->streaminfo.frames) {
+#else
+    if (this->current_frame++ == this->streaminfo.samples) {
+#endif
       xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
               _("libmusepack: data after last frame ignored\n"));
       return;
@@ -323,7 +385,11 @@
       if ((this->size - this->read) >= MPC_DECODER_MEMSIZE) {
         lprintf("initialise");
       
+#ifndef HAVE_MPC_MPCDEC_H
         if (!mpc_decoder_initialize(&this->decoder, &this->streaminfo)) {
+#else
+        if (!this->decoder) {
+#endif
           xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
                   _("libmusepack: mpc_decoder_initialise failed\n"));        
           
@@ -354,7 +420,11 @@
     
     /* If we are at the end of the stream we decode the remaining frames as we
      * know we'll have enough data */
+#ifndef HAVE_MPC_MPCDEC_H
     if (this->current_frame == this->streaminfo.frames) {
+#else
+    if (this->current_frame == this->streaminfo.samples) {
+#endif
       lprintf("flushing buffers\n");
       
       do {
@@ -392,6 +462,10 @@
   /* free anything that was allocated during operation */
   if (this->buf)
     free(this->buf);
+#ifdef HAVE_MPC_MPCDEC_H
+  if (this->decoder)
+    mpc_demux_exit(this->decoder);
+#endif
   
   free(this);
 }

reply via email to

[Prev in Thread] Current Thread [Next in Thread]