From 111b18e76114f1a46a23a979a7872e7fda412601 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 21 Feb 2013 00:03:57 -0800 Subject: Thu Feb 21 00:03:56 PST 2013 --- extra/moc/moc-ffmpeg.patch | 557 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 557 insertions(+) create mode 100644 extra/moc/moc-ffmpeg.patch (limited to 'extra/moc/moc-ffmpeg.patch') diff --git a/extra/moc/moc-ffmpeg.patch b/extra/moc/moc-ffmpeg.patch new file mode 100644 index 000000000..e268e5427 --- /dev/null +++ b/extra/moc/moc-ffmpeg.patch @@ -0,0 +1,557 @@ +Index: menu.c +=================================================================== +--- menu.c (revision 2516) ++++ menu.c (working copy) +@@ -90,9 +90,14 @@ + getyx (menu->win, y, x); + if (title_width <= title_space || mi->align == MENU_ALIGN_LEFT) + xwaddnstr (menu->win, mi->title, title_space); +- else +- xwaddstr (menu->win, mi->title + title_width - title_space); ++ else { ++ char *ptr; + ++ ptr = xstrtail (mi->title, title_space); ++ xwaddstr (menu->win, ptr); ++ free (ptr); ++ } ++ + /* Fill the remainder of the title field with spaces. */ + if (mi == menu->selected) { + getyx (menu->win, y, ix); +Index: utf8.c +=================================================================== +--- utf8.c (revision 2516) ++++ utf8.c (working copy) +@@ -199,47 +199,50 @@ + + int xwaddnstr (WINDOW *win, const char *str, const int n) + { +- int res; ++ int res, width, inv_char; ++ wchar_t *ucs; ++ char *mstr, *lstr; ++ size_t size, num_chars; + + assert (n > 0); + assert (str != NULL); + +- if (using_utf8) { ++ mstr = iconv_str (iconv_desc, str); + +- /* This nasty hack is because we need to count n in chars, but +- * [w]addnstr() takes arguments in bytes (in UTF-8 a char can be +- * longer than 1 byte). There are also problems with [w]addnwstr() +- * (screen garbled). I have no better idea. */ ++ size = xmbstowcs (NULL, mstr, -1, NULL) + 1; ++ ucs = (wchar_t *)xmalloc (sizeof(wchar_t) * size); ++ xmbstowcs (ucs, mstr, size, &inv_char); ++ width = wcswidth (ucs, WIDTH_MAX); + +- wchar_t *ucs; +- size_t size; +- size_t utf_num_chars; +- int inv_char; +- +- size = xmbstowcs (NULL, str, -1, NULL) + 1; +- ucs = (wchar_t *)xmalloc (sizeof(wchar_t) * size); +- xmbstowcs (ucs, str, size, &inv_char); +- if ((size_t)n < size - 1) +- ucs[n] = L'\0'; +- utf_num_chars = wcstombs (NULL, ucs, 0); +- if (inv_char) { +- char *utf8 = (char *)xmalloc (utf_num_chars + 1); +- +- wcstombs (utf8, ucs, utf_num_chars + 1); +- res = waddstr (win, utf8); +- free (utf8); ++ if (width == -1) { ++ size_t clidx; ++ for (clidx = 0; clidx < size - 1; clidx++) { ++ if (wcwidth (ucs[clidx]) == -1) ++ ucs[clidx] = L'?'; + } +- else +- res = waddnstr (win, str, utf_num_chars); +- free (ucs); ++ width = wcswidth (ucs, WIDTH_MAX); ++ inv_char = 1; + } +- else { +- char *lstr = iconv_str (iconv_desc, str); + +- res = waddnstr (win, lstr, n); +- free (lstr); ++ if (width > n) { ++ while (width > n) ++ width -= wcwidth (ucs[--size]); ++ ucs[size] = L'\0'; + } + ++ num_chars = wcstombs (NULL, ucs, 0); ++ lstr = (char *)xmalloc (num_chars + 1); ++ ++ if (inv_char) ++ wcstombs (lstr, ucs, num_chars + 1); ++ else ++ snprintf (lstr, num_chars + 1, "%s", mstr); ++ ++ res = waddstr (win, lstr); ++ ++ free (ucs); ++ free (lstr); ++ free (mstr); + return res; + } + +Index: decoder_plugins/mp3/mp3.c +=================================================================== +--- decoder_plugins/mp3/mp3.c (revision 2516) ++++ decoder_plugins/mp3/mp3.c (working copy) +@@ -696,17 +696,19 @@ + { + char *ext; + ++ strcpy (buf, "MPx"); ++ + ext = ext_pos (file); +- if (!strcasecmp (ext, "mp3")) +- strcpy (buf, "MP3"); +- else if (!strcasecmp (ext, "mp2")) +- strcpy (buf, "MP2"); +- else if (!strcasecmp (ext, "mp1")) +- strcpy (buf, "MP1"); +- else if (!strcasecmp (ext, "mpga")) +- strcpy (buf, "MPG"); +- else +- strcpy (buf, "MPx"); ++ if (ext) { ++ if (!strcasecmp (ext, "mp3")) ++ strcpy (buf, "MP3"); ++ else if (!strcasecmp (ext, "mp2")) ++ strcpy (buf, "MP2"); ++ else if (!strcasecmp (ext, "mp1")) ++ strcpy (buf, "MP1"); ++ else if (!strcasecmp (ext, "mpga")) ++ strcpy (buf, "MPG"); ++ } + } + + static int mp3_our_format_ext (const char *ext) +Index: decoder_plugins/ffmpeg/ffmpeg.m4 +=================================================================== +--- decoder_plugins/ffmpeg/ffmpeg.m4 (revision 2516) ++++ decoder_plugins/ffmpeg/ffmpeg.m4 (working copy) +@@ -88,6 +88,25 @@ + [#include ]) + AC_CHECK_DECLS([AV_CODEC_ID_OPUS], , , + [#include ]) ++ AC_SEARCH_LIBS(avcodec_free_frame, avcodec, ++ [AC_DEFINE([HAVE_AVCODEC_FREE_FRAME], 1, ++ [Define to 1 if you have the `avcodec_free_frame' function.])]) ++ AC_CHECK_DECLS([CODEC_ID_PCM_S8_PLANAR], , , ++ [#include ]) ++ AC_CHECK_DECLS([AV_SAMPLE_FMT_U8P], , , ++ [#include ]) ++ AC_CHECK_DECLS([AV_SAMPLE_FMT_S16P], , , ++ [#include ]) ++ AC_CHECK_DECLS([AV_SAMPLE_FMT_S32P], , , ++ [#include ]) ++ AC_CHECK_DECLS([AV_SAMPLE_FMT_FLTP], , , ++ [#include ]) ++ AC_SEARCH_LIBS(av_get_sample_fmt_name, avutil, ++ [AC_DEFINE([HAVE_AV_GET_SAMPLE_FMT_NAME], 1, ++ [Define to 1 if you have the `av_get_sample_fmt_name' function.])]) ++ AC_SEARCH_LIBS(av_lockmgr_register, avcodec, ++ [AC_DEFINE([HAVE_LOCKMGR_REGISTER], 1, ++ [Define to 1 if you have the `av_lockmgr_register' function.])]) + CPPFLAGS="$save_CPPFLAGS" + CFLAGS="$save_CFLAGS" + LIBS="$save_LIBS" +Index: decoder_plugins/ffmpeg/ffmpeg.c +=================================================================== +--- decoder_plugins/ffmpeg/ffmpeg.c (revision 2516) ++++ decoder_plugins/ffmpeg/ffmpeg.c (working copy) +@@ -99,6 +99,7 @@ + bool okay; /* was this stream successfully opened? */ + struct decoder_error error; + long fmt; ++ int sample_width; + int bitrate; /* in bits per second */ + int avg_bitrate; /* in bits per second */ + #if SEEK_IN_DECODER +@@ -106,6 +107,7 @@ + int seek_sec; /* second to which to seek */ + #endif + bool seek_broken; /* FFmpeg seeking is broken */ ++ bool timing_broken; /* FFmpeg trashes duration and bit_rate */ + #if SEEK_IN_DECODER && defined(DEBUG) + pthread_t thread_id; + #endif +@@ -277,8 +279,72 @@ + } + } + ++/* Handle FFmpeg's locking requirements. */ ++#ifdef HAVE_LOCKMGR_REGISTER ++static int locking_cb (void **mutex, enum AVLockOp op) ++{ ++ int result; ++ ++ switch (op) { ++ case AV_LOCK_CREATE: ++ *mutex = xmalloc (sizeof (pthread_mutex_t)); ++ result = pthread_mutex_init (*mutex, NULL); ++ break; ++ case AV_LOCK_OBTAIN: ++ result = pthread_mutex_lock (*mutex); ++ break; ++ case AV_LOCK_RELEASE: ++ result = pthread_mutex_unlock (*mutex); ++ break; ++ case AV_LOCK_DESTROY: ++ result = pthread_mutex_destroy (*mutex); ++ free (*mutex); ++ *mutex = NULL; ++ break; ++ } ++ ++ return result; ++} ++#endif ++ ++/* Here we attempt to determine if FFmpeg/LibAV has trashed the 'duration' ++ * and 'bit_rate' fields in AVFormatContext for large files. Determining ++ * whether or not they are likely to be valid is imprecise and will vary ++ * depending (at least) on: ++ * ++ * - The file's size, ++ * - The file's codec, ++ * - The number and size of tags, ++ * - The version of FFmpeg/LibAV, and ++ * - Whether it's FFmpeg or LibAV. ++ * ++ * This function represents a best guess. ++*/ ++static bool is_timing_broken (AVFormatContext *ic) ++{ ++ int64_t file_size; ++ ++ if (ic->duration < 0 || ic->bit_rate < 0) ++ return true; ++ ++#ifdef HAVE_AVIO_SIZE ++ file_size = avio_size (ic->pb); ++#else ++ file_size = ic->file_size; ++#endif ++ ++ if (file_size < UINT32_MAX) ++ return false; ++ ++ return true; ++} ++ + static void ffmpeg_init () + { ++#ifdef HAVE_LOCKMGR_REGISTER ++ int rc; ++#endif ++ + #ifdef DEBUG + av_log_set_level (AV_LOG_INFO); + #else +@@ -291,10 +357,20 @@ + supported_extns = lists_strs_new (16); + load_audio_extns (supported_extns); + load_video_extns (supported_extns); ++ ++#ifdef HAVE_LOCKMGR_REGISTER ++ rc = av_lockmgr_register (locking_cb); ++ if (rc < 0) ++ fatal ("Lock manager initialisation failed"); ++#endif + } + + static void ffmpeg_destroy () + { ++#ifdef HAVE_LOCKMGR_REGISTER ++ av_lockmgr_register (NULL); ++#endif ++ + av_log_set_level (AV_LOG_QUIET); + ffmpeg_log_repeats (NULL); + +@@ -341,9 +417,9 @@ + } + #endif + +- if (tags_sel & TAGS_TIME) { ++ if (!is_timing_broken (ic) && tags_sel & TAGS_TIME) { + info->time = -1; +- if (ic->duration >= 0) ++ if (ic->duration != (int64_t)AV_NOPTS_VALUE && ic->duration >= 0) + info->time = ic->duration / AV_TIME_BASE; + } + +@@ -426,12 +502,6 @@ + + #endif + +- if (tags_sel & TAGS_TIME) { +- info->time = -1; +- if (ic->duration != (int64_t)AV_NOPTS_VALUE && ic->duration >= 0) +- info->time = ic->duration / AV_TIME_BASE; +- } +- + end: + #ifdef HAVE_AVFORMAT_CLOSE_INPUT + avformat_close_input (&ic); +@@ -450,12 +520,16 @@ + if (!strcmp (data->ic->iformat->name, "wav")) { + switch (data->enc->codec_id) { + case CODEC_ID_PCM_S8: ++#if HAVE_DECL_CODEC_ID_PCM_S8_PLANAR ++ case CODEC_ID_PCM_S8_PLANAR: ++#endif + result = SFMT_S8; + break; + case CODEC_ID_PCM_U8: + result = SFMT_U8; + break; + case CODEC_ID_PCM_S16LE: ++ case CODEC_ID_PCM_S16LE_PLANAR: + case CODEC_ID_PCM_S16BE: + result = SFMT_S16; + break; +@@ -490,15 +564,27 @@ + + switch (data->enc->sample_fmt) { + case AV_SAMPLE_FMT_U8: ++#if HAVE_DECL_AV_SAMPLE_FMT_U8P ++ case AV_SAMPLE_FMT_U8P: ++#endif + result = SFMT_U8; + break; + case AV_SAMPLE_FMT_S16: ++#if HAVE_DECL_AV_SAMPLE_FMT_S16P ++ case AV_SAMPLE_FMT_S16P: ++#endif + result = SFMT_S16; + break; + case AV_SAMPLE_FMT_S32: ++#if HAVE_DECL_AV_SAMPLE_FMT_S32P ++ case AV_SAMPLE_FMT_S32P: ++#endif + result = SFMT_S32; + break; + case AV_SAMPLE_FMT_FLT: ++#if HAVE_DECL_AV_SAMPLE_FMT_FLTP ++ case AV_SAMPLE_FMT_FLTP: ++#endif + result = SFMT_FLOAT; + break; + default: +@@ -597,6 +683,7 @@ + data->stream = NULL; + data->enc = NULL; + data->codec = NULL; ++ data->sample_width = 0; + data->bitrate = 0; + data->avg_bitrate = 0; + +@@ -624,6 +711,7 @@ + data->seek_sec = 0; + #endif + data->seek_broken = false; ++ data->timing_broken = false; + + decoder_error_init (&data->error); + +@@ -702,27 +790,38 @@ + if (data->fmt == 0) + data->fmt = fmt_from_sample_fmt (data); + if (data->fmt == 0) { ++#ifdef HAVE_AV_GET_SAMPLE_FMT_NAME + decoder_error (&data->error, ERROR_FATAL, 0, ++ "Cannot get sample size from unknown sample format: %s", ++ av_get_sample_fmt_name (data->enc->sample_fmt)); ++#else ++ decoder_error (&data->error, ERROR_FATAL, 0, + "Unsupported sample size!"); ++#endif ++ avcodec_close (data->enc); + goto end; + } ++ data->sample_width = sfmt_Bps (data->fmt); + if (data->codec->capabilities & CODEC_CAP_DELAY) + data->delay = true; + data->seek_broken = is_seek_broken (data); ++ data->timing_broken = is_timing_broken (data->ic); + + data->okay = true; + +- if (data->ic->duration >= AV_TIME_BASE) { ++ if (!data->timing_broken && data->ic->duration >= AV_TIME_BASE) { + #ifdef HAVE_AVIO_SIZE + data->avg_bitrate = (int) (avio_size (data->ic->pb) / +- (data->ic->duration / AV_TIME_BASE) * 8); ++ (data->ic->duration / AV_TIME_BASE) * 8); + #else + data->avg_bitrate = (int) (data->ic->file_size / +- (data->ic->duration / AV_TIME_BASE) * 8); ++ (data->ic->duration / AV_TIME_BASE) * 8); + #endif + } +- data->bitrate = data->ic->bit_rate; + ++ if (!data->timing_broken && data->ic->bit_rate > 0) ++ data->bitrate = data->ic->bit_rate; ++ + return data; + + end: +@@ -943,12 +1042,14 @@ + char *buf, int buf_len) + { + int filled = 0; ++ AVFrame *frame; + ++ frame = avcodec_alloc_frame (); ++ + do { + int len, got_frame, is_planar, plane_size, data_size, copied; +- AVFrame frame; + +- len = avcodec_decode_audio4 (data->enc, &frame, &got_frame, pkt); ++ len = avcodec_decode_audio4 (data->enc, frame, &got_frame, pkt); + + if (len < 0) { + /* skip frame */ +@@ -968,33 +1069,46 @@ + + is_planar = av_sample_fmt_is_planar (data->enc->sample_fmt); + data_size = av_samples_get_buffer_size (&plane_size, +- data->enc->channels, frame.nb_samples, ++ data->enc->channels, ++ frame->nb_samples, + data->enc->sample_fmt, 1); + + if (data_size == 0) + continue; + +- copied = copy_or_buffer (data, (char *)frame.extended_data[0], +- plane_size, buf, buf_len); +- buf += copied; +- filled += copied; +- buf_len -= copied; ++ if (is_planar && data->enc->channels > 1) { ++ int offset, ch; + +- if (is_planar && data->enc->channels > 1) { +- int ch; ++ for (offset = 0; offset < plane_size; offset += data->sample_width) { ++ for (ch = 0; ch < data->enc->channels; ch += 1) { ++ copied = copy_or_buffer (data, ++ (char *)frame->extended_data[ch] ++ + offset, ++ data->sample_width, buf, buf_len); ++ buf += copied; ++ filled += copied; ++ buf_len -= copied; ++ } ++ } ++ } ++ else { ++ copied = copy_or_buffer (data, (char *)frame->extended_data[0], ++ plane_size, buf, buf_len); ++ buf += copied; ++ filled += copied; ++ buf_len -= copied; ++ } + +- for (ch = 1; ch < data->enc->channels; ch += 1) { +- copied = copy_or_buffer (data, (char *)frame.extended_data[ch], +- plane_size, buf, buf_len); +- buf += copied; +- filled += copied; +- buf_len -= copied; +- } +- } +- + debug ("Copying %dB (%dB filled)", data_size, filled); + } while (pkt->size > 0); + ++ avcodec_get_frame_defaults (frame); ++#ifdef HAVE_AVCODEC_FREE_FRAME ++ avcodec_free_frame (&frame); ++#else ++ av_freep (&frame); ++#endif ++ + return filled; + } + #endif +@@ -1122,9 +1236,10 @@ + free_packet (pkt); + } while (!bytes_produced && !data->eos); + +- data->bitrate = compute_bitrate (sound_params, bytes_used, +- bytes_produced + data->remain_buf_len, +- data->bitrate); ++ if (!data->timing_broken) ++ data->bitrate = compute_bitrate (sound_params, bytes_used, ++ bytes_produced + data->remain_buf_len, ++ data->bitrate); + + return bytes_produced; + } +@@ -1185,20 +1300,23 @@ + { + struct ffmpeg_data *data = (struct ffmpeg_data *)prv_data; + +- return data->bitrate / 1000; ++ return data->timing_broken ? -1 : data->bitrate / 1000; + } + + static int ffmpeg_get_avg_bitrate (void *prv_data) + { + struct ffmpeg_data *data = (struct ffmpeg_data *)prv_data; + +- return data->avg_bitrate / 1000; ++ return data->timing_broken ? -1 : data->avg_bitrate / 1000; + } + + static int ffmpeg_get_duration (void *prv_data) + { + struct ffmpeg_data *data = (struct ffmpeg_data *)prv_data; + ++ if (data->timing_broken) ++ return -1; ++ + if (!data->stream) + return -1; + + +Index: configure.in +=================================================================== +--- configure.in (revision 2518) ++++ configure.in (working copy) +@@ -293,7 +293,6 @@ + + dnl optional functions + AC_CHECK_FUNCS([strcasestr strerror_r syslog]) +-AC_CHECK_FUNCS([getrlimit pthread_attr_getstacksize]) + AX_CHECK_UNAME_SYSCALL + + dnl MIME magic +@@ -322,6 +321,7 @@ + CC="$PTHREAD_CC" + CFLAGS="$PTHREAD_CFLAGS $CFLAGS" + EXTRA_LIBS="$EXTRA_LIBS $PTHREAD_LIBS" ++AC_CHECK_FUNCS([getrlimit pthread_attr_getstacksize]) + + dnl __FUNCTION__ + AC_TRY_COMPILE(,[printf(__FUNCTION__);], [AC_DEFINE([HAVE__FUNCTION__], 1, + + -- cgit v1.2.3-54-g00ecf