Ticket #37159: patch-moc-2.5.0-beta1.diff

File patch-moc-2.5.0-beta1.diff, 28.1 KB (added by dbevans (David B. Evans), 11 years ago)

Proposed patch with ffmeg fixes

  • Portfile

     
    33PortSystem          1.0
    44
    55name                moc
    6 version             2.4.4
    7 revision            2
     6version             2.5.0-beta1
     7license             GPL-2
    88categories          multimedia
    99maintainers         martinvazquez.net:eu
    1010description         MOC (music on console) is a console audio player for LINUX/UNIX
     
    1818
    1919homepage            http://moc.daper.net
    2020platforms           darwin
    21 master_sites        ftp://ftp.daper.net/pub/soft/moc/stable/
     21master_sites        ftp://ftp.daper.net/pub/soft/moc/unstable/
    2222
    23 checksums           md5     647c770a5542a4ae5437386807a89796 \
    24                     sha1    e56ee13aa17c177f0afc42efe3804ebbbf46d4db \
    25                     rmd160  d757650b3d8ed4f830212f41d12af7144ecba29b
     23checksums           md5     795ecba86847e082aa2f21937cc04804 \
     24                    sha1    4030a1fa5c7cfef06909c54d8c7a1fbb93f23caa \
     25                    rmd160  ca7095f71e5fe8155eda41e98547db541d6a4cab
    2626
    2727use_bzip2           yes
    2828
     
    3838                    port:jack \
    3939                    port:curl
    4040
    41 patchfiles          patch-configure.diff \
    42                     patch-options.c.diff
     41patchfiles              patch-ffmpeg-r2529.diff
    4342
    44 configure.args      --with-jack --without-vorbis
     43use_autoreconf      yes
     44autoreconf.args     -fvi
    4545
    46 default_variants    +autojack
     46configure.args      --with-jack --without-vorbis --disable-cache
    4747
    48 variant autojack description {Autostart jack on mocp init and close it on server stop} {
    49         patchfiles-append       patch-autojack.diff
    50 }
     48#default_variants    +autojack
    5149
     50#variant autojack description {Autostart jack on mocp init and close it on server stop} {
     51#        patchfiles-append       patch-autojack.diff
     52#}
     53
    5254variant vorbis description {Add support for ogg files} {
    5355        depends_lib-append      port:libvorbis
    5456        configure.args-delete   --without-vorbis
    5557}
     58
     59livecheck.regex     <title>music on console (.*)</title>
  • files/patch-ffmpeg-r2529.diff

     
     1Index: THANKS
     2===================================================================
     3--- THANKS      (revision 2506)
     4+++ THANKS      (revision 2529)
     5@@ -10,6 +10,9 @@
     6        * Fixed miscellaneous coding errors.
     7        * Assisted with testing.
     8 
     9+Gregory Maxwell:
     10+       * Provided patch for off_t in io_* functions.
     11+
     12 Morten Grunnet Buhl:
     13        * Provided Yellow/Red theme.
     14 
     15@@ -44,6 +47,7 @@
     16        * Headed the effort to port MOC to OpenWRT.
     17        * Provided signficant information on DTS, AAC and other formats.
     18        * Also contributed much time in the refinement of feature ideas.
     19+       * Provided 24-bit format conversion bug fixes.
     20 
     21 Juho Hämäläinen:
     22        * Added -Q (--format) FORMAT_STRING option to display file information.
     23@@ -202,6 +206,9 @@
     24        * Fixed segfault when trying to play a file using FFmpeg.
     25        * Migrated to newer FFmpeg API.
     26 
     27+"firejox"
     28+       * Fixed screen upsets due to UTF-8 character handing.
     29+
     30 "fluxid":
     31        * Fixed incorrect setting for themes red channel value.
     32 
     33Index: mocp.1
     34===================================================================
     35--- mocp.1      (revision 2506)
     36+++ mocp.1      (revision 2529)
     37@@ -69,6 +69,11 @@
     38 set in the configuration file as \fBStartInMusicDir\fP.
     39 .LP
     40 .TP
     41+\fB\-q\fP, \fB\-\-enqueue\fP
     42+Add files given after command line options to the queue.  Don't start the
     43+interface.
     44+.LP
     45+.TP
     46 \fB\-a\fP, \fB\-\-append\fP
     47 Append files, directories (recursively) and playlists given after command
     48 line options to the playlist.  Don't start the interface.
     49Index: menu.c
     50===================================================================
     51--- menu.c      (revision 2506)
     52+++ menu.c      (revision 2529)
     53@@ -90,9 +90,14 @@
     54        getyx (menu->win, y, x);
     55        if (title_width <= title_space || mi->align == MENU_ALIGN_LEFT)
     56                xwaddnstr (menu->win, mi->title, title_space);
     57-       else
     58-               xwaddstr (menu->win, mi->title + title_width - title_space);
     59+       else {
     60+               char *ptr;
     61 
     62+               ptr = xstrtail (mi->title, title_space);
     63+               xwaddstr (menu->win, ptr);
     64+               free (ptr);
     65+       }
     66+
     67        /* Fill the remainder of the title field with spaces. */
     68        if (mi == menu->selected) {
     69                getyx (menu->win, y, ix);
     70Index: configure.in
     71===================================================================
     72--- configure.in        (revision 2506)
     73+++ configure.in        (revision 2529)
     74@@ -142,7 +142,7 @@
     75 
     76 PKG_PROG_PKG_CONFIG([0.20])
     77 
     78-if test "x$PKG_CONFIG" == "x"
     79+if test "x$PKG_CONFIG" = "x"
     80 then
     81        AC_MSG_WARN([No pkg-config utility found or it's too old, I will have trouble finding installed libraries.])
     82 fi
     83@@ -293,7 +293,6 @@
     84 
     85 dnl optional functions
     86 AC_CHECK_FUNCS([strcasestr strerror_r syslog])
     87-AC_CHECK_FUNCS([getrlimit pthread_attr_getstacksize])
     88 AX_CHECK_UNAME_SYSCALL
     89 
     90 dnl MIME magic
     91@@ -322,6 +321,7 @@
     92 CC="$PTHREAD_CC"
     93 CFLAGS="$PTHREAD_CFLAGS $CFLAGS"
     94 EXTRA_LIBS="$EXTRA_LIBS $PTHREAD_LIBS"
     95+AC_CHECK_FUNCS([getrlimit pthread_attr_getstacksize])
     96 
     97 dnl __FUNCTION__
     98 AC_TRY_COMPILE(,[printf(__FUNCTION__);], [AC_DEFINE([HAVE__FUNCTION__], 1,
     99@@ -342,7 +342,7 @@
     100 fi
     101 
     102 dnl popt
     103-AC_SEARCH_LIBS([poptGetContext], [popt], , [POPT_MISSING="yes"])
     104+AC_CHECK_LIB([popt], [poptGetContext], [true], [POPT_MISSING="yes"])
     105 
     106 dnl getopt
     107 AC_CHECK_FUNC(getopt_long,
     108Index: utf8.c
     109===================================================================
     110--- utf8.c      (revision 2506)
     111+++ utf8.c      (revision 2529)
     112@@ -199,47 +199,50 @@
     113 
     114 int xwaddnstr (WINDOW *win, const char *str, const int n)
     115 {
     116-       int res;
     117+       int res, width, inv_char;
     118+       wchar_t *ucs;
     119+       char *mstr, *lstr;
     120+       size_t size, num_chars;
     121 
     122        assert (n > 0);
     123        assert (str != NULL);
     124 
     125-       if (using_utf8) {
     126+       mstr = iconv_str (iconv_desc, str);
     127 
     128-               /* This nasty hack is because we need to count n in chars, but
     129-                * [w]addnstr() takes arguments in bytes (in UTF-8 a char can be
     130-                * longer than 1 byte).  There are also problems with [w]addnwstr()
     131-                * (screen garbled).  I have no better idea. */
     132+       size = xmbstowcs (NULL, mstr, -1, NULL) + 1;
     133+       ucs = (wchar_t *)xmalloc (sizeof(wchar_t) * size);
     134+       xmbstowcs (ucs, mstr, size, &inv_char);
     135+       width = wcswidth (ucs, WIDTH_MAX);
     136 
     137-               wchar_t *ucs;
     138-               size_t size;
     139-               size_t utf_num_chars;
     140-               int inv_char;
     141-
     142-               size = xmbstowcs (NULL, str, -1, NULL) + 1;
     143-               ucs = (wchar_t *)xmalloc (sizeof(wchar_t) * size);
     144-               xmbstowcs (ucs, str, size, &inv_char);
     145-               if ((size_t)n < size - 1)
     146-                       ucs[n] = L'\0';
     147-               utf_num_chars = wcstombs (NULL, ucs, 0);
     148-               if (inv_char) {
     149-                       char *utf8 = (char *)xmalloc (utf_num_chars + 1);
     150-
     151-                       wcstombs (utf8, ucs, utf_num_chars + 1);
     152-                       res = waddstr (win, utf8);
     153-                       free (utf8);
     154+       if (width == -1) {
     155+               size_t clidx;
     156+               for (clidx = 0; clidx < size - 1; clidx++) {
     157+                       if (wcwidth (ucs[clidx]) == -1)
     158+                               ucs[clidx] = L'?';
     159                }
     160-               else
     161-                       res = waddnstr (win, str, utf_num_chars);
     162-               free (ucs);
     163+               width = wcswidth (ucs, WIDTH_MAX);
     164+               inv_char = 1;
     165        }
     166-       else {
     167-               char *lstr = iconv_str (iconv_desc, str);
     168 
     169-               res = waddnstr (win, lstr, n);
     170-               free (lstr);
     171+       if (width > n) {
     172+               while (width > n)
     173+                       width -= wcwidth (ucs[--size]);
     174+               ucs[size] = L'\0';
     175        }
     176 
     177+       num_chars = wcstombs (NULL, ucs, 0);
     178+       lstr = (char *)xmalloc (num_chars + 1);
     179+
     180+       if (inv_char)
     181+               wcstombs (lstr, ucs, num_chars + 1);
     182+       else
     183+               snprintf (lstr, num_chars + 1, "%s", mstr);
     184+
     185+       res = waddstr (win, lstr);
     186+
     187+       free (ucs);
     188+       free (lstr);
     189+       free (mstr);
     190        return res;
     191 }
     192 
     193Index: audio_conversion.c
     194===================================================================
     195--- audio_conversion.c  (revision 2506)
     196+++ audio_conversion.c  (revision 2529)
     197@@ -189,7 +189,7 @@
     198        size_t i;
     199 
     200        /* maximum and minimum values of 32-bit samples */
     201-       const unsigned int U32_MAX = (1 << 24);
     202+       const unsigned int U32_MAX = (1 << 24) - 1;
     203        const int S32_MAX = (1 << 23) - 1;
     204        const int S32_MIN = -(1 << 23);
     205 
     206@@ -201,7 +201,7 @@
     207                float f = in[i] * S32_MAX;
     208 
     209                if (f >= S32_MAX)
     210-                       *out_val = U32_MAX;
     211+                       *out_val = U32_MAX << 8;
     212                else if (f <= S32_MIN)
     213                        *out_val = 0;
     214                else {
     215@@ -231,9 +231,9 @@
     216                float f = in[i] * S32_MAX;
     217 
     218                if (f >= S32_MAX)
     219-                       *out_val = S32_MAX;
     220+                       *out_val = S32_MAX << 8;
     221                else if (f <= S32_MIN)
     222-                       *out_val = S32_MIN;
     223+                       *out_val = S32_MIN << 8;
     224                else {
     225 #ifdef HAVE_LRINTF
     226                        *out_val = lrintf(f) << 8;
     227Index: io.c
     228===================================================================
     229--- io.c        (revision 2506)
     230+++ io.c        (revision 2529)
     231@@ -141,20 +141,20 @@
     232 }
     233 
     234 #ifdef HAVE_MMAP
     235-static off_t io_seek_mmap (struct io_stream *s, const long where)
     236+static off_t io_seek_mmap (struct io_stream *s, const off_t where)
     237 {
     238-       assert (RANGE(0, where, (long)s->size));
     239+       assert (RANGE(0, where, (off_t)s->size));
     240 
     241        return (s->mem_pos = where);
     242 }
     243 #endif
     244 
     245-static off_t io_seek_fd (struct io_stream *s, const int where)
     246+static off_t io_seek_fd (struct io_stream *s, const off_t where)
     247 {
     248        return lseek (s->fd, where, SEEK_SET);
     249 }
     250 
     251-static off_t io_seek_buffered (struct io_stream *s, const long where)
     252+static off_t io_seek_buffered (struct io_stream *s, const off_t where)
     253 {
     254        off_t res = -1;
     255 
     256@@ -180,7 +180,7 @@
     257        return res;
     258 }
     259 
     260-static off_t io_seek_unbuffered (struct io_stream *s, const long where)
     261+static off_t io_seek_unbuffered (struct io_stream *s, const off_t where)
     262 {
     263        off_t res = -1;
     264 
     265Index: decoder_plugins/mp3/mp3.c
     266===================================================================
     267--- decoder_plugins/mp3/mp3.c   (revision 2506)
     268+++ decoder_plugins/mp3/mp3.c   (revision 2529)
     269@@ -696,17 +696,19 @@
     270 {
     271        char *ext;
     272 
     273+       strcpy (buf, "MPx");
     274+
     275        ext = ext_pos (file);
     276-       if (!strcasecmp (ext, "mp3"))
     277-               strcpy (buf, "MP3");
     278-       else if (!strcasecmp (ext, "mp2"))
     279-               strcpy (buf, "MP2");
     280-       else if (!strcasecmp (ext, "mp1"))
     281-               strcpy (buf, "MP1");
     282-       else if (!strcasecmp (ext, "mpga"))
     283-               strcpy (buf, "MPG");
     284-       else
     285-               strcpy (buf, "MPx");
     286+       if (ext) {
     287+               if (!strcasecmp (ext, "mp3"))
     288+                       strcpy (buf, "MP3");
     289+               else if (!strcasecmp (ext, "mp2"))
     290+                       strcpy (buf, "MP2");
     291+               else if (!strcasecmp (ext, "mp1"))
     292+                       strcpy (buf, "MP1");
     293+               else if (!strcasecmp (ext, "mpga"))
     294+                       strcpy (buf, "MPG");
     295+       }
     296 }
     297 
     298 static int mp3_our_format_ext (const char *ext)
     299Index: decoder_plugins/ffmpeg/ffmpeg.m4
     300===================================================================
     301--- decoder_plugins/ffmpeg/ffmpeg.m4    (revision 2506)
     302+++ decoder_plugins/ffmpeg/ffmpeg.m4    (revision 2529)
     303@@ -88,6 +88,27 @@
     304                                 [#include <libavcodec/avcodec.h>])
     305                AC_CHECK_DECLS([AV_CODEC_ID_OPUS], , ,
     306                                 [#include <libavcodec/avcodec.h>])
     307+               AC_SEARCH_LIBS(avcodec_free_frame, avcodec,
     308+                       [AC_DEFINE([HAVE_AVCODEC_FREE_FRAME], 1,
     309+                               [Define to 1 if you have the `avcodec_free_frame' function.])])
     310+               AC_CHECK_DECLS([CODEC_ID_PCM_S8_PLANAR], , ,
     311+                                [#include <libavcodec/avcodec.h>])
     312+               AC_CHECK_DECLS([AV_SAMPLE_FMT_U8P], , ,
     313+                                [#include <libavcodec/avcodec.h>])
     314+               AC_CHECK_DECLS([AV_SAMPLE_FMT_S16P], , ,
     315+                                [#include <libavcodec/avcodec.h>])
     316+               AC_CHECK_DECLS([AV_SAMPLE_FMT_S32P], , ,
     317+                                [#include <libavcodec/avcodec.h>])
     318+               AC_CHECK_DECLS([AV_SAMPLE_FMT_FLTP], , ,
     319+                                [#include <libavcodec/avcodec.h>])
     320+               AC_CHECK_DECLS([CODEC_CAP_EXPERIMENTAL], , ,
     321+                                [#include <libavcodec/avcodec.h>])
     322+               AC_SEARCH_LIBS(av_get_sample_fmt_name, avutil,
     323+                       [AC_DEFINE([HAVE_AV_GET_SAMPLE_FMT_NAME], 1,
     324+                               [Define to 1 if you have the `av_get_sample_fmt_name' function.])])
     325+               AC_SEARCH_LIBS(av_lockmgr_register, avcodec,
     326+                       [AC_DEFINE([HAVE_LOCKMGR_REGISTER], 1,
     327+                               [Define to 1 if you have the `av_lockmgr_register' function.])])
     328                CPPFLAGS="$save_CPPFLAGS"
     329                CFLAGS="$save_CFLAGS"
     330                LIBS="$save_LIBS"
     331Index: decoder_plugins/ffmpeg/ffmpeg.c
     332===================================================================
     333--- decoder_plugins/ffmpeg/ffmpeg.c     (revision 2506)
     334+++ decoder_plugins/ffmpeg/ffmpeg.c     (revision 2529)
     335@@ -99,6 +99,7 @@
     336        bool okay; /* was this stream successfully opened? */
     337        struct decoder_error error;
     338        long fmt;
     339+       int sample_width;
     340        int bitrate;            /* in bits per second */
     341        int avg_bitrate;        /* in bits per second */
     342 #if SEEK_IN_DECODER
     343@@ -106,6 +107,7 @@
     344        int seek_sec;           /* second to which to seek */
     345 #endif
     346        bool seek_broken;       /* FFmpeg seeking is broken */
     347+       bool timing_broken;     /* FFmpeg trashes duration and bit_rate */
     348 #if SEEK_IN_DECODER && defined(DEBUG)
     349        pthread_t thread_id;
     350 #endif
     351@@ -277,8 +279,72 @@
     352        }
     353 }
     354 
     355+/* Handle FFmpeg's locking requirements. */
     356+#ifdef HAVE_LOCKMGR_REGISTER
     357+static int locking_cb (void **mutex, enum AVLockOp op)
     358+{
     359+       int result;
     360+
     361+       switch (op) {
     362+       case AV_LOCK_CREATE:
     363+               *mutex = xmalloc (sizeof (pthread_mutex_t));
     364+               result = pthread_mutex_init (*mutex, NULL);
     365+               break;
     366+       case AV_LOCK_OBTAIN:
     367+               result = pthread_mutex_lock (*mutex);
     368+               break;
     369+       case AV_LOCK_RELEASE:
     370+               result = pthread_mutex_unlock (*mutex);
     371+               break;
     372+       case AV_LOCK_DESTROY:
     373+               result = pthread_mutex_destroy (*mutex);
     374+               free (*mutex);
     375+               *mutex = NULL;
     376+               break;
     377+       }
     378+
     379+       return result;
     380+}
     381+#endif
     382+
     383+/* Here we attempt to determine if FFmpeg/LibAV has trashed the 'duration'
     384+ * and 'bit_rate' fields in AVFormatContext for large files.  Determining
     385+ * whether or not they are likely to be valid is imprecise and will vary
     386+ * depending (at least) on:
     387+ *
     388+ * - The file's size,
     389+ * - The file's codec,
     390+ * - The number and size of tags,
     391+ * - The version of FFmpeg/LibAV, and
     392+ * - Whether it's FFmpeg or LibAV.
     393+ *
     394+ * This function represents a best guess.
     395+*/
     396+static bool is_timing_broken (AVFormatContext *ic)
     397+{
     398+       int64_t file_size;
     399+
     400+       if (ic->duration < 0 || ic->bit_rate < 0)
     401+               return true;
     402+
     403+#ifdef HAVE_AVIO_SIZE
     404+       file_size = avio_size (ic->pb);
     405+#else
     406+       file_size = ic->file_size;
     407+#endif
     408+
     409+       if (file_size < UINT32_MAX)
     410+               return false;
     411+
     412+       return true;
     413+}
     414+
     415 static void ffmpeg_init ()
     416 {
     417+#ifdef HAVE_LOCKMGR_REGISTER
     418+       int rc;
     419+#endif
     420+
     421 #ifdef DEBUG
     422        av_log_set_level (AV_LOG_INFO);
     423 #else
     424@@ -291,10 +357,20 @@
     425        supported_extns = lists_strs_new (16);
     426        load_audio_extns (supported_extns);
     427        load_video_extns (supported_extns);
     428+
     429+#ifdef HAVE_LOCKMGR_REGISTER
     430+       rc = av_lockmgr_register (locking_cb);
     431+       if (rc < 0)
     432+               fatal ("Lock manager initialisation failed");
     433+#endif
     434 }
     435 
     436 static void ffmpeg_destroy ()
     437 {
     438+#ifdef HAVE_LOCKMGR_REGISTER
     439+       av_lockmgr_register (NULL);
     440+#endif
     441+
     442        av_log_set_level (AV_LOG_QUIET);
     443        ffmpeg_log_repeats (NULL);
     444 
     445@@ -341,9 +417,9 @@
     446        }
     447 #endif
     448 
     449-       if (tags_sel & TAGS_TIME) {
     450+       if (!is_timing_broken (ic) && tags_sel & TAGS_TIME) {
     451                info->time = -1;
     452-               if (ic->duration >= 0)
     453+               if (ic->duration != (int64_t)AV_NOPTS_VALUE && ic->duration >= 0)
     454                        info->time = ic->duration / AV_TIME_BASE;
     455        }
     456 
     457@@ -426,12 +502,6 @@
     458 
     459 #endif
     460 
     461-       if (tags_sel & TAGS_TIME) {
     462-               info->time = -1;
     463-               if (ic->duration != (int64_t)AV_NOPTS_VALUE && ic->duration >= 0)
     464-                       info->time = ic->duration / AV_TIME_BASE;
     465-       }
     466-
     467 end:
     468 #ifdef HAVE_AVFORMAT_CLOSE_INPUT
     469        avformat_close_input (&ic);
     470@@ -450,6 +520,9 @@
     471                if (!strcmp (data->ic->iformat->name, "wav")) {
     472                        switch (data->enc->codec_id) {
     473                        case CODEC_ID_PCM_S8:
     474+#if HAVE_DECL_CODEC_ID_PCM_S8_PLANAR
     475+                       case CODEC_ID_PCM_S8_PLANAR:
     476+#endif
     477                                result = SFMT_S8;
     478                                break;
     479                        case CODEC_ID_PCM_U8:
     480@@ -456,6 +529,7 @@
     481                                result = SFMT_U8;
     482                                break;
     483                        case CODEC_ID_PCM_S16LE:
     484+                       case CODEC_ID_PCM_S16LE_PLANAR:
     485                        case CODEC_ID_PCM_S16BE:
     486                                result = SFMT_S16;
     487                                break;
     488@@ -490,15 +564,27 @@
     489 
     490        switch (data->enc->sample_fmt) {
     491        case AV_SAMPLE_FMT_U8:
     492+#if HAVE_DECL_AV_SAMPLE_FMT_U8P
     493+       case AV_SAMPLE_FMT_U8P:
     494+#endif
     495                result = SFMT_U8;
     496                break;
     497        case AV_SAMPLE_FMT_S16:
     498+#if HAVE_DECL_AV_SAMPLE_FMT_S16P
     499+       case AV_SAMPLE_FMT_S16P:
     500+#endif
     501                result = SFMT_S16;
     502                break;
     503        case AV_SAMPLE_FMT_S32:
     504+#if HAVE_DECL_AV_SAMPLE_FMT_S32P
     505+       case AV_SAMPLE_FMT_S32P:
     506+#endif
     507                result = SFMT_S32;
     508                break;
     509        case AV_SAMPLE_FMT_FLT:
     510+#if HAVE_DECL_AV_SAMPLE_FMT_FLTP
     511+       case AV_SAMPLE_FMT_FLTP:
     512+#endif
     513                result = SFMT_FLOAT;
     514                break;
     515        default:
     516@@ -597,6 +683,7 @@
     517        data->stream = NULL;
     518        data->enc = NULL;
     519        data->codec = NULL;
     520+       data->sample_width = 0;
     521        data->bitrate = 0;
     522        data->avg_bitrate = 0;
     523 
     524@@ -624,6 +711,7 @@
     525        data->seek_sec = 0;
     526 #endif
     527        data->seek_broken = false;
     528+       data->timing_broken = false;
     529 
     530        decoder_error_init (&data->error);
     531 
     532@@ -655,6 +743,9 @@
     533        err = av_find_stream_info (data->ic);
     534 #endif
     535        if (err < 0) {
     536+               /* Depending on the particular FFmpeg/LibAV version in use, this
     537+                * may misreport experimental codecs.  Given we don't know the
     538+                * codec at this time, we will have to live with it. */
     539                decoder_error (&data->error, ERROR_FATAL, 0,
     540                                "Could not find codec parameters (err %d)",
     541                                err);
     542@@ -683,6 +774,19 @@
     543        debug ("FFmpeg thinks '%s' is format(codec) '%s(%s)'",
     544                fn, data->ic->iformat->name, data->codec->name);
     545 
     546+#if HAVE_DECL_CODEC_CAP_EXPERIMENTAL
     547+       /* This may or may not work depending on the particular version of
     548+        * FFmpeg/LibAV in use.  For some versions this will be caught in
     549+        * *_find_stream_info() above and misreported as an unfound codec
     550+        * parameters error. */
     551+       if (data->codec->capabilities & CODEC_CAP_EXPERIMENTAL) {
     552+               decoder_error (&data->error, ERROR_FATAL, 0,
     553+                               "The codec is experimental and may damage MOC: %s",
     554+                               data->codec->name);
     555+               goto end;
     556+       }
     557+#endif
     558+
     559        set_downmixing (data);
     560        if (data->codec->capabilities & CODEC_CAP_TRUNCATED)
     561                data->enc->flags |= CODEC_FLAG_TRUNCATED;
     562@@ -702,27 +806,38 @@
     563        if (data->fmt == 0)
     564                data->fmt = fmt_from_sample_fmt (data);
     565        if (data->fmt == 0) {
     566+#ifdef HAVE_AV_GET_SAMPLE_FMT_NAME
     567                decoder_error (&data->error, ERROR_FATAL, 0,
     568+                              "Cannot get sample size from unknown sample format: %s",
     569+                              av_get_sample_fmt_name (data->enc->sample_fmt));
     570+#else
     571+               decoder_error (&data->error, ERROR_FATAL, 0,
     572                               "Unsupported sample size!");
     573+#endif
     574+               avcodec_close (data->enc);
     575                goto end;
     576        }
     577+       data->sample_width = sfmt_Bps (data->fmt);
     578        if (data->codec->capabilities & CODEC_CAP_DELAY)
     579                data->delay = true;
     580        data->seek_broken = is_seek_broken (data);
     581+       data->timing_broken = is_timing_broken (data->ic);
     582 
     583        data->okay = true;
     584 
     585-       if (data->ic->duration >= AV_TIME_BASE) {
     586+       if (!data->timing_broken && data->ic->duration >= AV_TIME_BASE) {
     587 #ifdef HAVE_AVIO_SIZE
     588                data->avg_bitrate = (int) (avio_size (data->ic->pb) /
     589-                                         (data->ic->duration / AV_TIME_BASE) * 8);
     590+                                          (data->ic->duration / AV_TIME_BASE) * 8);
     591 #else
     592                data->avg_bitrate = (int) (data->ic->file_size /
     593-                                         (data->ic->duration / AV_TIME_BASE) * 8);
     594+                                          (data->ic->duration / AV_TIME_BASE) * 8);
     595 #endif
     596        }
     597-       data->bitrate = data->ic->bit_rate;
     598 
     599+       if (!data->timing_broken && data->ic->bit_rate > 0)
     600+               data->bitrate = data->ic->bit_rate;
     601+
     602        return data;
     603 
     604 end:
     605@@ -908,8 +1023,6 @@
     606                                            &data_size, pkt->data, pkt->size);
     607 #endif
     608 
     609-               debug ("Decoded %dB", data_size);
     610-
     611                if (len < 0)  {
     612                        /* skip frame */
     613                        decoder_error (&data->error, ERROR_STREAM, 0, "Error in the stream!");
     614@@ -916,14 +1029,16 @@
     615                        break;
     616                }
     617 
     618+               debug ("Decoded %dB", data_size);
     619+
     620+               pkt->data += len;
     621+               pkt->size -= len;
     622+
     623                if (data->eof && data_size == 0) {
     624                        data->eos = true;
     625                        break;
     626                }
     627 
     628-               pkt->data += len;
     629-               pkt->size -= len;
     630-
     631                copied = copy_or_buffer (data, data->avbuf, data_size, buf, buf_len);
     632 
     633                buf += copied;
     634@@ -943,12 +1058,15 @@
     635                           char *buf, int buf_len)
     636 {
     637        int filled = 0;
     638+       char *packed;
     639+       AVFrame *frame;
     640 
     641+       frame = avcodec_alloc_frame ();
     642+
     643        do {
     644-               int len, got_frame, is_planar, plane_size, data_size, copied;
     645-               AVFrame frame;
     646+               int len, got_frame, is_planar, packed_size, copied;
     647 
     648-               len = avcodec_decode_audio4 (data->enc, &frame, &got_frame, pkt);
     649+               len = avcodec_decode_audio4 (data->enc, frame, &got_frame, pkt);
     650 
     651                if (len < 0)  {
     652                        /* skip frame */
     653@@ -956,45 +1074,56 @@
     654                        break;
     655                }
     656 
     657-               if (!got_frame) {
     658-                       data->eos = data->eof;
     659-                       break;
     660-               }
     661-
     662                debug ("Decoded %dB", len);
     663 
     664                pkt->data += len;
     665                pkt->size -= len;
     666 
     667-               is_planar = av_sample_fmt_is_planar (data->enc->sample_fmt);
     668-               data_size = av_samples_get_buffer_size (&plane_size,
     669-                                                       data->enc->channels,                                                   frame.nb_samples,
     670-                                                       data->enc->sample_fmt, 1);
     671+               if (!got_frame) {
     672+                       data->eos = data->eof && (pkt->size == 0);
     673+                       continue;
     674+               }
     675 
     676-               if (data_size == 0)
     677+               if (frame->nb_samples == 0)
     678                        continue;
     679 
     680-               copied = copy_or_buffer (data, (char *)frame.extended_data[0],
     681-                                        plane_size, buf, buf_len);
     682+               is_planar = av_sample_fmt_is_planar (data->enc->sample_fmt);
     683+               packed = (char *)frame->extended_data[0];
     684+               packed_size = frame->nb_samples * data->sample_width
     685+                                               * data->enc->channels;
     686+
     687+               if (is_planar && data->enc->channels > 1) {
     688+                       int sample, ch;
     689+
     690+                       packed = xmalloc (packed_size);
     691+
     692+                       for (sample = 0; sample < frame->nb_samples; sample += 1) {
     693+                               for (ch = 0; ch < data->enc->channels; ch += 1)
     694+                                       memcpy (packed + (sample * data->enc->channels + ch)
     695+                                                                * data->sample_width,
     696+                                               (char *)frame->extended_data[ch] + sample * data->sample_width,
     697+                                               data->sample_width);
     698+                       }
     699+               }
     700+
     701+               copied = copy_or_buffer (data, packed, packed_size, buf, buf_len);
     702                buf += copied;
     703                filled += copied;
     704                buf_len -= copied;
     705 
     706-        if (is_planar && data->enc->channels > 1) {
     707-                       int ch;
     708+               debug ("Copying %dB (%dB filled)", packed_size, filled);
     709 
     710-            for (ch = 1; ch < data->enc->channels; ch += 1) {
     711-                               copied = copy_or_buffer (data, (char *)frame.extended_data[ch],
     712-                                                        plane_size, buf, buf_len);
     713-                               buf += copied;
     714-                               filled += copied;
     715-                               buf_len -= copied;
     716-            }
     717-        }
     718-
     719-               debug ("Copying %dB (%dB filled)", data_size, filled);
     720+               if (packed != (char *)frame->extended_data[0])
     721+                       free (packed);
     722        } while (pkt->size > 0);
     723 
     724+       avcodec_get_frame_defaults (frame);
     725+#ifdef HAVE_AVCODEC_FREE_FRAME
     726+       avcodec_free_frame (&frame);
     727+#else
     728+       av_freep (&frame);
     729+#endif
     730+
     731        return filled;
     732 }
     733 #endif
     734@@ -1122,9 +1251,10 @@
     735                free_packet (pkt);
     736        } while (!bytes_produced && !data->eos);
     737 
     738-       data->bitrate = compute_bitrate (sound_params, bytes_used,
     739-                                        bytes_produced + data->remain_buf_len,
     740-                                        data->bitrate);
     741+       if (!data->timing_broken)
     742+               data->bitrate = compute_bitrate (sound_params, bytes_used,
     743+                                                bytes_produced + data->remain_buf_len,
     744+                                                data->bitrate);
     745 
     746        return bytes_produced;
     747 }
     748@@ -1185,7 +1315,7 @@
     749 {
     750        struct ffmpeg_data *data = (struct ffmpeg_data *)prv_data;
     751 
     752-       return data->bitrate / 1000;
     753+       return data->timing_broken ? -1 : data->bitrate / 1000;
     754 }
     755 
     756 static int ffmpeg_get_avg_bitrate (void *prv_data)
     757@@ -1192,7 +1322,7 @@
     758 {
     759        struct ffmpeg_data *data = (struct ffmpeg_data *)prv_data;
     760 
     761-       return data->avg_bitrate / 1000;
     762+       return data->timing_broken ? -1 : data->avg_bitrate / 1000;
     763 }
     764 
     765 static int ffmpeg_get_duration (void *prv_data)
     766@@ -1199,6 +1329,9 @@
     767 {
     768        struct ffmpeg_data *data = (struct ffmpeg_data *)prv_data;
     769 
     770+       if (data->timing_broken)
     771+               return -1;
     772+
     773        if (!data->stream)
     774                return -1;
     775 
     776Index: decoder_plugins/vorbis/vorbis.c
     777===================================================================
     778--- decoder_plugins/vorbis/vorbis.c     (revision 2506)
     779+++ decoder_plugins/vorbis/vorbis.c     (revision 2529)
     780@@ -47,9 +47,9 @@
     781 
     782 /* Tremor defines time as 64-bit integer milliseconds. */
     783 #ifndef HAVE_TREMOR
     784-static const double time_scaler = 1;
     785+static const int64_t time_scaler = 1;
     786 #else
     787-static const ogg_int64_t time_scaler = 1000;
     788+static const int64_t time_scaler = 1000;
     789 #endif
     790 
     791 struct vorbis_data
     792@@ -171,11 +171,11 @@
     793                get_comment_tags (&vf, info);
     794 
     795        if (tags_sel & TAGS_TIME) {
     796-               int vorbis_time;
     797+               int64_t vorbis_time;
     798 
     799-           vorbis_time = ov_time_total (&vf, -1) / time_scaler;
     800-           if (vorbis_time >= 0)
     801-                       info->time = vorbis_time;
     802+               vorbis_time = ov_time_total (&vf, -1);
     803+               if (vorbis_time >= 0)
     804+                       info->time = vorbis_time / time_scaler;
     805        }
     806 
     807        ov_clear (&vf);
     808@@ -244,12 +244,15 @@
     809                io_close (data->stream);
     810        }
     811        else {
     812+               int64_t duration;
     813+
     814                data->last_section = -1;
     815                data->avg_bitrate = ov_bitrate (&data->vf, -1) / 1000;
     816                data->bitrate = data->avg_bitrate;
     817-               data->duration = ov_time_total (&data->vf, -1) / time_scaler;
     818-               if (data->duration == OV_EINVAL)
     819-                       data->duration = -1;
     820+               data->duration = -1;
     821+               duration = ov_time_total (&data->vf, -1);
     822+               if (duration >= 0)
     823+                       data->duration = duration / time_scaler;
     824                data->ok = 1;
     825                get_comment_tags (&data->vf, data->tags);
     826        }
     827@@ -280,9 +283,9 @@
     828 
     829 static int vorbis_can_decode (struct io_stream *stream)
     830 {
     831-       char buf[34];
     832+       char buf[35];
     833 
     834-       if (io_peek (stream, buf, 34) == 34 && !memcmp (buf, "OggS", 4)
     835+       if (io_peek (stream, buf, 35) == 35 && !memcmp (buf, "OggS", 4)
     836                        && !memcmp (buf + 28, "\01vorbis", 7))
     837                return 1;
     838 
     839Index: decoder_plugins/flac/flac.c
     840===================================================================
     841--- decoder_plugins/flac/flac.c (revision 2506)
     842+++ decoder_plugins/flac/flac.c (revision 2529)
     843@@ -54,7 +54,7 @@
     844        int abort; /* abort playing (due to an error) */
     845 
     846        unsigned length;
     847-       unsigned total_samples;
     848+       FLAC__uint64 total_samples;
     849 
     850        FLAC__byte sample_buffer[SAMPLE_BUFFER_SIZE];
     851        unsigned sample_buffer_fill;
     852@@ -156,11 +156,8 @@
     853        if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
     854                debug ("Got metadata info");
     855 
     856-               data->total_samples =
     857-                       (unsigned)(metadata->data.stream_info.total_samples
     858-                                  & 0xffffffff);
     859-               data->bits_per_sample =
     860-                       metadata->data.stream_info.bits_per_sample;
     861+               data->total_samples = metadata->data.stream_info.total_samples;
     862+               data->bits_per_sample = metadata->data.stream_info.bits_per_sample;
     863                data->channels = metadata->data.stream_info.channels;
     864                data->sample_rate = metadata->data.stream_info.sample_rate;
     865                data->length = data->total_samples / data->sample_rate;
     866@@ -536,9 +533,10 @@
     867        if ((unsigned)sec > data->length)
     868                return -1;
     869 
     870-       target_sample = (FLAC__uint64)((sec/(double)data->length) *
     871-                       (double)data->total_samples);
     872+       target_sample = (FLAC__uint64)(((double)sec / (double)data->length) *
     873+                                      (double)data->total_samples);
     874 
     875+
     876 #ifdef LEGACY_FLAC
     877        if (FLAC__seekable_stream_decoder_seek_absolute(data->decoder,
     878                                target_sample))
     879Index: audio.c
     880===================================================================
     881--- audio.c     (revision 2506)
     882+++ audio.c     (revision 2529)
     883@@ -169,7 +169,7 @@
     884        if (fmt1 & (SFMT_S16 | SFMT_U16)
     885                        && fmt2 & (SFMT_S16 | SFMT_U16))
     886                return 1;
     887-       if (fmt1 & (SFMT_S8 | SFMT_U8)
     888+       if (fmt1 & (SFMT_S32 | SFMT_U32)
     889                        && fmt2 & (SFMT_S32 | SFMT_U32))
     890                return 1;
     891        if (fmt1 & fmt2 & SFMT_FLOAT)
     892Index: TODO
     893===================================================================
     894--- TODO        (revision 2506)
     895+++ TODO        (revision 2529)
     896@@ -9,8 +9,6 @@
     897   - Recognition of ID3 tags v1 is broken (example: small.mp3).  [node/234]
     898   - Perhaps MOC can add support for the frame field_type to differentiate
     899     between ID3_FIELD_TYPE_LATIN1 and ID3_FIELD_TYPE_STRING.  [node/234]
     900-  - Characters which are represented in more than one screen column cause
     901-    the text to overflow its field.  [node/82, 99 and 788]
     902   - Some Cyrillic characters in file and directory names don't get displayed
     903     correctly.
     904 * Program crashes: