diff --git a/projects/RPi/patches/xbmc/xbmc-001-newclock4.patch b/projects/RPi/patches/xbmc/xbmc-001-newclock4.patch index b2e0453bb1..bf2e59c356 100644 --- a/projects/RPi/patches/xbmc/xbmc-001-newclock4.patch +++ b/projects/RPi/patches/xbmc/xbmc-001-newclock4.patch @@ -1,7 +1,7 @@ -From 6a095dba6f512c2c78158feb4f764b6ddc5b1d3e Mon Sep 17 00:00:00 2001 +From efc821fb0cdd20cb444a8e0b9c3871b6f524e081 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 18 Aug 2014 17:48:04 +0100 -Subject: [PATCH 01/77] omxplayer: Reset codec on flush to stop a stale +Subject: [PATCH 01/82] omxplayer: Reset codec on flush to stop a stale timestamp from being returned --- @@ -9,10 +9,10 @@ Subject: [PATCH 01/77] omxplayer: Reset codec on flush to stop a stale 1 file changed, 2 insertions(+) diff --git a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp -index 55f8ac7..2d5ddf2 100644 +index f1208e6..01d2afc 100644 --- a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp +++ b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp -@@ -491,6 +491,8 @@ void OMXPlayerAudio::Process() +@@ -490,6 +490,8 @@ void OMXPlayerAudio::Process() void OMXPlayerAudio::Flush() { m_flush = true; @@ -22,10 +22,10 @@ index 55f8ac7..2d5ddf2 100644 m_messageQueue.Put( new CDVDMsg(CDVDMsg::GENERAL_FLUSH), 1); } -From 05e74bdeac984a465a5a132f127ea60c0aa2a773 Mon Sep 17 00:00:00 2001 +From bf54dc7ac1285b92e8bf36d18d47c34999c74c1f Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 30 Dec 2013 12:02:14 +0000 -Subject: [PATCH 03/77] [rbp] Hardware accelerated resampling +Subject: [PATCH 02/82] [rbp] Hardware accelerated resampling This replaces the format conversion, up/down mixing and resampling code from ActiveAE with a GPU accelerated version. Should significantly reduce CPU when using paplayer or dvdplayer. @@ -911,10 +911,10 @@ index 4ae29ba..4caa304 100644 OMX_ERRORTYPE omx_err = OMX_ErrorNone; -From 74fd1f96569ef50e18d8b1733b2953356ce5b409 Mon Sep 17 00:00:00 2001 +From 0a3befcfb1b3ade5395970beeba32c0d52bbf86d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 7 Apr 2014 18:19:32 +0100 -Subject: [PATCH 04/77] [rbp/omxplayer] When opening a stream don't try to +Subject: [PATCH 03/82] [rbp/omxplayer] When opening a stream don't try to update gui so often --- @@ -938,10 +938,10 @@ index e9ba7d3..0fdc3c2 100644 g_windowManager.ProcessRenderLoop(false); if (allowCancel && dialog->IsCanceled()) -From 50339d0bf4b90ee909e0b9a6788f6dc7043b5de2 Mon Sep 17 00:00:00 2001 +From 00b3bf000b56143c58f7f889cf1e83ad1990c2a3 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 29 Apr 2014 15:23:22 +0100 -Subject: [PATCH 05/77] [ffmpeg] Speed up wtv index creation +Subject: [PATCH 04/82] [ffmpeg] Speed up wtv index creation The index creation is O(N^2) with number of entries (typically thousands). On a Pi this can take more than 60 seconds to execute for a recording of a few hours. @@ -975,7 +975,7 @@ index 0e08dcf..7ce982c 100644 ./configure $(ffmpg_config) diff --git a/tools/depends/target/ffmpeg/ffmpeg_Speed_up_wtv_index_creation.patch b/tools/depends/target/ffmpeg/ffmpeg_Speed_up_wtv_index_creation.patch new file mode 100644 -index 0000000..8f5f989 +index 0000000..4ac5636 --- /dev/null +++ b/tools/depends/target/ffmpeg/ffmpeg_Speed_up_wtv_index_creation.patch @@ -0,0 +1,47 @@ @@ -1008,7 +1008,7 @@ index 0000000..8f5f989 ++ e->pos = last_position; ++ e++; ++ } -+ if (url_feof(pb)) ++ if (avio_feof(pb)) + break; +- for (i = wtv->nb_index_entries - 1; i >= 0; i--) { +- AVIndexEntry *e = wtv->index_entries + i; @@ -1027,904 +1027,10 @@ index 0000000..8f5f989 + } + } -From 420bc890afead12f3315e660c77860bc5744242d Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 8 Jul 2014 15:18:47 +0100 -Subject: [PATCH 06/77] ffmpeg: Add armv6 acceleration for imdct/fft used by - ac3/aac - -armv6: Accelerate ff_imdct_half for general case (mdct_bits != 6) - -The previous implementation targeted DTS Coherent Acoustics, which only -requires mdct_bits == 6. This relatively small size lent itself to -unrolling the loops a small number of times, and encoding offsets -calculated at assembly time within the load/store instructions of each -iteration. - -In the more general case (codecs such as AAC and AC3) much larger arrays -are used - mdct_bits == [8, 9, 11]. The old method does not scale for -these cases, so more integer registers are used with non-unrolled versions -of the loops (and with some stack spillage). The postrotation filter loop -is still unrolled by a factor of 2 to permit the double-buffering of some -VFP registers to facilitate overlap of neighbouring iterations. - -I benchmarked the result by measuring the number of gperftools samples -that hit anywhere in the AAC decoder (starting from aac_decode_frame()) -or specifically in ff_imdct_half_c / ff_imdct_half_vfp, for the same -example AAC stream: - - Before After - Mean StdDev Mean StdDev Confidence Change -aac_decode_frame 2368.1 35.8 2117.2 35.3 100.0% +11.8% -ff_imdct_half_* 457.5 22.4 251.2 16.2 100.0% +82.1% - -armv6: Accelerate ff_fft_calc for general case (nbits != 4) - -The previous implementation targeted DTS Coherent Acoustics, which only -requires nbits == 4 (fft16()). This case was (and still is) linked directly -rather than being indirected through ff_fft_calc_vfp(), but now the full -range from radix-4 up to radix-65536 is available. This benefits other codecs -such as AAC and AC3. - -The implementaion is based upon the C version, with each routine larger than -radix-16 calling a hierarchy of smaller FFT functions, then performing a -post-processing pass. This pass benefits a lot from loop unrolling to -counter the long pipelines in the VFP. A relaxed calling standard also -reduces the overhead of the call hierarchy, and avoiding the excessive -inlining performed by GCC probably helps with I-cache utilisation too. - -I benchmarked the result by measuring the number of gperftools samples that -hit anywhere in the AAC decoder (starting from aac_decode_frame()) or -specifically in the FFT routines (fft4() to fft512() and pass()) for the -same sample AAC stream: - - Before After - Mean StdDev Mean StdDev Confidence Change -Audio decode 2245.5 53.1 1599.6 43.8 100.0% +40.4% -FFT routines 940.6 22.0 348.1 20.8 100.0% +170.2% ---- - tools/depends/target/ffmpeg/Makefile | 8 +- - .../armv6-Accelerate-butterflies-float.patch | 165 ++++++++++ - ...6-Accelerate-ff_fft_calc-for-general-case.patch | 361 +++++++++++++++++++++ - .../armv6-Accelerate-vector-fmul-window.patch | 259 +++++++++++++++ - 4 files changed, 792 insertions(+), 1 deletion(-) - create mode 100644 tools/depends/target/ffmpeg/armv6-Accelerate-butterflies-float.patch - create mode 100644 tools/depends/target/ffmpeg/armv6-Accelerate-ff_fft_calc-for-general-case.patch - create mode 100644 tools/depends/target/ffmpeg/armv6-Accelerate-vector-fmul-window.patch - -diff --git a/tools/depends/target/ffmpeg/Makefile b/tools/depends/target/ffmpeg/Makefile -index 7ce982c..f205f70 100644 ---- a/tools/depends/target/ffmpeg/Makefile -+++ b/tools/depends/target/ffmpeg/Makefile -@@ -1,6 +1,8 @@ - include ../../Makefile.include - include FFMPEG-VERSION --DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ffmpeg_Speed_up_wtv_index_creation.patch -+DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ffmpeg_Speed_up_wtv_index_creation.patch \ -+ armv6-Accelerate-ff_fft_calc-for-general-case.patch \ -+ armv6-Accelerate-vector-fmul-window.patch armv6-Accelerate-butterflies-float.patch - - # set to "yes" to enable patching - # we don't apply patches until we move to a vanilla ffmpeg tarball -@@ -64,6 +66,10 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) - cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) - cd $(PLATFORM); sed -i".bak" -e "s%pkg_config_default=pkg-config%export PKG_CONFIG_LIBDIR=$(PREFIX)/lib/pkgconfig \&\& pkg_config_default=$(NATIVEPREFIX)/bin/pkg-config%" configure - cd $(PLATFORM); patch -p3 < ../ffmpeg_Speed_up_wtv_index_creation.patch -+ cd $(PLATFORM); patch -p1 < ../armv6-Accelerate-ff_fft_calc-for-general-case.patch -+ cd $(PLATFORM); patch -p1 < ../armv6-Accelerate-vector-fmul-window.patch -+ cd $(PLATFORM); patch -p1 < ../armv6-Accelerate-butterflies-float.patch -+ - cd $(PLATFORM);\ - CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" \ - ./configure $(ffmpg_config) -diff --git a/tools/depends/target/ffmpeg/armv6-Accelerate-butterflies-float.patch b/tools/depends/target/ffmpeg/armv6-Accelerate-butterflies-float.patch -new file mode 100644 -index 0000000..e1b6cd0 ---- /dev/null -+++ b/tools/depends/target/ffmpeg/armv6-Accelerate-butterflies-float.patch -@@ -0,0 +1,165 @@ -+From 46c74f06402ff196c3d35349a81423b0c2878527 Mon Sep 17 00:00:00 2001 -+From: Ben Avison -+Date: Thu, 10 Jul 2014 17:51:55 +0100 -+Subject: [PATCH] armv6: Accelerate butterflies_float -+ -+I benchmarked the result by measuring the number of gperftools samples that -+hit anywhere in the AAC decoder (starting from aac_decode_frame()) or -+specifically in butterflies_float_c() / ff_butterflies_float_vfp() for the -+same sample AAC stream: -+ -+ Before After -+ Mean StdDev Mean StdDev Confidence Change -+Audio decode 1542.8 43.7 1470.5 41.5 100.0% +4.9% -+butterflies_float 130.0 11.9 70.2 12.1 100.0% +85.2% -+--- -+ libavutil/arm/float_dsp_init_vfp.c | 4 ++ -+ libavutil/arm/float_dsp_vfp.S | 116 +++++++++++++++++++++++++++++++++++++ -+ 2 files changed, 120 insertions(+) -+ -+diff --git a/libavutil/arm/float_dsp_init_vfp.c b/libavutil/arm/float_dsp_init_vfp.c -+index f44020e..61ff2ed 100644 -+--- a/libavutil/arm/float_dsp_init_vfp.c -++++ b/libavutil/arm/float_dsp_init_vfp.c -+@@ -32,6 +32,8 @@ void ff_vector_fmul_window_vfp(float *dst, const float *src0, -+ void ff_vector_fmul_reverse_vfp(float *dst, const float *src0, -+ const float *src1, int len); -+ -++void ff_butterflies_float_vfp(float *restrict v1, float *restrict v2, int len); -++ -+ av_cold void ff_float_dsp_init_vfp(AVFloatDSPContext *fdsp, int cpu_flags) -+ { -+ if (!have_vfpv3(cpu_flags)) { -+@@ -39,4 +41,6 @@ av_cold void ff_float_dsp_init_vfp(AVFloatDSPContext *fdsp, int cpu_flags) -+ fdsp->vector_fmul_window = ff_vector_fmul_window_vfp; -+ } -+ fdsp->vector_fmul_reverse = ff_vector_fmul_reverse_vfp; -++ if (!have_vfpv3(cpu_flags)) -++ fdsp->butterflies_float = ff_butterflies_float_vfp; -+ } -+diff --git a/libavutil/arm/float_dsp_vfp.S b/libavutil/arm/float_dsp_vfp.S -+index c25588f..9f920aa 100644 -+--- a/libavutil/arm/float_dsp_vfp.S -++++ b/libavutil/arm/float_dsp_vfp.S -+@@ -339,3 +339,119 @@ function ff_vector_fmul_reverse_vfp, export=1 -+ vpop {d8-d15} -+ bx lr -+ endfunc -++ -++/** -++ * ARM VFP implementation of 'butterflies_float_c' function -++ * Assume that len is a positive non-zero number -++ */ -++@ void ff_butterflies_float_vfp(float *restrict v1, float *restrict v2, int len) -++function ff_butterflies_float_vfp, export=1 -++BASE1 .req a1 -++BASE2 .req a2 -++LEN .req a3 -++OLDFPSCR .req a4 -++ -++ vpush {s16-s31} -++ fmrx OLDFPSCR, FPSCR -++ -++ tst LEN, #7 -++ beq 4f @ common case: len is a multiple of 8 -++ -++ ldr ip, =0x03000000 @ RunFast mode, scalar mode -++ fmxr FPSCR, ip -++ -++ tst LEN, #1 -++ beq 1f -++ vldmia BASE1!, {s0} -++ vldmia BASE2!, {s8} -++ vadd.f s16, s0, s8 -++ vsub.f s24, s0, s8 -++ vstr s16, [BASE1, #0-4*1] -++ vstr s24, [BASE2, #0-4*1] -++1: -++ tst LEN, #2 -++ beq 2f -++ vldmia BASE1!, {s0-s1} -++ vldmia BASE2!, {s8-s9} -++ vadd.f s16, s0, s8 -++ vadd.f s17, s1, s9 -++ vsub.f s24, s0, s8 -++ vsub.f s25, s1, s9 -++ vstr d8, [BASE1, #0-8*1] @ s16,s17 -++ vstr d12, [BASE2, #0-8*1] @ s24,s25 -++2: -++ tst LEN, #4 -++ beq 3f -++ vldmia BASE1!, {s0-s1} -++ vldmia BASE2!, {s8-s9} -++ vldmia BASE1!, {s2-s3} -++ vldmia BASE2!, {s10-s11} -++ vadd.f s16, s0, s8 -++ vadd.f s17, s1, s9 -++ vsub.f s24, s0, s8 -++ vsub.f s25, s1, s9 -++ vadd.f s18, s2, s10 -++ vadd.f s19, s3, s11 -++ vsub.f s26, s2, s10 -++ vsub.f s27, s3, s11 -++ vstr d8, [BASE1, #0-16*1] @ s16,s17 -++ vstr d12, [BASE2, #0-16*1] @ s24,s25 -++ vstr d9, [BASE1, #8-16*1] @ s18,s19 -++ vstr d13, [BASE2, #8-16*1] @ s26,s27 -++3: -++ bics LEN, LEN, #7 -++ beq 7f -++4: -++ ldr ip, =0x03030000 @ RunFast mode, short vectors of length 4, stride 1 -++ fmxr FPSCR, ip -++ -++ vldmia BASE1!, {s0-s1} -++ vldmia BASE2!, {s8-s9} -++ vldmia BASE1!, {s2-s3} -++ vldmia BASE2!, {s10-s11} -++ vadd.f s16, s0, s8 -++ vldmia BASE1!, {s4-s5} -++ vldmia BASE2!, {s12-s13} -++ vldmia BASE1!, {s6-s7} -++ vldmia BASE2!, {s14-s15} -++ vsub.f s24, s0, s8 -++ vadd.f s20, s4, s12 -++ subs LEN, LEN, #8 -++ beq 6f -++5: vldmia BASE1!, {s0-s3} -++ vldmia BASE2!, {s8-s11} -++ vsub.f s28, s4, s12 -++ vstr d8, [BASE1, #0-16*3] @ s16,s17 -++ vstr d9, [BASE1, #8-16*3] @ s18,s19 -++ vstr d12, [BASE2, #0-16*3] @ s24,s25 -++ vstr d13, [BASE2, #8-16*3] @ s26,s27 -++ vadd.f s16, s0, s8 -++ vldmia BASE1!, {s4-s7} -++ vldmia BASE2!, {s12-s15} -++ vsub.f s24, s0, s8 -++ vstr d10, [BASE1, #0-16*3] @ s20,s21 -++ vstr d11, [BASE1, #8-16*3] @ s22,s23 -++ vstr d14, [BASE2, #0-16*3] @ s28,s29 -++ vstr d15, [BASE2, #8-16*3] @ s30,s31 -++ vadd.f s20, s4, s12 -++ subs LEN, LEN, #8 -++ bne 5b -++6: vsub.f s28, s4, s12 -++ vstr d8, [BASE1, #0-16*2] @ s16,s17 -++ vstr d9, [BASE1, #8-16*2] @ s18,s19 -++ vstr d12, [BASE2, #0-16*2] @ s24,s25 -++ vstr d13, [BASE2, #8-16*2] @ s26,s27 -++ vstr d10, [BASE1, #0-16*1] @ s20,s21 -++ vstr d11, [BASE1, #8-16*1] @ s22,s23 -++ vstr d14, [BASE2, #0-16*1] @ s28,s29 -++ vstr d15, [BASE2, #8-16*1] @ s30,s31 -++7: -++ fmxr FPSCR, OLDFPSCR -++ vpop {s16-s31} -++ bx lr -++ -++ .unreq BASE1 -++ .unreq BASE2 -++ .unreq LEN -++ .unreq OLDFPSCR -++endfunc -+-- -+1.9.3 -diff --git a/tools/depends/target/ffmpeg/armv6-Accelerate-ff_fft_calc-for-general-case.patch b/tools/depends/target/ffmpeg/armv6-Accelerate-ff_fft_calc-for-general-case.patch -new file mode 100644 -index 0000000..ccf9743 ---- /dev/null -+++ b/tools/depends/target/ffmpeg/armv6-Accelerate-ff_fft_calc-for-general-case.patch -@@ -0,0 +1,361 @@ -+From 883fb70c576181dbdf41e21872f1d0794024a6b4 Mon Sep 17 00:00:00 2001 -+From: Ben Avison -+Date: Mon, 7 Jul 2014 15:29:09 +0100 -+Subject: [PATCH] armv6: Accelerate ff_fft_calc for general case (nbits != 4) -+ -+The previous implementation targeted DTS Coherent Acoustics, which only -+requires nbits == 4 (fft16()). This case was (and still is) linked directly -+rather than being indirected through ff_fft_calc_vfp(), but now the full -+range from radix-4 up to radix-65536 is available. This benefits other codecs -+such as AAC and AC3. -+ -+The implementaion is based upon the C version, with each routine larger than -+radix-16 calling a hierarchy of smaller FFT functions, then performing a -+post-processing pass. This pass benefits a lot from loop unrolling to -+counter the long pipelines in the VFP. A relaxed calling standard also -+reduces the overhead of the call hierarchy, and avoiding the excessive -+inlining performed by GCC probably helps with I-cache utilisation too. -+ -+I benchmarked the result by measuring the number of gperftools samples that -+hit anywhere in the AAC decoder (starting from aac_decode_frame()) or -+specifically in the FFT routines (fft4() to fft512() and pass()) for the -+same sample AAC stream: -+ -+ Before After -+ Mean StdDev Mean StdDev Confidence Change -+Audio decode 2245.5 53.1 1599.6 43.8 100.0% +40.4% -+FFT routines 940.6 22.0 348.1 20.8 100.0% +170.2% -+--- -+ libavcodec/arm/fft_init_arm.c | 8 +- -+ libavcodec/arm/fft_vfp.S | 261 +++++++++++++++++++++++++++++++++++++++--- -+ 2 files changed, 252 insertions(+), 17 deletions(-) -+ -+diff --git a/libavcodec/arm/fft_init_arm.c b/libavcodec/arm/fft_init_arm.c -+index 3a3d1a7..bc143c1 100644 -+--- a/libavcodec/arm/fft_init_arm.c -++++ b/libavcodec/arm/fft_init_arm.c -+@@ -23,6 +23,8 @@ -+ #include "libavcodec/rdft.h" -+ #include "libavcodec/synth_filter.h" -+ -++void ff_fft_calc_vfp(FFTContext *s, FFTComplex *z); -++ -+ void ff_fft_permute_neon(FFTContext *s, FFTComplex *z); -+ void ff_fft_calc_neon(FFTContext *s, FFTComplex *z); -+ -+@@ -38,10 +40,10 @@ av_cold void ff_fft_init_arm(FFTContext *s) -+ { -+ int cpu_flags = av_get_cpu_flags(); -+ -+- if (have_vfp(cpu_flags)) { -++ if (have_vfp(cpu_flags) && !have_vfpv3(cpu_flags)) { -++ s->fft_calc = ff_fft_calc_vfp; -+ #if CONFIG_MDCT -+- if (!have_vfpv3(cpu_flags)) -+- s->imdct_half = ff_imdct_half_vfp; -++ s->imdct_half = ff_imdct_half_vfp; -+ #endif -+ } -+ -+diff --git a/libavcodec/arm/fft_vfp.S b/libavcodec/arm/fft_vfp.S -+index 7845ebb..186bed9 100644 -+--- a/libavcodec/arm/fft_vfp.S -++++ b/libavcodec/arm/fft_vfp.S -+@@ -21,8 +21,9 @@ -+ -+ #include "libavutil/arm/asm.S" -+ -+-@ TODO: * FFTs wider than 16 -+-@ * dispatch code -++@ The fftx_internal_vfp versions of the functions obey a modified AAPCS: -++@ VFP is in RunFast mode, vector length 4, stride 1 thoroughout, and -++@ all single-precision VFP registers may be corrupted on exit. -+ -+ function fft4_vfp -+ vldr d0, [a1, #0*2*4] @ s0,s1 = z[0] -+@@ -131,18 +132,22 @@ endfunc -+ vstr d9, [a1, #3 * 2*4] -+ .endm -+ -++function fft8_internal_vfp -++ macro_fft8_head -++ macro_fft8_tail -++ bx lr -++endfunc -++ -+ function fft8_vfp -+ ldr a3, =0x03030000 @ RunFast mode, vector length 4, stride 1 -+ fmrx a2, FPSCR -+ fmxr FPSCR, a3 -+ vpush {s16-s31} -+- -+- macro_fft8_head -+- macro_fft8_tail -+- -++ mov ip, lr -++ bl fft8_internal_vfp -+ vpop {s16-s31} -+ fmxr FPSCR, a2 -+- bx lr -++ bx ip -+ endfunc -+ -+ .align 3 -+@@ -153,12 +158,7 @@ cos1pi8: @ cos(1*pi/8) = sqrt(2+sqrt(2))/2 -+ cos3pi8: @ cos(2*pi/8) = sqrt(2-sqrt(2))/2 -+ .float 0.3826834261417388916015625 -+ -+-function ff_fft16_vfp, export=1 -+- ldr a3, =0x03030000 @ RunFast mode, vector length 4, stride 1 -+- fmrx a2, FPSCR -+- fmxr FPSCR, a3 -+- vpush {s16-s31} -+- -++function fft16_internal_vfp -+ macro_fft8_head -+ @ FFT4(z+8) -+ vldr d10, [a1, #8 * 2*4] -+@@ -292,7 +292,240 @@ function ff_fft16_vfp, export=1 -+ vstr d8, [a1, #0 * 2*4] -+ vstr d9, [a1, #4 * 2*4] -+ -++ bx lr -++endfunc -++ -++function ff_fft16_vfp, export=1 -++ ldr a3, =0x03030000 @ RunFast mode, vector length 4, stride 1 -++ fmrx a2, FPSCR -++ fmxr FPSCR, a3 -++ vpush {s16-s31} -++ mov ip, lr -++ bl fft16_internal_vfp -+ vpop {s16-s31} -+ fmxr FPSCR, a2 -+- bx lr -++ bx ip -++endfunc -++ -++.macro pass n, z0, z1, z2, z3 -++ add v6, v5, #4*2*\n -++ @ TRANSFORM_ZERO(z[0],z[o1],z[o2],z[o3]) -++ @ TRANSFORM(z[1],z[o1+1],z[o2+1],z[o3+1],wre[1],wim[-1]) -++ @ TRANSFORM(z[0],z[o1],z[o2],z[o3],wre[0],wim[0]) -++ @ TRANSFORM(z[1],z[o1+1],z[o2+1],z[o3+1],wre[1],wim[-1]) -++ vldr d8, [\z2, #8*(o2+1)] @ s16,s17 -++ vldmdb v6!, {s2} -++ vldr d9, [\z3, #8*(o3+1)] @ s18,s19 -++ vldmia v5!, {s0,s1} @ s0 is unused -++ vldr s7, [\z2, #8*o2] @ t1 -++ vmul.f s20, s16, s2 @ vector * scalar -++ vldr s0, [\z3, #8*o3] @ t5 -++ vldr s6, [\z2, #8*o2+4] @ t2 -++ vldr s3, [\z3, #8*o3+4] @ t6 -++ vmul.f s16, s16, s1 @ vector * scalar -++ ldr a4, =\n-1 -++1: add \z0, \z0, #8*2 -++ .if \n*4*2 >= 512 -++ add \z1, \z1, #8*2 -++ .endif -++ .if \n*4*2 >= 256 -++ add \z2, \z2, #8*2 -++ .endif -++ .if \n*4*2 >= 512 -++ add \z3, \z3, #8*2 -++ .endif -++ @ up to 2 stalls (VFP vector issuing / waiting for s0) -++ @ depending upon whether this is the first iteration and -++ @ how many add instructions are inserted above -++ vadd.f s4, s0, s7 @ t5 -++ vadd.f s5, s6, s3 @ t6 -++ vsub.f s6, s6, s3 @ t4 -++ vsub.f s7, s0, s7 @ t3 -++ vldr d6, [\z0, #8*0-8*2] @ s12,s13 -++ vadd.f s0, s16, s21 @ t1 -++ vldr d7, [\z1, #8*o1-8*2] @ s14,s15 -++ vsub.f s1, s18, s23 @ t5 -++ vadd.f s8, s4, s12 @ vector + vector -++ @ stall (VFP vector issuing) -++ @ stall (VFP vector issuing) -++ @ stall (VFP vector issuing) -++ vsub.f s4, s12, s4 -++ vsub.f s5, s13, s5 -++ vsub.f s6, s14, s6 -++ vsub.f s7, s15, s7 -++ vsub.f s2, s17, s20 @ t2 -++ vadd.f s3, s19, s22 @ t6 -++ vstr d4, [\z0, #8*0-8*2] @ s8,s9 -++ vstr d5, [\z1, #8*o1-8*2] @ s10,s11 -++ @ stall (waiting for s5) -++ vstr d2, [\z2, #8*o2-8*2] @ s4,s5 -++ vadd.f s4, s1, s0 @ t5 -++ vstr d3, [\z3, #8*o3-8*2] @ s6,s7 -++ vsub.f s7, s1, s0 @ t3 -++ vadd.f s5, s2, s3 @ t6 -++ vsub.f s6, s2, s3 @ t4 -++ vldr d6, [\z0, #8*1-8*2] @ s12,s13 -++ vldr d7, [\z1, #8*(o1+1)-8*2] @ s14,s15 -++ vldr d4, [\z2, #8*o2] @ s8,s9 -++ vldmdb v6!, {s2,s3} -++ vldr d5, [\z3, #8*o3] @ s10,s11 -++ vadd.f s20, s4, s12 @ vector + vector -++ vldmia v5!, {s0,s1} -++ vldr d8, [\z2, #8*(o2+1)] @ s16,s17 -++ @ stall (VFP vector issuing) -++ vsub.f s4, s12, s4 -++ vsub.f s5, s13, s5 -++ vsub.f s6, s14, s6 -++ vsub.f s7, s15, s7 -++ vmul.f s12, s8, s3 @ vector * scalar -++ vstr d10, [\z0, #8*1-8*2] @ s20,s21 -++ vldr d9, [\z3, #8*(o3+1)] @ s18,s19 -++ vstr d11, [\z1, #8*(o1+1)-8*2] @ s22,s23 -++ vmul.f s8, s8, s0 @ vector * scalar -++ vstr d2, [\z2, #8*(o2+1)-8*2] @ s4,s5 -++ @ stall (waiting for s7) -++ vstr d3, [\z3, #8*(o3+1)-8*2] @ s6,s7 -++ vmul.f s20, s16, s2 @ vector * scalar -++ @ stall (VFP vector issuing) -++ @ stall (VFP vector issuing) -++ @ stall (VFP vector issuing) -++ vadd.f s7, s8, s13 @ t1 -++ vsub.f s6, s9, s12 @ t2 -++ vsub.f s0, s10, s15 @ t5 -++ vadd.f s3, s11, s14 @ t6 -++ vmul.f s16, s16, s1 @ vector * scalar -++ subs a4, a4, #1 -++ bne 1b -++ @ What remains is identical to the first two indentations of -++ @ the above, but without the increment of z -++ vadd.f s4, s0, s7 @ t5 -++ vadd.f s5, s6, s3 @ t6 -++ vsub.f s6, s6, s3 @ t4 -++ vsub.f s7, s0, s7 @ t3 -++ vldr d6, [\z0, #8*0] @ s12,s13 -++ vadd.f s0, s16, s21 @ t1 -++ vldr d7, [\z1, #8*o1] @ s14,s15 -++ vsub.f s1, s18, s23 @ t5 -++ vadd.f s8, s4, s12 @ vector + vector -++ vsub.f s4, s12, s4 -++ vsub.f s5, s13, s5 -++ vsub.f s6, s14, s6 -++ vsub.f s7, s15, s7 -++ vsub.f s2, s17, s20 @ t2 -++ vadd.f s3, s19, s22 @ t6 -++ vstr d4, [\z0, #8*0] @ s8,s9 -++ vstr d5, [\z1, #8*o1] @ s10,s11 -++ vstr d2, [\z2, #8*o2] @ s4,s5 -++ vadd.f s4, s1, s0 @ t5 -++ vstr d3, [\z3, #8*o3] @ s6,s7 -++ vsub.f s7, s1, s0 @ t3 -++ vadd.f s5, s2, s3 @ t6 -++ vsub.f s6, s2, s3 @ t4 -++ vldr d6, [\z0, #8*1] @ s12,s13 -++ vldr d7, [\z1, #8*(o1+1)] @ s14,s15 -++ vadd.f s20, s4, s12 @ vector + vector -++ vsub.f s4, s12, s4 -++ vsub.f s5, s13, s5 -++ vsub.f s6, s14, s6 -++ vsub.f s7, s15, s7 -++ vstr d10, [\z0, #8*1] @ s20,s21 -++ vstr d11, [\z1, #8*(o1+1)] @ s22,s23 -++ vstr d2, [\z2, #8*(o2+1)] @ s4,s5 -++ vstr d3, [\z3, #8*(o3+1)] @ s6,s7 -++.endm -++ -++.macro fft_internal_vfp name, name2, name4, costable, n -++function \name -++ .if \n >= 512 -++ push {v1-v6,lr} -++ .elseif \n >= 256 -++ push {v1-v2,v5-v6,lr} -++ .else -++ push {v1,v5-v6,lr} -++ .endif -++ mov v1, a1 -++ bl \name2 -++ add a1, v1, #8*(\n/4)*2 -++ bl \name4 -++ ldr v5, =\costable -++ add a1, v1, #8*(\n/4)*3 -++ bl \name4 -++ .if \n >= 512 -++ .set o1, 0*(\n/4/2) -++ .set o2, 0*(\n/4/2) -++ .set o3, 0*(\n/4/2) -++ add v2, v1, #8*2*(\n/4/2) -++ add v3, v1, #8*4*(\n/4/2) -++ add v4, v1, #8*6*(\n/4/2) -++ pass (\n/4/2), v1, v2, v3, v4 -++ pop {v1-v6,pc} -++ .elseif \n >= 256 -++ .set o1, 2*(\n/4/2) -++ .set o2, 0*(\n/4/2) -++ .set o3, 2*(\n/4/2) -++ add v2, v1, #8*4*(\n/4/2) -++ pass (\n/4/2), v1, v1, v2, v2 -++ pop {v1-v2,v5-v6,pc} -++ .else -++ .set o1, 2*(\n/4/2) -++ .set o2, 4*(\n/4/2) -++ .set o3, 6*(\n/4/2) -++ pass (\n/4/2), v1, v1, v1, v1 -++ pop {v1,v5-v6,pc} -++ .endif -++endfunc -++.endm -++ -++#define DECL_FFT(n,n2,n4) \ -++fft_internal_vfp fft##n##_internal_vfp, fft##n2##_internal_vfp, fft##n4##_internal_vfp, ff_cos_##n, n ;\ -++ ;\ -++function fft##n##_vfp ;\ -++ ldr a3, =0x03030000 /* RunFast mode, vector length 4, stride 1 */ ;\ -++ fmrx a2, FPSCR ;\ -++ fmxr FPSCR, a3 ;\ -++ vpush {s16-s31} ;\ -++ mov ip, lr ;\ -++ bl fft##n##_internal_vfp ;\ -++ vpop {s16-s31} ;\ -++ fmxr FPSCR, a2 ;\ -++ bx ip ;\ -++endfunc ;\ -++ ;\ -++.ltorg -++ -++DECL_FFT(32,16,8) -++DECL_FFT(64,32,16) -++DECL_FFT(128,64,32) -++DECL_FFT(256,128,64) -++DECL_FFT(512,256,128) -++DECL_FFT(1024,512,256) -++DECL_FFT(2048,1024,512) -++DECL_FFT(4096,2048,1024) -++DECL_FFT(8192,4096,2048) -++DECL_FFT(16384,8192,4096) -++DECL_FFT(32768,16384,8192) -++DECL_FFT(65536,32768,16384) -++ -++function ff_fft_calc_vfp, export=1 -++ ldr ip, [a1, #0] @ nbits -++ mov a1, a2 -++ ldr ip, [pc, ip, lsl #2] -++ bx ip -++ .word 0 -++ .word 0 -++ .word fft4_vfp -++ .word fft8_vfp -++ .word ff_fft16_vfp @ this one alone is exported -++ .word fft32_vfp -++ .word fft64_vfp -++ .word fft128_vfp -++ .word fft256_vfp -++ .word fft512_vfp -++ .word fft1024_vfp -++ .word fft2048_vfp -++ .word fft4096_vfp -++ .word fft8192_vfp -++ .word fft16384_vfp -++ .word fft32768_vfp -++ .word fft65536_vfp -+ endfunc -+-- -+1.9.3 -diff --git a/tools/depends/target/ffmpeg/armv6-Accelerate-vector-fmul-window.patch b/tools/depends/target/ffmpeg/armv6-Accelerate-vector-fmul-window.patch -new file mode 100644 -index 0000000..db0118f ---- /dev/null -+++ b/tools/depends/target/ffmpeg/armv6-Accelerate-vector-fmul-window.patch -@@ -0,0 +1,259 @@ -+From 1f5c397bdd4ebd2c9ed04488fcf52d77a5db3e88 Mon Sep 17 00:00:00 2001 -+From: Ben Avison -+Date: Thu, 10 Jul 2014 13:01:47 +0100 -+Subject: [PATCH] armv6: Accelerate vector_fmul_window -+ -+I benchmarked the result by measuring the number of gperftools samples that -+hit anywhere in the AAC decoder (starting from aac_decode_frame()) or -+specifically in vector_fmul_window_c() / ff_vector_fmul_window_vfp() for the -+same sample AAC stream: -+ -+ Before After -+ Mean StdDev Mean StdDev Confidence Change -+Audio decode 1598.2 47.4 1529.2 25.4 100.0% +4.5% -+vector_fmul_window 244.0 22.1 188.9 22.3 100.0% +29.2% -+--- -+ libavutil/arm/float_dsp_init_vfp.c | 7 +- -+ libavutil/arm/float_dsp_vfp.S | 204 +++++++++++++++++++++++++++++++++++++ -+ 2 files changed, 210 insertions(+), 1 deletion(-) -+ -+diff --git a/libavutil/arm/float_dsp_init_vfp.c b/libavutil/arm/float_dsp_init_vfp.c -+index 31cb6ae..f44020e 100644 -+--- a/libavutil/arm/float_dsp_init_vfp.c -++++ b/libavutil/arm/float_dsp_init_vfp.c -+@@ -26,12 +26,17 @@ -+ void ff_vector_fmul_vfp(float *dst, const float *src0, const float *src1, -+ int len); -+ -++void ff_vector_fmul_window_vfp(float *dst, const float *src0, -++ const float *src1, const float *win, int len); -++ -+ void ff_vector_fmul_reverse_vfp(float *dst, const float *src0, -+ const float *src1, int len); -+ -+ av_cold void ff_float_dsp_init_vfp(AVFloatDSPContext *fdsp, int cpu_flags) -+ { -+- if (!have_vfpv3(cpu_flags)) -++ if (!have_vfpv3(cpu_flags)) { -+ fdsp->vector_fmul = ff_vector_fmul_vfp; -++ fdsp->vector_fmul_window = ff_vector_fmul_window_vfp; -++ } -+ fdsp->vector_fmul_reverse = ff_vector_fmul_reverse_vfp; -+ } -+diff --git a/libavutil/arm/float_dsp_vfp.S b/libavutil/arm/float_dsp_vfp.S -+index 8295280..c25588f 100644 -+--- a/libavutil/arm/float_dsp_vfp.S -++++ b/libavutil/arm/float_dsp_vfp.S -+@@ -68,6 +68,210 @@ function ff_vector_fmul_vfp, export=1 -+ endfunc -+ -+ /** -++ * ARM VFP implementation of 'vector_fmul_window_c' function -++ * Assume that len is a positive non-zero number -++ */ -++@ void ff_vector_fmul_window_vfp(float *dst, const float *src0, -++@ const float *src1, const float *win, int len) -++function ff_vector_fmul_window_vfp, export=1 -++DST0 .req a1 -++SRC0 .req a2 -++SRC1 .req a3 -++WIN0 .req a4 -++LEN .req v1 -++DST1 .req v2 -++WIN1 .req v3 -++OLDFPSCR .req ip -++ -++ push {v1-v3,lr} -++ ldr LEN, [sp, #4*4+0] -++ vpush {s16-s31} -++ fmrx OLDFPSCR, FPSCR -++ add DST1, DST0, LEN, lsl #3 -++ add SRC1, SRC1, LEN, lsl #2 -++ add WIN1, WIN0, LEN, lsl #3 -++ -++ tst LEN, #7 -++ beq 4f @ common case: len is a multiple of 8 -++ -++ ldr lr, =0x03000000 @ RunFast mode, scalar mode -++ fmxr FPSCR, lr -++ -++ tst LEN, #1 -++ beq 1f -++ vldmdb WIN1!, {s0} -++ vldmia SRC0!, {s8} -++ vldmia WIN0!, {s16} -++ vmul.f s24, s0, s8 -++ vldmdb SRC1!, {s20} -++ vmul.f s8, s16, s8 -++ vmls.f s24, s16, s20 -++ vmla.f s8, s0, s20 -++ vstmia DST0!, {s24} -++ vstmdb DST1!, {s8} -++1: -++ tst LEN, #2 -++ beq 2f -++ vldmdb WIN1!, {s0} -++ vldmdb WIN1!, {s1} -++ vldmia SRC0!, {s8-s9} -++ vldmia WIN0!, {s16-s17} -++ vmul.f s24, s0, s8 -++ vmul.f s25, s1, s9 -++ vldmdb SRC1!, {s20} -++ vldmdb SRC1!, {s21} -++ vmul.f s8, s16, s8 -++ vmul.f s9, s17, s9 -++ vmls.f s24, s16, s20 -++ vmls.f s25, s17, s21 -++ vmla.f s8, s0, s20 -++ vmla.f s9, s1, s21 -++ vstmia DST0!, {s24-s25} -++ vstmdb DST1!, {s8} -++ vstmdb DST1!, {s9} -++2: -++ tst LEN, #4 -++ beq 3f -++ vldmdb WIN1!, {s0} -++ vldmdb WIN1!, {s1} -++ vldmdb WIN1!, {s2} -++ vldmdb WIN1!, {s3} -++ vldmia SRC0!, {s8-s11} -++ vldmia WIN0!, {s16-s19} -++ vmul.f s24, s0, s8 -++ vmul.f s25, s1, s9 -++ vmul.f s26, s2, s10 -++ vmul.f s27, s3, s11 -++ vldmdb SRC1!, {s20} -++ vldmdb SRC1!, {s21} -++ vldmdb SRC1!, {s22} -++ vldmdb SRC1!, {s23} -++ vmul.f s8, s16, s8 -++ vmul.f s9, s17, s9 -++ vmul.f s10, s18, s10 -++ vmul.f s11, s19, s11 -++ vmls.f s24, s16, s20 -++ vmls.f s25, s17, s21 -++ vmls.f s26, s18, s22 -++ vmls.f s27, s19, s23 -++ vmla.f s8, s0, s20 -++ vmla.f s9, s1, s21 -++ vmla.f s10, s2, s22 -++ vmla.f s11, s3, s23 -++ vstmia DST0!, {s24-s27} -++ vstmdb DST1!, {s8} -++ vstmdb DST1!, {s9} -++ vstmdb DST1!, {s10} -++ vstmdb DST1!, {s11} -++3: -++ bics LEN, LEN, #7 -++ beq 7f -++4: -++ ldr lr, =0x03030000 @ RunFast mode, short vectors of length 4, stride 1 -++ fmxr FPSCR, lr -++ -++ vldmdb WIN1!, {s0} -++ vldmdb WIN1!, {s1} -++ vldmdb WIN1!, {s2} -++ vldmdb WIN1!, {s3} -++ vldmia SRC0!, {s8-s11} -++ vldmia WIN0!, {s16-s19} -++ vmul.f s24, s0, s8 @ vector * vector -++ vldmdb SRC1!, {s20} -++ vldmdb SRC1!, {s21} -++ vldmdb SRC1!, {s22} -++ vldmdb SRC1!, {s23} -++ vmul.f s8, s16, s8 @ vector * vector -++ vmls.f s24, s16, s20 @ vector * vector -++ vldmdb WIN1!, {s4} -++ vldmdb WIN1!, {s5} -++ vldmdb WIN1!, {s6} -++ vldmdb WIN1!, {s7} -++ vldmia SRC0!, {s12-s13} -++ vmla.f s8, s0, s20 @ vector * vector -++ vldmia SRC0!, {s14-s15} -++ subs LEN, LEN, #8 -++ beq 6f -++5: vldmia WIN0!, {s20-s23} -++ vmul.f s28, s4, s12 @ vector * vector -++ vstmia DST0!, {s24-s25} -++ vldmdb SRC1!, {s16} -++ vldmdb SRC1!, {s17} -++ vldmdb SRC1!, {s18} -++ vldmdb SRC1!, {s19} -++ vmul.f s12, s20, s12 @ vector * vector -++ vstmia DST0!, {s26-s27} -++ vstmdb DST1!, {s8} -++ vstmdb DST1!, {s9} -++ vstmdb DST1!, {s10} -++ vstmdb DST1!, {s11} -++ vmls.f s28, s20, s16 @ vector * vector -++ vldmdb WIN1!, {s0} -++ vldmdb WIN1!, {s1} -++ vldmdb WIN1!, {s2} -++ vldmdb WIN1!, {s3} -++ vldmia SRC0!, {s8-s9} -++ vmla.f s12, s4, s16 @ vector * vector -++ vldmia SRC0!, {s10-s11} -++ subs LEN, LEN, #8 -++ vldmia WIN0!, {s16-s19} -++ vmul.f s24, s0, s8 @ vector * vector -++ vstmia DST0!, {s28-s29} -++ vldmdb SRC1!, {s20} -++ vldmdb SRC1!, {s21} -++ vldmdb SRC1!, {s22} -++ vldmdb SRC1!, {s23} -++ vmul.f s8, s16, s8 @ vector * vector -++ vstmia DST0!, {s30-s31} -++ vstmdb DST1!, {s12} -++ vstmdb DST1!, {s13} -++ vstmdb DST1!, {s14} -++ vstmdb DST1!, {s15} -++ vmls.f s24, s16, s20 @ vector * vector -++ vldmdb WIN1!, {s4} -++ vldmdb WIN1!, {s5} -++ vldmdb WIN1!, {s6} -++ vldmdb WIN1!, {s7} -++ vldmia SRC0!, {s12-s13} -++ vmla.f s8, s0, s20 @ vector * vector -++ vldmia SRC0!, {s14-s15} -++ bne 5b -++6: vldmia WIN0!, {s20-s23} -++ vmul.f s28, s4, s12 @ vector * vector -++ vstmia DST0!, {s24-s25} -++ vldmdb SRC1!, {s16} -++ vldmdb SRC1!, {s17} -++ vldmdb SRC1!, {s18} -++ vldmdb SRC1!, {s19} -++ vmul.f s12, s20, s12 @ vector * vector -++ vstmia DST0!, {s26-s27} -++ vstmdb DST1!, {s8} -++ vstmdb DST1!, {s9} -++ vstmdb DST1!, {s10} -++ vstmdb DST1!, {s11} -++ vmls.f s28, s20, s16 @ vector * vector -++ vmla.f s12, s4, s16 @ vector * vector -++ vstmia DST0!, {s28-s31} -++ vstmdb DST1!, {s12} -++ vstmdb DST1!, {s13} -++ vstmdb DST1!, {s14} -++ vstmdb DST1!, {s15} -++7: -++ fmxr FPSCR, OLDFPSCR -++ vpop {s16-s31} -++ pop {v1-v3,pc} -++ -++ .unreq DST0 -++ .unreq SRC0 -++ .unreq SRC1 -++ .unreq WIN0 -++ .unreq LEN -++ .unreq OLDFPSCR -++ .unreq DST1 -++ .unreq WIN1 -++endfunc -++ -++/** -+ * ARM VFP optimized implementation of 'vector_fmul_reverse_c' function. -+ * Assume that len is a positive number and is multiple of 8 -+ */ -+-- -+1.9.3 - -From 472c348860f3aa6b39339dfea7e1a61a76ad9a45 Mon Sep 17 00:00:00 2001 +From da0b53794ad0cdfba4a8d8a5d20431461339e677 Mon Sep 17 00:00:00 2001 From: Jonathan Marshall Date: Sat, 2 Nov 2013 23:49:17 +1300 -Subject: [PATCH 07/77] adds GetTvShowSeasons +Subject: [PATCH 05/82] adds GetTvShowSeasons --- xbmc/video/VideoDatabase.cpp | 30 ++++++++++++++++++++++++------ @@ -2000,10 +1106,10 @@ index 78259ed..cbb26b7 100644 bool GetArtTypes(const MediaType &mediaType, std::vector &artTypes); -From 4873479f1b979e3e42de7f425645b8047748525d Mon Sep 17 00:00:00 2001 +From 3263688a14f9f784b4d1a751472e5c350538f0c2 Mon Sep 17 00:00:00 2001 From: Jonathan Marshall Date: Sat, 2 Nov 2013 23:50:10 +1300 -Subject: [PATCH 08/77] move AddSeason() public. +Subject: [PATCH 06/82] move AddSeason() public. --- xbmc/video/VideoDatabase.h | 2 +- @@ -2030,10 +1136,10 @@ index cbb26b7..1a79c00 100644 /*! \brief Adds a path to the tvshow link table. \param idShow the id of the show. -From 8d4bf50d6ec30ae5760bfc08ce63198775b55399 Mon Sep 17 00:00:00 2001 +From 8a63d0f9f991b6b87ef0581865933d60749dac32 Mon Sep 17 00:00:00 2001 From: Jonathan Marshall Date: Sat, 2 Nov 2013 23:48:24 +1300 -Subject: [PATCH 09/77] adds GetArt function to (video) scraper, allowing art +Subject: [PATCH 07/82] adds GetArt function to (video) scraper, allowing art to be fetched given the video identifier. --- @@ -2148,10 +1254,10 @@ index 22ac229..75bc341 100644 enum LOOKUP_STATE { DO_NOTHING = 0, FIND_MOVIE = 1, -From 7ee9b363f0bd7cfe77d835284a7d7c770e223e3f Mon Sep 17 00:00:00 2001 +From 04b9ff47bd3c79dd3857272a1dcb9749a26e04a7 Mon Sep 17 00:00:00 2001 From: Jonathan Marshall Date: Sat, 2 Nov 2013 23:53:14 +1300 -Subject: [PATCH 10/77] refresh season art if a new season is found that isn't +Subject: [PATCH 08/82] refresh season art if a new season is found that isn't recorded in the database yet. Fixes #14339 --- @@ -2255,10 +1361,10 @@ index 7da1bf2..c764e20 100644 bool ProcessItemByVideoInfoTag(const CFileItem *item, EPISODELIST &episodeList); -From 60cf5bb235e87d2f69dbf89d359e2c581ff44b03 Mon Sep 17 00:00:00 2001 +From 60a66042dd6592b82a71ecc989f8bf67f1f79461 Mon Sep 17 00:00:00 2001 From: Jonathan Marshall Date: Sat, 2 Nov 2013 23:53:34 +1300 -Subject: [PATCH 11/77] REMOVEME: updated thetvdb.com scraper to support art +Subject: [PATCH 09/82] REMOVEME: updated thetvdb.com scraper to support art updates --- @@ -2366,10 +1472,10 @@ index f27e4fc..bdf329f 100644 -From 0d268f2c4ccf5ccce96f8b56235ce2be2c39e30e Mon Sep 17 00:00:00 2001 +From 08e7b88346eff63caf9587325847399361cb9862 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 2 Aug 2014 17:48:04 +0100 -Subject: [PATCH 12/77] [omx] Report decoded image name +Subject: [PATCH 10/82] [omx] Report decoded image name --- xbmc/cores/omxplayer/OMXImage.cpp | 1 + @@ -2388,10 +1494,10 @@ index 3fbea3b..57f69c5 100644 else { -From c90a0c3aceeaf3dec055ede0126eb495dcc331dc Mon Sep 17 00:00:00 2001 +From 99fd138ae7e2f0f160f1214e1b0b046ccd8f0d8a Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 14 Dec 2013 16:55:05 +0000 -Subject: [PATCH 13/77] logging: Add microsecond timer to log messages +Subject: [PATCH 11/82] logging: Add microsecond timer to log messages --- xbmc/utils/log.cpp | 12 ++++++++---- @@ -2437,10 +1543,10 @@ index 4e51166..8ed8eec 100644 levelNames[logLevel]) + strData; -From ede35f9c20d4468b43987b49182f6f73e5d75882 Mon Sep 17 00:00:00 2001 +From 74ed6d07664e3cf3503fb3a8e52666d269d14719 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 8 Mar 2014 15:36:06 +0000 -Subject: [PATCH 17/77] [hifiberry] Hack: force it to be recognised as IEC958 +Subject: [PATCH 14/82] [hifiberry] Hack: force it to be recognised as IEC958 capable to enable passthrough options --- @@ -2463,10 +1569,10 @@ index a464b4b..7eba389 100644 info.m_displayName.substr(info.m_displayName.size()-5) == " HDMI") { -From 205678b81f1602bfa11de7f4993a3e94d0bd93ab Mon Sep 17 00:00:00 2001 +From 630974ad95c6cb92ecf0f09ea5d9fdf714952097 Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Wed, 11 Dec 2013 17:21:54 +0000 -Subject: [PATCH 18/77] Move the reference-counting of Begin and End calls from +Subject: [PATCH 15/82] Move the reference-counting of Begin and End calls from DX and GL source files into GUIFontTTF.cpp. --- @@ -2854,10 +1960,10 @@ index c0bb53a..735fb3a 100644 protected: virtual CBaseTexture* ReallocTexture(unsigned int& newHeight); -From 70d3e4869c1eb9a308a6ff32a1cd13958dd3f3be Mon Sep 17 00:00:00 2001 +From f6390582c089b3fe0a45f92f73a3f7a46340b204 Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Wed, 11 Dec 2013 18:47:54 +0000 -Subject: [PATCH 19/77] Convert CGUIFontTTFBase::m_vertex to be managed as a +Subject: [PATCH 16/82] Convert CGUIFontTTFBase::m_vertex to be managed as a std::vector. Also retired CGUIFontTTFBase::m_vertex_count and @@ -3037,10 +2143,10 @@ index 97853fd..b76c6a5 100644 *vertices++ = m_vertex[i]; *vertices++ = m_vertex[i+1]; -From 0ad5ef4114e14d2a2df50dad2013cad5525752c1 Mon Sep 17 00:00:00 2001 +From 8abe127f37de7746803cc29bed9d586c2dd72e50 Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Mon, 16 Dec 2013 18:58:12 +0000 -Subject: [PATCH 20/77] CGUIFontTTFBase::RenderCharacter can now append to +Subject: [PATCH 17/82] CGUIFontTTFBase::RenderCharacter can now append to arbitrary vectors of vertices rather than only CGUIFontTTFBase::m_vertex --- @@ -3113,10 +2219,10 @@ index 10a7060..dde0350 100644 virtual CBaseTexture* ReallocTexture(unsigned int& newHeight) = 0; -From 4a29d6593f48ecac6b1cee902dccbbfd99bd4348 Mon Sep 17 00:00:00 2001 +From d00f850afefc2d0262859fa291f32c571ab38182 Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Wed, 15 Jan 2014 17:18:38 +0000 -Subject: [PATCH 21/77] Add a cache of font glyph bounding box vertices. +Subject: [PATCH 18/82] Add a cache of font glyph bounding box vertices. This is implemented as a template because ultimately we will key on different parameters and store values of different types, depending upon whether we @@ -3139,7 +2245,7 @@ applicable transformation matrices permit the use of hardware clipping. create mode 100644 xbmc/guilib/GUIFontCache.h diff --git a/XBMC.xcodeproj/project.pbxproj b/XBMC.xcodeproj/project.pbxproj -index 10a2e89..1eb7173 100644 +index 3c6c77e..f6722e7 100644 --- a/XBMC.xcodeproj/project.pbxproj +++ b/XBMC.xcodeproj/project.pbxproj @@ -168,6 +168,9 @@ @@ -3152,7 +2258,7 @@ index 10a2e89..1eb7173 100644 32C631281423A90F00F18420 /* JpegIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 32C631261423A90F00F18420 /* JpegIO.cpp */; }; 36A9443D15821E2800727135 /* DatabaseUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9443B15821E2800727135 /* DatabaseUtils.cpp */; }; 36A9444115821E7C00727135 /* SortUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9443F15821E7C00727135 /* SortUtils.cpp */; }; -@@ -4008,6 +4011,8 @@ +@@ -4011,6 +4014,8 @@ 1DAFDB7B16DFDCA7007F8C68 /* PeripheralBusCEC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PeripheralBusCEC.h; sourceTree = ""; }; 1DE0443315828F4B005DDB4D /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Exception.cpp; path = commons/Exception.cpp; sourceTree = ""; }; 1DE0443415828F4B005DDB4D /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Exception.h; path = commons/Exception.h; sourceTree = ""; }; @@ -3161,7 +2267,7 @@ index 10a2e89..1eb7173 100644 32C631261423A90F00F18420 /* JpegIO.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JpegIO.cpp; sourceTree = ""; }; 32C631271423A90F00F18420 /* JpegIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JpegIO.h; sourceTree = ""; }; 36A9443B15821E2800727135 /* DatabaseUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseUtils.cpp; sourceTree = ""; }; -@@ -6513,6 +6518,8 @@ +@@ -6518,6 +6523,8 @@ 18B7C7101294222D009E7A26 /* GUIFixedListContainer.h */, 18B7C76B1294222E009E7A26 /* GUIFont.cpp */, 18B7C7111294222D009E7A26 /* GUIFont.h */, @@ -3170,7 +2276,7 @@ index 10a2e89..1eb7173 100644 18B7C76C1294222E009E7A26 /* GUIFontManager.cpp */, 18B7C7121294222D009E7A26 /* GUIFontManager.h */, 18B7C76D1294222E009E7A26 /* GUIFontTTF.cpp */, -@@ -11000,6 +11007,7 @@ +@@ -11007,6 +11014,7 @@ 7C5608C70F1754930056433A /* ExternalPlayer.cpp in Sources */, F584E12E0F257C5100DB26A5 /* HTTPDirectory.cpp in Sources */, F54C51D20F1E783200D46E3C /* GUIDialogKaraokeSongSelector.cpp in Sources */, @@ -3178,7 +2284,7 @@ index 10a2e89..1eb7173 100644 F54C51D50F1E784800D46E3C /* karaokelyricscdg.cpp in Sources */, F54C51D80F1E785700D46E3C /* karaokelyrics.cpp in Sources */, F54C51E50F1E787700D46E3C /* karaokelyricstextkar.cpp in Sources */, -@@ -12666,6 +12674,7 @@ +@@ -12675,6 +12683,7 @@ DFF0F45B17528350002DA3A4 /* Control.cpp in Sources */, DFF0F45C17528350002DA3A4 /* Dialog.cpp in Sources */, DFF0F45D17528350002DA3A4 /* File.cpp in Sources */, @@ -3186,7 +2292,7 @@ index 10a2e89..1eb7173 100644 DFF0F45E17528350002DA3A4 /* InfoTagMusic.cpp in Sources */, DFF0F45F17528350002DA3A4 /* InfoTagVideo.cpp in Sources */, DFF0F46017528350002DA3A4 /* Keyboard.cpp in Sources */, -@@ -13465,6 +13474,7 @@ +@@ -13474,6 +13483,7 @@ E499131D174E5DAD00741B6D /* GUIVisualisationControl.cpp in Sources */, E499131E174E5DAD00741B6D /* GUIWindow.cpp in Sources */, E499131F174E5DAD00741B6D /* GUIWindowManager.cpp in Sources */, @@ -3195,10 +2301,10 @@ index 10a2e89..1eb7173 100644 E4991321174E5DAD00741B6D /* imagefactory.cpp in Sources */, E4991322174E5DAD00741B6D /* IWindowManagerCallback.cpp in Sources */, diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj -index 8e1e4df..a8f3426 100644 +index ff9e0ff..d3639f2 100644 --- a/project/VS2010Express/XBMC.vcxproj +++ b/project/VS2010Express/XBMC.vcxproj -@@ -425,6 +425,7 @@ +@@ -426,6 +426,7 @@ @@ -3206,7 +2312,7 @@ index 8e1e4df..a8f3426 100644 -@@ -1744,6 +1745,7 @@ +@@ -1748,6 +1749,7 @@ @@ -3215,10 +2321,10 @@ index 8e1e4df..a8f3426 100644 diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters -index fcec4f0..e8ac96e 100644 +index 2e43d7c..5d9c6f3 100644 --- a/project/VS2010Express/XBMC.vcxproj.filters +++ b/project/VS2010Express/XBMC.vcxproj.filters -@@ -991,6 +991,9 @@ +@@ -994,6 +994,9 @@ guilib @@ -3228,7 +2334,7 @@ index fcec4f0..e8ac96e 100644 guilib -@@ -3882,6 +3885,9 @@ +@@ -3891,6 +3894,9 @@ guilib @@ -3876,10 +2982,10 @@ index f351c99..9036ba9 100644 + return !operator==(a, b); +} -From 7a0a7b745d08f94b93ab789b33aa9447e9427e29 Mon Sep 17 00:00:00 2001 +From e2248c28d591b4ae20bb748823661f26da3bc384 Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Thu, 23 Jan 2014 22:24:17 +0000 -Subject: [PATCH 22/77] Lay the groundwork for hardware clipping. +Subject: [PATCH 19/82] Lay the groundwork for hardware clipping. For glScissor() to replace CGraphicContext::ClipRect, a necessary condition is that no shear or rotation is introduced between the coordinate systems @@ -4141,10 +3247,10 @@ index 98e398a..81ee49e 100644 virtual void ResetScissors(); -From a5604966904a4e2fc856bd7c34175a71ca530dfe Mon Sep 17 00:00:00 2001 +From 7aa8b3db78cead1355ac78f516a6cd8addb7346e Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Thu, 23 Jan 2014 16:42:22 +0000 -Subject: [PATCH 23/77] Increase font cache hit rate by keying on the +Subject: [PATCH 20/82] Increase font cache hit rate by keying on the fractional part of m_originX and m_originY *after* they have been through the graphics context's transformation matrix, plus the scale/rotation elements of the matrix, rather than the origin in the original frame of reference plus @@ -4345,10 +3451,10 @@ index 77111bc..39bfa52 100644 private: virtual bool FirstBegin() = 0; -From 37f4f936fe6d927b8c556a46d812cebbbe5475d7 Mon Sep 17 00:00:00 2001 +From 3d36d856b5b494dfb911e7df87ddf5a85a414719 Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Wed, 8 Jan 2014 12:16:33 +0000 -Subject: [PATCH 24/77] Rewrite of scrolling text code. +Subject: [PATCH 21/82] Rewrite of scrolling text code. No longer shuffles the string round to minimise the number of characters before the clipping rectangle; this doesn't save much on rendering time but @@ -4664,10 +3770,10 @@ index 2cda726..fbc579e 100644 private: void Process(); -From 7bedebd03ff7a7986f178714a3586a07c3d5a9b5 Mon Sep 17 00:00:00 2001 +From f8ddebec82988b66204874dd0fc0fd99de8856f3 Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Mon, 27 Jan 2014 23:21:10 +0000 -Subject: [PATCH 25/77] Move the application of the translation offsets into +Subject: [PATCH 22/82] Move the application of the translation offsets into the GLES code. Still all pure software at this stage. Main change is in the data types at @@ -4861,10 +3967,10 @@ index 9935ea4..18c9358 100644 memset(newTexture->GetPixels(), 0, m_textureHeight * newTexture->GetPitch()); if (m_texture) -From e0abdac7367737366a3d1054a2cef8568f6cd6ad Mon Sep 17 00:00:00 2001 +From b3c7a0fac81bd97f239ffa8bd82968d33a82156c Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Wed, 15 Jan 2014 15:28:06 +0000 -Subject: [PATCH 26/77] Rather than applying the translation offsets to the +Subject: [PATCH 23/82] Rather than applying the translation offsets to the vertices, now applies them to the model view matrix from the top of the matrix stack and pushes it over to OpenGL. The vertices themselves are still all held client-side. @@ -5008,10 +4114,10 @@ index 81ee49e..d2f9cd1 100644 protected: virtual void SetVSyncImpl(bool enable) = 0; -From 54e3057566feeaea70e61b7d5173857a37cfad23 Mon Sep 17 00:00:00 2001 +From 6a7471d35bcf13a09d4eec164900e2ff48081dde Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Wed, 29 Jan 2014 13:21:19 +0000 -Subject: [PATCH 27/77] Enable hardware clipping. +Subject: [PATCH 24/82] Enable hardware clipping. --- xbmc/guilib/GUIFontTTF.cpp | 4 ++-- @@ -5084,10 +4190,10 @@ index ea08bf4..b63e337 100644 glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW)); } -From 73c558a08f0441236fb44e408c4ad507d27e056a Mon Sep 17 00:00:00 2001 +From 556f6e65dcf67b6a6ca1b7d5b8c7918af1fa81bb Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Wed, 15 Jan 2014 15:32:51 +0000 -Subject: [PATCH 28/77] Move the vertex data across to a vertex buffer object +Subject: [PATCH 25/82] Move the vertex data across to a vertex buffer object just prior to drawing. --- @@ -5138,10 +4244,10 @@ index b63e337..b00055d 100644 // Disable the attributes used by this shader -From 1bdbf7a657217a2974e830f711a84d843f9f574f Mon Sep 17 00:00:00 2001 +From 39b12db282b00732a5e39e3ed10361dfc5888ee1 Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Wed, 15 Jan 2014 16:04:04 +0000 -Subject: [PATCH 29/77] Move vertex data into an OpenGL VBO when the font cache +Subject: [PATCH 26/82] Move vertex data into an OpenGL VBO when the font cache entry is populated. The font cache now stores the "name" (handle) of the VBO, rather than a vector @@ -5414,10 +4520,10 @@ index 735fb3a..6102c90 100644 protected: virtual CBaseTexture* ReallocTexture(unsigned int& newHeight); -From 774a3446b96a8c39b7a98a5e0663564893d50965 Mon Sep 17 00:00:00 2001 +From 3da3676ff144ad7d67c93ac2c278142964072078 Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Thu, 16 Jan 2014 16:29:42 +0000 -Subject: [PATCH 30/77] Switch from glDrawArrays() to glDrawElements(). +Subject: [PATCH 27/82] Switch from glDrawArrays() to glDrawElements(). This involves setting up a static VBO containing the indexes necessary to convert from quads to triangles on the fly in the GPU. @@ -5638,10 +4744,10 @@ index 6de3532..258a293 100644 if (m_display != EGL_NO_DISPLAY) -From 09468bf68f2b5047849b0731d46bb5528cee6d4d Mon Sep 17 00:00:00 2001 +From dcbc3dbce334053e9233e9df63d66af5b7f65902 Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Thu, 1 May 2014 16:28:39 +0100 -Subject: [PATCH 31/77] Improved file buffering in CArchive +Subject: [PATCH 28/82] Improved file buffering in CArchive Even though memcpy is typically inlined by the compiler into byte/word loads and stores (at least for release builds), the frequency with which 1, 2 and 4 @@ -5701,256 +4807,131 @@ index 6ed0f8f..8506d95 100644 } else -From 6ce2c7d35b7ca4355b7cd687ecbc29238d28808c Mon Sep 17 00:00:00 2001 +From 1dfe980dbbd32d81225268b6268b9d0b01b96efe Mon Sep 17 00:00:00 2001 From: popcornmix -Date: Wed, 9 Jul 2014 01:14:23 +0100 -Subject: [PATCH 32/77] [omxcodec] Switch to MMAL decoder with MMAL renderer +Date: Wed, 10 Sep 2014 21:35:12 +0100 +Subject: [PATCH 29/82] [mmal] Add MMAL decoder and MMAL renderer for Raspberry + Pi +While omxplayer is the best performing player on the Pi (and the only option for raw Blu-Rays) +there are some reasons to use dvdplayer on a Pi: + +DVDs with menus do not work well with omxplayer +support of software decode for SD codecs like divx3, msmpeg, sorenson spark etc +omxplayer doesn't support alsa, so can't be used with USB and I2S sound cards +dvdplayer may behave better with dodgy timestamps and packet loss, e.g. with live TV + +So this PR adds hardware acceleration to dvdplayer using the MMAL api. + +There is also a MMAL based video renderer. Compared to using GL, this: +saves the processing cost of YUV->RGB conversion +saves the memory cost of the RGB textures for video frames (1080p = 3MB for YUV and 8MB for RGB) +allows high quality (cubic) scaling --- - configure.in | 23 +- - language/English/strings.po | 2 +- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 78 - - xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 8 +- - xbmc/cores/VideoRenderers/Makefile.in | 1 + - xbmc/cores/VideoRenderers/OMXRenderer.cpp | 784 +++++++++ - xbmc/cores/VideoRenderers/OMXRenderer.h | 129 ++ - xbmc/cores/VideoRenderers/RenderManager.cpp | 6 +- + configure.in | 4 +- + language/English/strings.po | 14 +- + system/settings/rbp.xml | 8 + + xbmc/cores/VideoRenderers/MMALRenderer.cpp | 726 +++++++++++++ + xbmc/cores/VideoRenderers/MMALRenderer.h | 129 +++ + xbmc/cores/VideoRenderers/Makefile.in | 4 + + xbmc/cores/VideoRenderers/RenderFormats.h | 1 + + xbmc/cores/VideoRenderers/RenderManager.cpp | 8 + xbmc/cores/VideoRenderers/RenderManager.h | 3 + - xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 9 +- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 7 +- - .../DVDCodecs/Video/DVDVideoCodecOpenMax.cpp | 301 +--- - .../DVDCodecs/Video/DVDVideoCodecOpenMax.h | 38 +- - xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in | 1 - - .../dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp | 1727 ++++++++++---------- - .../cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h | 165 +- - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 2 +- - 17 files changed, 1975 insertions(+), 1309 deletions(-) - create mode 100644 xbmc/cores/VideoRenderers/OMXRenderer.cpp - create mode 100644 xbmc/cores/VideoRenderers/OMXRenderer.h + xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 14 + + .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 5 + + .../DVDCodecs/Video/DVDVideoCodecMMAL.cpp | 99 ++ + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h | 50 + + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 1084 ++++++++++++++++++++ + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h | 157 +++ + xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in | 5 + + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 1 + + 17 files changed, 2310 insertions(+), 2 deletions(-) + create mode 100644 xbmc/cores/VideoRenderers/MMALRenderer.cpp + create mode 100644 xbmc/cores/VideoRenderers/MMALRenderer.h + create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp + create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h + create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp + create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h diff --git a/configure.in b/configure.in -index fcb7b62..c0ea777 100644 +index 490b12b..8bf74cd 100644 --- a/configure.in +++ b/configure.in -@@ -1003,7 +1003,7 @@ if test "$use_gles" = "yes"; then +@@ -721,6 +721,7 @@ case $use_platform in + ARCH="arm" + AC_DEFINE(HAS_EGLGLES, [1], [Define if supporting EGL based GLES Framebuffer]) + USE_OMXLIB=1; AC_DEFINE([HAVE_OMXLIB],[1],["Define to 1 if OMX libs is enabled"]) ++ USE_MMAL=1; AC_DEFINE([HAS_MMAL],[1],["Define to 1 if MMAL libs is enabled"]) + CFLAGS="$CFLAGS" + CXXFLAGS="$CXXFLAGS" + ;; +@@ -1010,7 +1011,7 @@ if test "$use_gles" = "yes"; then AC_DEFINE([HAVE_LIBEGL],[1],["Define to 1 if you have the `EGL' library (-lEGL)."]) AC_DEFINE([HAVE_LIBGLESV2],[1],["Define to 1 if you have the `GLESv2' library (-lGLESv2)."]) AC_MSG_RESULT(== WARNING: OpenGLES support is assumed.) - LIBS="$LIBS -lEGL -lGLESv2 -lbcm_host -lvcos -lvchiq_arm" -+ LIBS="$LIBS -lEGL -lGLESv2 -lbcm_host -lvcos -lvchiq_arm -lvchiq_arm -lmmal -lmmal_core -lmmal_util" ++ LIBS="$LIBS -lEGL -lGLESv2 -lbcm_host -lvcos -lvchiq_arm -lmmal -lmmal_core -lmmal_util" else AC_CHECK_LIB([EGL], [main],, AC_MSG_ERROR($missing_library)) AC_CHECK_LIB([GLESv2],[main],, AC_MSG_ERROR($missing_library)) -@@ -1865,9 +1865,24 @@ if test "$host_vendor" = "apple" ; then - USE_OPENMAX=0 - AC_MSG_NOTICE($openmax_disabled) - elif test "$target_platform" = "target_raspberry_pi"; then -- use_openmax="no" -- USE_OPENMAX=0 -- AC_MSG_NOTICE($openmax_disabled) -+ if test "$use_gles" = "yes" && test "$use_openmax" = "auto"; then -+ use_openmax="yes" -+ USE_OPENMAX=1 -+ HAVE_LIBOPENMAX=1 -+ AC_DEFINE([HAVE_LIBOPENMAX], [1], [Define to 1 if you have the 'LIBOPENMAX' library.]) -+ AC_DEFINE([OMX_SKIP64BIT], [1], [Define to 1 if you have the 'LIBOPENMAX' library.]) -+ AC_MSG_NOTICE($openmax_enabled) -+ elif test "$use_gles" = "yes" && test "$use_openmax" = "yes"; then -+ use_openmax="yes" -+ USE_OPENMAX=1 -+ HAVE_LIBOPENMAX=1 -+ AC_DEFINE([HAVE_LIBOPENMAX], [1], [Define to 1 if you have the 'LIBOPENMAX' library.]) -+ AC_MSG_NOTICE($openmax_enabled) -+ else -+ AC_MSG_NOTICE($openmax_disabled) -+ use_openmax=no -+ USE_OPENMAX=0 -+ fi - else - if test "$use_gles" = "yes" && test "$use_openmax" = "auto"; then - PKG_CHECK_MODULES([OPENMAX], [libomxil-bellagio], +@@ -2583,6 +2584,7 @@ AC_SUBST(USE_DOXYGEN) + AC_SUBST(USE_PVR_ADDONS) + AC_SUBST(UPNP_DEFINES) + AC_SUBST(USE_SSE4) ++AC_SUBST(USE_MMAL) + + # pushd and popd are not available in other shells besides bash, so implement + # our own pushd/popd functions diff --git a/language/English/strings.po b/language/English/strings.po -index fea6e08..ade855e 100755 +index 348b77e..03b4146 100755 --- a/language/English/strings.po +++ b/language/English/strings.po -@@ -13864,7 +13864,7 @@ msgstr "" - #. Description of setting "Videos -> Playback -> Allow hardware acceleration (OpenMax)" with label #13430 - #: system/settings/settings.xml - msgctxt "#36161" --msgid "Enable OpenMax hardware decoding of video files." -+msgid "Enable OpenMax hardware decoding of video files (using DVDPlayer)." +@@ -15409,7 +15409,19 @@ msgctxt "#36433" + msgid "If enabled VAAPI render method is prefered. This puts less load on the CPU but driver may hang!" msgstr "" - #. Description of setting "Videos -> Playback -> Allow hardware acceleration (VideoToolbox)" with label #13432 -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 8db4ea1..d946e03 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -101,9 +101,6 @@ CLinuxRendererGLES::YUVBUFFER::YUVBUFFER() - memset(&fields, 0, sizeof(fields)); - memset(&image , 0, sizeof(image)); - flipindex = 0; --#ifdef HAVE_LIBOPENMAX -- openMaxBuffer = NULL; --#endif - #ifdef HAVE_VIDEOTOOLBOXDECODER - cvBufferRef = NULL; - #endif -@@ -616,9 +613,6 @@ unsigned int CLinuxRendererGLES::PreInit() - m_formats.push_back(RENDER_FMT_YUV420P); - m_formats.push_back(RENDER_FMT_NV12); - m_formats.push_back(RENDER_FMT_BYPASS); --#if defined(HAVE_LIBOPENMAX) -- m_formats.push_back(RENDER_FMT_OMXEGL); --#endif - #ifdef HAVE_VIDEOTOOLBOXDECODER - m_formats.push_back(RENDER_FMT_CVBREF); - #endif -@@ -1369,67 +1363,6 @@ void CLinuxRendererGLES::RenderSoftware(int index, int field) - VerifyGLState(); - } +-#empty strings from id 36434 to 36499 ++#. Description of setting "Videos -> Playback -> Enable MMAL hardware decoding of video files" ++#: system/settings/settings.xml ++msgctxt "#36434" ++msgid "Allow hardware acceleration (MMAL)" ++msgstr "" ++ ++#. Description of setting "Videos -> Playback -> Enable MMAL hardware decoding of video files" ++#: system/settings/settings.xml ++msgctxt "#36435" ++msgid "Use DVDPlayer for decoding of video files with MMAL acceleration." ++msgstr "" ++ ++#empty strings from id 36436 to 36499 + #end reservation --void CLinuxRendererGLES::RenderOpenMax(int index, int field) --{ --#if defined(HAVE_LIBOPENMAX) -- GLuint textureId = m_buffers[index].openMaxBuffer->texture_id; -- -- glDisable(GL_DEPTH_TEST); -- -- // Y -- glEnable(m_textureTarget); -- glActiveTexture(GL_TEXTURE0); -- glBindTexture(m_textureTarget, textureId); -- -- g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA); -- -- GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip -- GLfloat ver[4][4]; -- GLfloat tex[4][2]; -- GLfloat col[3] = {1.0f, 1.0f, 1.0f}; -- -- GLint posLoc = g_Windowing.GUIShaderGetPos(); -- GLint texLoc = g_Windowing.GUIShaderGetCoord0(); -- GLint colLoc = g_Windowing.GUIShaderGetCol(); -- -- glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver); -- glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex); -- glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col); -- -- glEnableVertexAttribArray(posLoc); -- glEnableVertexAttribArray(texLoc); -- glEnableVertexAttribArray(colLoc); -- -- // Set vertex coordinates -- for(int i = 0; i < 4; i++) -- { -- ver[i][0] = m_rotatedDestCoords[i].x; -- ver[i][1] = m_rotatedDestCoords[i].y; -- ver[i][2] = 0.0f;// set z to 0 -- ver[i][3] = 1.0f; -- } -- -- // Set texture coordinates -- tex[0][0] = tex[3][0] = 0; -- tex[0][1] = tex[1][1] = 0; -- tex[1][0] = tex[2][0] = 1; -- tex[2][1] = tex[3][1] = 1; -- -- glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx); -- -- glDisableVertexAttribArray(posLoc); -- glDisableVertexAttribArray(texLoc); -- glDisableVertexAttribArray(colLoc); -- -- g_Windowing.DisableGUIShader(); -- -- VerifyGLState(); -- -- glDisable(m_textureTarget); -- VerifyGLState(); --#endif --} -- - void CLinuxRendererGLES::RenderEglImage(int index, int field) - { - #if defined(HAS_LIBSTAGEFRIGHT) -@@ -1786,11 +1719,7 @@ void CLinuxRendererGLES::UploadYV12Texture(int source) - YUVFIELDS& fields = buf.fields; - - --#if defined(HAVE_LIBOPENMAX) -- if (!(im->flags&IMAGE_FLAG_READY) || m_buffers[source].openMaxBuffer) --#else - if (!(im->flags&IMAGE_FLAG_READY)) --#endif - { - return; - } -@@ -2904,13 +2833,6 @@ unsigned int CLinuxRendererGLES::GetProcessorSize() - return 0; - } - --#ifdef HAVE_LIBOPENMAX --void CLinuxRendererGLES::AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index) --{ -- YUVBUFFER &buf = m_buffers[index]; -- buf.openMaxBuffer = picture->openMaxBuffer; --} --#endif - #ifdef HAVE_VIDEOTOOLBOXDECODER - void CLinuxRendererGLES::AddProcessor(struct __CVBuffer *cvBufferRef, int index) - { -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -index 1e89ecf..2cc5821 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -@@ -39,7 +39,7 @@ class CRenderCapture; - class CBaseTexture; - namespace Shaders { class BaseYUV2RGBShader; } - namespace Shaders { class BaseVideoFilterShader; } --class COpenMaxVideo; -+class COpenMaxVideoBuffer; - class CDVDVideoCodecStageFright; - class CDVDMediaCodecInfo; - typedef std::vector Features; -@@ -158,9 +158,6 @@ class CLinuxRendererGLES : public CBaseRenderer - - virtual std::vector SupportedFormats() { return m_formats; } - --#ifdef HAVE_LIBOPENMAX -- virtual void AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index); --#endif - #ifdef HAVE_VIDEOTOOLBOXDECODER - virtual void AddProcessor(struct __CVBuffer *cvBufferRef, int index); - #endif -@@ -280,9 +277,6 @@ class CLinuxRendererGLES : public CBaseRenderer - YV12Image image; - unsigned flipindex; /* used to decide if this has been uploaded */ - --#ifdef HAVE_LIBOPENMAX -- OpenMaxVideoBuffer *openMaxBuffer; --#endif - #ifdef HAVE_VIDEOTOOLBOXDECODER - struct __CVBuffer *cvBufferRef; - #endif -diff --git a/xbmc/cores/VideoRenderers/Makefile.in b/xbmc/cores/VideoRenderers/Makefile.in -index d964285..5b78852 100644 ---- a/xbmc/cores/VideoRenderers/Makefile.in -+++ b/xbmc/cores/VideoRenderers/Makefile.in -@@ -18,6 +18,7 @@ endif - ifeq (@USE_OPENGLES@,1) - SRCS += LinuxRendererGLES.cpp - SRCS += OverlayRendererGL.cpp -+SRCS += OMXRenderer.cpp - endif - - LIB = VideoRenderer.a -diff --git a/xbmc/cores/VideoRenderers/OMXRenderer.cpp b/xbmc/cores/VideoRenderers/OMXRenderer.cpp + #: system/settings/settings.xml +diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml +index 28e68eb..bbb2076 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -16,6 +16,14 @@ + + false + ++ ++ ++ 1 ++ ++ 2 ++ true ++ ++ + + + +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp new file mode 100644 -index 0000000..ceaec7a +index 0000000..9a81eb9 --- /dev/null -+++ b/xbmc/cores/VideoRenderers/OMXRenderer.cpp -@@ -0,0 +1,784 @@ ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +@@ -0,0 +1,726 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org @@ -5971,10 +4952,8 @@ index 0000000..ceaec7a + * + */ + -+#ifdef TARGET_RASPBERRY_PI -+ +#include "Util.h" -+#include "OMXRenderer.h" ++#include "MMALRenderer.h" +#include "cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h" +#include "filesystem/File.h" +#include "settings/AdvancedSettings.h" @@ -5985,13 +4964,13 @@ index 0000000..ceaec7a +#include "utils/log.h" +#include "utils/MathUtils.h" +#include "windowing/WindowingFactory.h" -+#include "cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h" ++#include "cores/dvdplayer/DVDCodecs/Video/MMALCodec.h" +#include "xbmc/Application.h" + -+#define CLASSNAME "COMXRenderer" ++#define CLASSNAME "CMMALRenderer" + +#ifdef _DEBUG -+#define OMX_DEBUG_VERBOSE ++#define MMAL_DEBUG_VERBOSE +#endif + +static void vout_control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) @@ -5999,19 +4978,17 @@ index 0000000..ceaec7a + mmal_buffer_header_release(buffer); +} + -+void COMXRenderer::vout_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) ++void CMMALRenderer::vout_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) +{ -+ COpenMaxVideoBuffer *omvb = (COpenMaxVideoBuffer *)buffer->user_data; ++ CMMALVideoBuffer *omvb = (CMMALVideoBuffer *)buffer->user_data; + -+ #if defined(OMX_DEBUG_VERBOSE) ++ #if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s port:%p buffer %p (%p), len %d cmd:%x", CLASSNAME, __func__, port, buffer, omvb, buffer->length, buffer->cmd); + #endif + -+ if (m_format == RENDER_FMT_OMXEGL) ++ if (m_format == RENDER_FMT_MMAL) + { -+ #if defined(HAVE_LIBOPENMAX) + mmal_queue_put(m_release_queue, buffer); -+ #endif + } + else if (m_format == RENDER_FMT_YUV420P) + { @@ -6022,14 +4999,13 @@ index 0000000..ceaec7a + +static void vout_input_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) +{ -+ COMXRenderer *omx = reinterpret_cast(port->userdata); -+ omx->vout_input_port_cb(port, buffer); ++ CMMALRenderer *mmal = reinterpret_cast(port->userdata); ++ mmal->vout_input_port_cb(port, buffer); +} + -+bool COMXRenderer::init_vout(MMAL_ES_FORMAT_T *format) ++bool CMMALRenderer::init_vout(MMAL_ES_FORMAT_T *format) +{ + MMAL_STATUS_T status; -+ // todo: deinterlace + + CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); + @@ -6059,7 +5035,7 @@ index 0000000..ceaec7a + } + + if (m_format == RENDER_FMT_YUV420P) -+ m_vout_input->buffer_num = m_NumYV12Buffers; ++ m_vout_input->buffer_num = NUM_BUFFERS; + else + m_vout_input->buffer_num = m_vout_input->buffer_num_min; + m_vout_input->buffer_size = m_vout_input->buffer_size_recommended; @@ -6090,51 +5066,19 @@ index 0000000..ceaec7a + return true; +} + -+bool COMXRenderer::change_vout_input_format(MMAL_ES_FORMAT_T *format) ++void CMMALRenderer::Process() +{ -+ MMAL_STATUS_T status; -+ CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); -+ -+ status = mmal_port_disable(m_vout_input); -+ if (status != MMAL_SUCCESS) ++ MMAL_BUFFER_HEADER_T *buffer; ++ while (buffer = mmal_queue_wait(m_release_queue), buffer) + { -+ CLog::Log(LOGERROR, "%s::%s Failed to disable vout input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ mmal_format_full_copy(m_vout_input->format, format); -+ status = mmal_port_format_commit(m_vout_input); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to commit vout input format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ m_vout_input->buffer_size = m_vout_input->buffer_size_min; -+ status = mmal_port_enable(m_vout_input, vout_input_port_cb_static); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to enable vout input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ return true; -+} -+ -+ -+static void *vout_worker(void *p) -+{ -+ MMAL_QUEUE_T *queue = (MMAL_QUEUE_T *)p; -+ -+ while (true) -+ { -+ MMAL_BUFFER_HEADER_T *buffer = mmal_queue_wait(queue); -+ COpenMaxVideoBuffer *omvb = (COpenMaxVideoBuffer *)buffer->user_data; ++ CMMALVideoBuffer *omvb = (CMMALVideoBuffer *)buffer->user_data; + omvb->Release(); + } -+ return NULL; ++ m_sync.Set(); +} + -+COMXRenderer::COMXRenderer() ++CMMALRenderer::CMMALRenderer() ++: CThread("CMMALRenderer") +{ + CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); + m_vout = NULL; @@ -6142,30 +5086,32 @@ index 0000000..ceaec7a + m_vout_input_pool = NULL; + memset(m_buffers, 0, sizeof m_buffers); + m_release_queue = mmal_queue_create(); -+ pthread_create(&m_worker, NULL, vout_worker, (void *)m_release_queue); ++ Create(); +} + -+COMXRenderer::~COMXRenderer() ++CMMALRenderer::~CMMALRenderer() +{ + CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); ++ // shutdown thread ++ mmal_queue_put(m_release_queue, NULL); ++ m_sync.Wait(); ++ mmal_queue_destroy(m_release_queue); + UnInit(); +} + -+void COMXRenderer::AddProcessor(COpenMaxVideoBuffer *openMaxBuffer, int index) ++void CMMALRenderer::AddProcessor(CMMALVideoBuffer *buffer, int index) +{ -+#if defined(HAVE_LIBOPENMAX) -+#if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s - %p (%p) %i", CLASSNAME, __func__, openMaxBuffer, openMaxBuffer->mmal_buffer, index); ++#if defined(MMAL_DEBUG_VERBOSE) ++ CLog::Log(LOGDEBUG, "%s::%s - %p (%p) %i", CLASSNAME, __func__, buffer, buffer->mmal_buffer, index); +#endif + + YUVBUFFER &buf = m_buffers[index]; -+ assert(!buf.openMaxBuffer); ++ assert(!buf.MMALBuffer); + memset(&buf, 0, sizeof buf); -+ buf.openMaxBuffer = openMaxBuffer->Acquire(); -+#endif ++ buf.MMALBuffer = buffer->Acquire(); +} + -+bool COMXRenderer::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation) ++bool CMMALRenderer::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation) +{ + ReleaseBuffers(); + @@ -6209,14 +5155,48 @@ index 0000000..ceaec7a + SetViewMode(CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode); + ManageDisplay(); + -+ m_bConfigured = true; ++ if (m_format == RENDER_FMT_MMAL|| m_format == RENDER_FMT_YUV420P) ++ { ++ MMAL_ES_FORMAT_T *es_format = mmal_format_alloc(); ++ es_format->type = MMAL_ES_TYPE_VIDEO; ++ es_format->es->video.crop.width = m_sourceWidth; ++ es_format->es->video.crop.height = m_sourceHeight; + -+ return true; ++ if (m_format == RENDER_FMT_MMAL) ++ { ++ es_format->encoding = MMAL_ENCODING_OPAQUE; ++ es_format->es->video.width = m_sourceWidth; ++ es_format->es->video.height = m_sourceHeight; ++ } ++ else if (m_format == RENDER_FMT_YUV420P) ++ { ++ const int pitch = ALIGN_UP(m_sourceWidth, 32); ++ const int aligned_height = ALIGN_UP(m_sourceHeight, 16); ++ ++ es_format->encoding = MMAL_ENCODING_I420; ++ es_format->es->video.width = pitch; ++ es_format->es->video.height = aligned_height; ++ ++ if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT709) ++ es_format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT709; ++ else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT601) ++ es_format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT601; ++ else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_240M) ++ es_format->es->video.color_space = MMAL_COLOR_SPACE_SMPTE240M; ++ } ++ assert(!m_vout); ++ m_bConfigured = init_vout(es_format); ++ mmal_format_free(es_format); ++ } ++ else ++ m_bConfigured = true; ++ ++ return m_bConfigured; +} + -+int COMXRenderer::GetImage(YV12Image *image, int source, bool readonly) ++int CMMALRenderer::GetImage(YV12Image *image, int source, bool readonly) +{ -+#if defined(OMX_DEBUG_VERBOSE) ++#if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s - %p %d %d", CLASSNAME, __func__, image, source, readonly); +#endif + if (!image) return -1; @@ -6224,40 +5204,15 @@ index 0000000..ceaec7a + if( source < 0) + return -1; + -+ if (m_format == RENDER_FMT_OMXEGL) ++ if (m_format == RENDER_FMT_MMAL) + { + } + else if (m_format == RENDER_FMT_YUV420P) + { + const int pitch = ALIGN_UP(m_sourceWidth, 32); + const int aligned_height = ALIGN_UP(m_sourceHeight, 16); -+ MMAL_BUFFER_HEADER_T *buffer = NULL; -+ if (!m_vout) -+ { -+ MMAL_ES_FORMAT_T *m_es_format = mmal_format_alloc(); -+ m_es_format->encoding = MMAL_ENCODING_I420; -+ m_es_format->type = MMAL_ES_TYPE_VIDEO; -+ m_es_format->es->video.width = pitch; -+ m_es_format->es->video.height = aligned_height; -+ m_es_format->es->video.crop.width = m_sourceWidth; -+ m_es_format->es->video.crop.height = m_sourceHeight; + -+ if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT709) -+ m_es_format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT709; -+ else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT601) -+ m_es_format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT601; -+ else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_240M) -+ m_es_format->es->video.color_space = MMAL_COLOR_SPACE_SMPTE240M; -+ -+ if (!m_vout && init_vout(m_es_format)) -+ { -+ mmal_format_free(m_es_format); -+ return -1; -+ } -+ mmal_format_free(m_es_format); -+ } -+ -+ buffer = mmal_queue_timedwait(m_vout_input_pool->queue, 500); ++ MMAL_BUFFER_HEADER_T *buffer = mmal_queue_timedwait(m_vout_input_pool->queue, 500); + if (!buffer) + { + CLog::Log(LOGERROR, "%s::%s - mmal_queue_get failed", CLASSNAME, __func__); @@ -6290,49 +5245,48 @@ index 0000000..ceaec7a + YUVBUFFER &buf = m_buffers[source]; + memset(&buf, 0, sizeof buf); + buf.mmal_buffer = buffer; -+ //return -1; + } + else assert(0); + + return source; +} + -+void COMXRenderer::ReleaseBuffer(int idx) ++void CMMALRenderer::ReleaseBuffer(int idx) +{ -+#if defined(OMX_DEBUG_VERBOSE) ++#if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s - %d", CLASSNAME, __func__, idx); +#endif + YUVBUFFER &buf = m_buffers[idx]; -+ SAFE_RELEASE(buf.openMaxBuffer); ++ SAFE_RELEASE(buf.MMALBuffer); +} + -+void COMXRenderer::ReleaseImage(int source, bool preserve) ++void CMMALRenderer::ReleaseImage(int source, bool preserve) +{ -+#if defined(OMX_DEBUG_VERBOSE) ++#if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s - %d %d", CLASSNAME, __func__, source, preserve); +#endif +} + -+void COMXRenderer::Reset() ++void CMMALRenderer::Reset() +{ + CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); +} + -+void COMXRenderer::Flush() ++void CMMALRenderer::Flush() +{ + CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); +} + -+void COMXRenderer::Update() ++void CMMALRenderer::Update() +{ + CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); + if (!m_bConfigured) return; + ManageDisplay(); +} + -+void COMXRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) ++void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) +{ -+#if defined(OMX_DEBUG_VERBOSE) ++#if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s - %d %x %d", CLASSNAME, __func__, clear, flags, alpha); +#endif + @@ -6363,9 +5317,9 @@ index 0000000..ceaec7a + g_graphicsContext.EndPaint(); +} + -+void COMXRenderer::FlipPage(int source) ++void CMMALRenderer::FlipPage(int source) +{ -+#if defined(OMX_DEBUG_VERBOSE) ++#if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s - %d", CLASSNAME, __func__, source); +#endif + @@ -6376,42 +5330,17 @@ index 0000000..ceaec7a + // we only want to upload frames once + if (buffer->flipindex++) + return; -+ if (m_format == RENDER_FMT_OMXEGL) ++ if (m_format == RENDER_FMT_MMAL) + { -+ COpenMaxVideoBuffer *omvb = buffer->openMaxBuffer; ++ CMMALVideoBuffer *omvb = buffer->MMALBuffer; + if (omvb) + { -+#if defined(HAVE_LIBOPENMAX) -+#if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s %p (%p) frame:%d(%d)", CLASSNAME, __func__, omvb, omvb->mmal_buffer, m_changed_count_vout, omvb->m_changed_count); ++#if defined(MMAL_DEBUG_VERBOSE) ++ CLog::Log(LOGDEBUG, "%s::%s %p (%p)", CLASSNAME, __func__, omvb, omvb->mmal_buffer); +#endif -+ -+ -+ MMAL_ES_FORMAT_T *m_es_format = mmal_format_alloc(); -+ m_es_format->encoding = MMAL_ENCODING_OPAQUE; -+ m_es_format->type = MMAL_ES_TYPE_VIDEO; -+ m_es_format->es->video.width = m_sourceWidth; -+ m_es_format->es->video.height = m_sourceHeight; -+ m_es_format->es->video.crop.width = m_sourceWidth; -+ m_es_format->es->video.crop.height = m_sourceHeight; -+ -+ if (!m_vout && init_vout(m_es_format)) -+ { -+ mmal_format_free(m_es_format); -+ return; -+ } -+ mmal_format_free(m_es_format); -+ -+ /*if (m_changed_count_vout != omvb->m_changed_count) -+ { -+ CLog::Log(LOGDEBUG, "%s::%s format changed frame:%d(%d)", CLASSNAME, __func__, m_changed_count_vout, omvb->m_changed_count); -+ change_vout_input_format(omvb->GetFormat()); -+ m_changed_count_vout = omvb->m_changed_count; -+ }*/ + omvb->Acquire(); + mmal_port_send_buffer(m_vout_input, omvb->mmal_buffer); + } else assert(0); -+#endif + } + else if (m_format == RENDER_FMT_YUV420P) + { @@ -6423,14 +5352,12 @@ index 0000000..ceaec7a + else assert(0); +} + -+unsigned int COMXRenderer::PreInit() ++unsigned int CMMALRenderer::PreInit() +{ + CSingleLock lock(g_graphicsContext); + m_bConfigured = false; + UnInit(); + -+ m_changed_count_vout = 0; -+ + m_iFlags = 0; + m_src_rect.SetRect(0, 0, 0, 0); + m_dst_rect.SetRect(0, 0, 0, 0); @@ -6446,23 +5373,21 @@ index 0000000..ceaec7a + + m_formats.clear(); + m_formats.push_back(RENDER_FMT_YUV420P); -+ m_formats.push_back(RENDER_FMT_OMXEGL); ++ m_formats.push_back(RENDER_FMT_MMAL); + m_formats.push_back(RENDER_FMT_BYPASS); + -+ m_NumYV12Buffers = 3; ++ m_NumYV12Buffers = NUM_BUFFERS; + + return 0; +} + -+void COMXRenderer::ReleaseBuffers() ++void CMMALRenderer::ReleaseBuffers() +{ -+#if defined(HAVE_LIBOPENMAX) + for (int i=0; i +#include @@ -6782,24 +5706,25 @@ index 0000000..724342a +#define AUTOSOURCE -1 + +class CBaseTexture; -+class COpenMaxVideoBuffer; ++class CMMALVideoBuffer; + +struct DVDVideoPicture; + -+class COMXRenderer : public CBaseRenderer ++class CMMALRenderer : public CBaseRenderer, public CThread +{ + struct YUVBUFFER + { -+ COpenMaxVideoBuffer *openMaxBuffer; // used for hw decoded buffers ++ CMMALVideoBuffer *MMALBuffer; // used for hw decoded buffers + MMAL_BUFFER_HEADER_T *mmal_buffer; // used for sw decoded buffers + unsigned flipindex; /* used to decide if this has been uploaded */ + }; +public: -+ COMXRenderer(); -+ ~COMXRenderer(); ++ CMMALRenderer(); ++ ~CMMALRenderer(); + + virtual void Update(); + virtual void SetupScreenshot() {}; ++ virtual void Process(); + + bool RenderCapture(CRenderCapture* capture); + @@ -6814,7 +5739,7 @@ index 0000000..724342a + virtual void Reset(); /* resets renderer after seek for example */ + virtual void Flush(); + virtual bool IsConfigured() { return m_bConfigured; } -+ virtual void AddProcessor(COpenMaxVideoBuffer *openMaxVideoBuffer, int index); ++ virtual void AddProcessor(CMMALVideoBuffer *buffer, int index); + virtual std::vector SupportedFormats() { return m_formats; } + + virtual bool Supports(ERENDERFEATURE feature); @@ -6859,10 +5784,8 @@ index 0000000..724342a + MMAL_PORT_T *m_vout_input; + MMAL_POOL_T *m_vout_input_pool; + -+ uint32_t m_changed_count_vout; -+ pthread_t m_worker; + MMAL_QUEUE_T *m_release_queue; -+ bool change_vout_input_format(MMAL_ES_FORMAT_T *m_format); ++ CEvent m_sync; + bool init_vout(MMAL_ES_FORMAT_T *m_format); + void ReleaseBuffers(); +}; @@ -6870,46 +5793,75 @@ index 0000000..724342a +#else +#include "LinuxRenderer.h" +#endif +diff --git a/xbmc/cores/VideoRenderers/Makefile.in b/xbmc/cores/VideoRenderers/Makefile.in +index d964285..7fcc322 100644 +--- a/xbmc/cores/VideoRenderers/Makefile.in ++++ b/xbmc/cores/VideoRenderers/Makefile.in +@@ -20,6 +20,10 @@ SRCS += LinuxRendererGLES.cpp + SRCS += OverlayRendererGL.cpp + endif + ++ifeq (@USE_MMAL@,1) ++SRCS += MMALRenderer.cpp ++endif ++ + LIB = VideoRenderer.a + + include @abs_top_srcdir@/Makefile.include +diff --git a/xbmc/cores/VideoRenderers/RenderFormats.h b/xbmc/cores/VideoRenderers/RenderFormats.h +index 1bdd1d3..6394ef1 100644 +--- a/xbmc/cores/VideoRenderers/RenderFormats.h ++++ b/xbmc/cores/VideoRenderers/RenderFormats.h +@@ -39,6 +39,7 @@ enum ERenderFormat { + RENDER_FMT_EGLIMG, + RENDER_FMT_MEDIACODEC, + RENDER_FMT_IMXMAP, ++ RENDER_FMT_MMAL, + }; + + #endif diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index 568c8b2..f770146 100644 +index 91d7635..e72d791 100644 --- a/xbmc/cores/VideoRenderers/RenderManager.cpp +++ b/xbmc/cores/VideoRenderers/RenderManager.cpp @@ -41,6 +41,8 @@ #if defined(HAS_GL) #include "LinuxRendererGL.h" -+#elif defined(TARGET_RASPBERRY_PI) -+ #include "OMXRenderer.h" ++#elif defined(HAS_MMAL) ++ #include "MMALRenderer.h" #elif HAS_GLES == 2 #include "LinuxRendererGLES.h" #elif defined(HAS_DX) -@@ -424,6 +426,8 @@ unsigned int CXBMCRenderManager::PreInit() +@@ -423,6 +425,8 @@ unsigned int CXBMCRenderManager::PreInit() { #if defined(HAS_GL) m_pRenderer = new CLinuxRendererGL(); -+#elif defined(TARGET_RASPBERRY_PI) -+ m_pRenderer = new COMXRenderer(); ++#elif defined(HAS_MMAL) ++ m_pRenderer = new CMMALRenderer(); #elif HAS_GLES == 2 m_pRenderer = new CLinuxRendererGLES(); #elif defined(HAS_DX) -@@ -921,7 +925,7 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic) +@@ -951,6 +955,10 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic) + else if(pic.format == RENDER_FMT_IMXMAP) + m_pRenderer->AddProcessor(pic.IMXBuffer, index); #endif - #ifdef HAVE_LIBOPENMAX - else if(pic.format == RENDER_FMT_OMXEGL) -- m_pRenderer->AddProcessor(pic.openMax, &pic, index); -+ m_pRenderer->AddProcessor(pic.openMaxBuffer, index); - #endif - #ifdef TARGET_DARWIN - else if(pic.format == RENDER_FMT_CVBREF) ++#ifdef HAS_MMAL ++ else if(pic.format == RENDER_FMT_MMAL) ++ m_pRenderer->AddProcessor(pic.MMALBuffer, index); ++#endif + + m_pRenderer->ReleaseImage(index, false); + diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h -index e8d4ca2..1b54c79 100644 +index 850890f..d3c2f1d 100644 --- a/xbmc/cores/VideoRenderers/RenderManager.h +++ b/xbmc/cores/VideoRenderers/RenderManager.h @@ -42,6 +42,7 @@ struct DVDVideoPicture; #define ERRORBUFFSIZE 30 class CWinRenderer; -+class COMXRenderer; ++class CMMALRenderer; class CLinuxRenderer; class CLinuxRendererGL; class CLinuxRendererGLES; @@ -6917,556 +5869,289 @@ index e8d4ca2..1b54c79 100644 #ifdef HAS_GL CLinuxRendererGL *m_pRenderer; -+#elif defined(TARGET_RASPBERRY_PI) -+ COMXRenderer *m_pRenderer; ++#elif defined(HAS_MMAL) ++ CMMALRenderer *m_pRenderer; #elif HAS_GLES == 2 CLinuxRendererGLES *m_pRenderer; #elif defined(HAS_DX) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp -index f8a5635..3a11154 100644 +index f8a5635..6ef941f 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp -@@ -191,6 +191,10 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne +@@ -39,6 +39,7 @@ + #if defined(HAS_IMXVPU) + #include "Video/DVDVideoCodecIMX.h" + #endif ++#include "Video/DVDVideoCodecMMAL.h" + #include "Video/DVDVideoCodecStageFright.h" + #if defined(HAS_LIBAMCODEC) + #include "utils/AMLUtils.h" +@@ -259,6 +260,19 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne + } #endif - CLog::Log(LOGDEBUG, "CDVDFactoryCodec: compiled in hardware support: %s", hwSupport.c_str()); -+#if defined(HAVE_LIBOPENMAX) -+ // libopenmax can handle dvd playback including stills -+ if (!CSettings::Get().GetBool("videoplayer.useomx")) -+#endif - if (hint.stills && (hint.codec == AV_CODEC_ID_MPEG2VIDEO || hint.codec == AV_CODEC_ID_MPEG1VIDEO)) - { - // If dvd is an mpeg2 and hint.stills -@@ -252,7 +256,10 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne - #if defined(HAVE_LIBOPENMAX) - if (CSettings::Get().GetBool("videoplayer.useomx") && !hint.software ) - { -- if (hint.codec == AV_CODEC_ID_H264 || hint.codec == AV_CODEC_ID_MPEG2VIDEO || hint.codec == AV_CODEC_ID_VC1) ++#if defined(HAS_MMAL) ++ if (CSettings::Get().GetBool("videoplayer.usemmal") && !hint.software ) ++ { + if (hint.codec == AV_CODEC_ID_H264 || hint.codec == AV_CODEC_ID_H263 || hint.codec == AV_CODEC_ID_MPEG4 || + hint.codec == AV_CODEC_ID_MPEG1VIDEO || hint.codec == AV_CODEC_ID_MPEG2VIDEO || + hint.codec == AV_CODEC_ID_VP6 || hint.codec == AV_CODEC_ID_VP6F || hint.codec == AV_CODEC_ID_VP6A || hint.codec == AV_CODEC_ID_VP8 || + hint.codec == AV_CODEC_ID_THEORA || hint.codec == AV_CODEC_ID_MJPEG || hint.codec == AV_CODEC_ID_MJPEGB || hint.codec == AV_CODEC_ID_VC1 || hint.codec == AV_CODEC_ID_WMV3) - { - if ( (pCodec = OpenCodec(new CDVDVideoCodecOpenMax(), hint, options)) ) return pCodec; - } ++ { ++ if ( (pCodec = OpenCodec(new CDVDVideoCodecMMAL(), hint, options)) ) return pCodec; ++ } ++ } ++#endif ++ + #if defined(HAS_LIBSTAGEFRIGHT) + if (!hint.software && CSettings::Get().GetBool("videoplayer.usestagefright")) + { diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -index b236ad7..10b38d4 100644 +index c4152f9..51364ab 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -@@ -50,9 +50,7 @@ struct DVDCodecAvailableType - namespace DXVA { class CSurfaceContext; } - namespace VAAPI { class CVaapiRenderPicture; } - namespace VDPAU { class CVdpauRenderPicture; } --class COpenMax; --class COpenMaxVideo; --struct OpenMaxVideoBuffer; -+class COpenMaxVideoBuffer; +@@ -56,6 +56,7 @@ struct OpenMaxVideoBuffer; class CDVDVideoCodecStageFright; class CDVDMediaCodecInfo; class CDVDVideoCodecIMXBuffer; -@@ -82,8 +80,7 @@ struct DVDVideoPicture ++class CMMALVideoBuffer; + typedef void* EGLImageKHR; + + +@@ -103,6 +104,10 @@ struct DVDVideoPicture + CDVDVideoCodecIMXBuffer *IMXBuffer; }; - struct { -- COpenMax *openMax; -- OpenMaxVideoBuffer *openMaxBuffer; -+ COpenMaxVideoBuffer *openMaxBuffer; - }; ++ struct { ++ CMMALVideoBuffer *MMALBuffer; ++ }; ++ + }; - struct { -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp -index b2e7816..8323497 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp -@@ -28,114 +28,37 @@ - #include "DVDClock.h" - #include "DVDStreamInfo.h" - #include "DVDVideoCodecOpenMax.h" --#include "OpenMaxVideo.h" + unsigned int iFlags; +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp +new file mode 100644 +index 0000000..55b9969 +--- /dev/null ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp +@@ -0,0 +1,99 @@ ++/* ++ * Copyright (C) 2010-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS) ++ #include "config.h" ++#elif defined(TARGET_WINDOWS) ++#include "system.h" ++#endif ++ ++#if defined(HAS_MMAL) ++#include "DVDClock.h" ++#include "DVDStreamInfo.h" ++#include "DVDVideoCodecMMAL.h" +#include "settings/Settings.h" - #include "utils/log.h" - --#define CLASSNAME "COpenMax" -+#define CLASSNAME "CDVDVideoCodecOpenMax" - //////////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////////////////// --CDVDVideoCodecOpenMax::CDVDVideoCodecOpenMax() : CDVDVideoCodec() -+CDVDVideoCodecOpenMax::CDVDVideoCodecOpenMax() -+ : m_omx_decoder( new COpenMaxVideo ) - { -- m_omx_decoder = NULL; -- m_pFormatName = "omx-xxxx"; -- -- m_convert_bitstream = false; -- memset(&m_videobuffer, 0, sizeof(DVDVideoPicture)); -+ CLog::Log(LOGDEBUG, "%s::%s %p\n", CLASSNAME, __func__, this); - } - - CDVDVideoCodecOpenMax::~CDVDVideoCodecOpenMax() - { -+ CLog::Log(LOGDEBUG, "%s::%s %p\n", CLASSNAME, __func__, this); - Dispose(); - } - - bool CDVDVideoCodecOpenMax::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) - { -- // we always qualify even if DVDFactoryCodec does this too. -- if (CSettings::Get().GetBool("videoplayer.useomx") && !hints.software) -- { -- m_convert_bitstream = false; -- -- switch (hints.codec) -- { -- case AV_CODEC_ID_H264: -- { -- m_pFormatName = "omx-h264"; -- if (hints.extrasize < 7 || hints.extradata == NULL) -- { -- CLog::Log(LOGNOTICE, -- "%s::%s - avcC data too small or missing", CLASSNAME, __func__); -- return false; -- } -- // valid avcC data (bitstream) always starts with the value 1 (version) -- if ( *(char*)hints.extradata == 1 ) -- m_convert_bitstream = bitstream_convert_init(hints.extradata, hints.extrasize); -- } -- break; -- case AV_CODEC_ID_MPEG4: -- m_pFormatName = "omx-mpeg4"; -- break; -- case AV_CODEC_ID_MPEG2VIDEO: -- m_pFormatName = "omx-mpeg2"; -- break; -- case AV_CODEC_ID_VC1: -- m_pFormatName = "omx-vc1"; -- break; -- default: -- return false; -- break; -- } -- -- m_omx_decoder = new COpenMaxVideo; -- if (!m_omx_decoder->Open(hints)) -- { -- CLog::Log(LOGERROR, -- "%s::%s - failed to open, codec(%d), profile(%d), level(%d)", -- CLASSNAME, __func__, hints.codec, hints.profile, hints.level); -- return false; -- } -- -- // allocate a YV12 DVDVideoPicture buffer. -- // first make sure all properties are reset. -- memset(&m_videobuffer, 0, sizeof(DVDVideoPicture)); -- -- m_videobuffer.dts = DVD_NOPTS_VALUE; -- m_videobuffer.pts = DVD_NOPTS_VALUE; -- //m_videobuffer.format = RENDER_FMT_YUV420P; -- m_videobuffer.format = RENDER_FMT_OMXEGL; -- m_videobuffer.color_range = 0; -- m_videobuffer.color_matrix = 4; -- m_videobuffer.iFlags = DVP_FLAG_ALLOCATED; -- m_videobuffer.iWidth = hints.width; -- m_videobuffer.iHeight = hints.height; -- m_videobuffer.iDisplayWidth = hints.width; -- m_videobuffer.iDisplayHeight = hints.height; -- -- return true; -- } -+ return m_omx_decoder->Open(hints, options, m_omx_decoder); -+} - -- return false; -+const char* CDVDVideoCodecOpenMax::GetName(void) ++#include "utils/log.h" ++ ++#define CLASSNAME "CDVDVideoCodecMMAL" ++//////////////////////////////////////////////////////////////////////////////////////////// ++//////////////////////////////////////////////////////////////////////////////////////////// ++CDVDVideoCodecMMAL::CDVDVideoCodecMMAL() ++ : m_decoder( new CMMALVideo ) +{ -+ return m_omx_decoder ? m_omx_decoder->GetName() : "omx-xxx"; - } - - void CDVDVideoCodecOpenMax::Dispose() - { -- if (m_omx_decoder) -- { -- m_omx_decoder->Close(); -- delete m_omx_decoder; -- m_omx_decoder = NULL; -- } -- if (m_videobuffer.iFlags & DVP_FLAG_ALLOCATED) -- { -- m_videobuffer.iFlags = 0; -- } -- if (m_convert_bitstream) -- { -- if (m_sps_pps_context.sps_pps_data) -- { -- free(m_sps_pps_context.sps_pps_data); -- m_sps_pps_context.sps_pps_data = NULL; -- } -- } -+ m_omx_decoder->Dispose(); - } - - void CDVDVideoCodecOpenMax::SetDropState(bool bDrop) -@@ -145,37 +68,12 @@ void CDVDVideoCodecOpenMax::SetDropState(bool bDrop) - - int CDVDVideoCodecOpenMax::Decode(uint8_t* pData, int iSize, double dts, double pts) - { -- if (pData) -- { -- int rtn; -- int demuxer_bytes = iSize; -- uint8_t *demuxer_content = pData; -- bool bitstream_convered = false; -- -- if (m_convert_bitstream) -- { -- // convert demuxer packet from bitstream to bytestream (AnnexB) -- int bytestream_size = 0; -- uint8_t *bytestream_buff = NULL; -- -- bitstream_convert(demuxer_content, demuxer_bytes, &bytestream_buff, &bytestream_size); -- if (bytestream_buff && (bytestream_size > 0)) -- { -- bitstream_convered = true; -- demuxer_bytes = bytestream_size; -- demuxer_content = bytestream_buff; -- } -- } -- -- rtn = m_omx_decoder->Decode(demuxer_content, demuxer_bytes, dts, pts); -- -- if (bitstream_convered) -- free(demuxer_content); -+ return m_omx_decoder->Decode(pData, iSize, dts, pts); ++ CLog::Log(LOGDEBUG, "%s::%s %p\n", CLASSNAME, __func__, this); +} - -- return rtn; -- } -- -- return VC_BUFFER; -+unsigned CDVDVideoCodecOpenMax::GetAllowedReferences() ++ ++CDVDVideoCodecMMAL::~CDVDVideoCodecMMAL() +{ -+ return m_omx_decoder->GetAllowedReferences(); - } - - void CDVDVideoCodecOpenMax::Reset(void) -@@ -185,172 +83,17 @@ void CDVDVideoCodecOpenMax::Reset(void) - - bool CDVDVideoCodecOpenMax::GetPicture(DVDVideoPicture* pDvdVideoPicture) - { -- m_omx_decoder->GetPicture(&m_videobuffer); -- *pDvdVideoPicture = m_videobuffer; -- -- return VC_PICTURE | VC_BUFFER; --} -- --//////////////////////////////////////////////////////////////////////////////////////////// --bool CDVDVideoCodecOpenMax::bitstream_convert_init(void *in_extradata, int in_extrasize) --{ -- // based on h264_mp4toannexb_bsf.c (ffmpeg) -- // which is Copyright (c) 2007 Benoit Fouet -- // and Licensed GPL 2.1 or greater -- -- m_sps_pps_size = 0; -- m_sps_pps_context.sps_pps_data = NULL; -- -- // nothing to filter -- if (!in_extradata || in_extrasize < 6) -- return false; -- -- uint16_t unit_size; -- uint32_t total_size = 0; -- uint8_t *out = NULL, unit_nb, sps_done = 0; -- const uint8_t *extradata = (uint8_t*)in_extradata + 4; -- static const uint8_t nalu_header[4] = {0, 0, 0, 1}; -- -- // retrieve length coded size -- m_sps_pps_context.length_size = (*extradata++ & 0x3) + 1; -- if (m_sps_pps_context.length_size == 3) -- return false; -- -- // retrieve sps and pps unit(s) -- unit_nb = *extradata++ & 0x1f; // number of sps unit(s) -- if (!unit_nb) -- { -- unit_nb = *extradata++; // number of pps unit(s) -- sps_done++; -- } -- while (unit_nb--) -- { -- unit_size = extradata[0] << 8 | extradata[1]; -- total_size += unit_size + 4; -- if ( (extradata + 2 + unit_size) > ((uint8_t*)in_extradata + in_extrasize) ) -- { -- free(out); -- return false; -- } -- uint8_t* new_out = (uint8_t*)realloc(out, total_size); -- if (new_out) -- { -- out = new_out; -- } -- else -- { -- CLog::Log(LOGERROR, "bitstream_convert_init failed - %s : could not realloc the buffer out", __FUNCTION__); -- free(out); -- return false; -- } -- -- memcpy(out + total_size - unit_size - 4, nalu_header, 4); -- memcpy(out + total_size - unit_size, extradata + 2, unit_size); -- extradata += 2 + unit_size; -- -- if (!unit_nb && !sps_done++) -- unit_nb = *extradata++; // number of pps unit(s) -- } -- -- m_sps_pps_context.sps_pps_data = out; -- m_sps_pps_context.size = total_size; -- m_sps_pps_context.first_idr = 1; -- -- return true; -+ return m_omx_decoder->GetPicture(pDvdVideoPicture); - } - --bool CDVDVideoCodecOpenMax::bitstream_convert(uint8_t* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size) -+bool CDVDVideoCodecOpenMax::ClearPicture(DVDVideoPicture* pDvdVideoPicture) - { -- // based on h264_mp4toannexb_bsf.c (ffmpeg) -- // which is Copyright (c) 2007 Benoit Fouet -- // and Licensed GPL 2.1 or greater -- -- uint8_t *buf = pData; -- uint32_t buf_size = iSize; -- uint8_t unit_type; -- int32_t nal_size; -- uint32_t cumul_size = 0; -- const uint8_t *buf_end = buf + buf_size; -- -- do -- { -- if (buf + m_sps_pps_context.length_size > buf_end) -- goto fail; -- -- if (m_sps_pps_context.length_size == 1) -- nal_size = buf[0]; -- else if (m_sps_pps_context.length_size == 2) -- nal_size = buf[0] << 8 | buf[1]; -- else -- nal_size = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; -- -- buf += m_sps_pps_context.length_size; -- unit_type = *buf & 0x1f; -- -- if (buf + nal_size > buf_end || nal_size < 0) -- goto fail; -- -- // prepend only to the first type 5 NAL unit of an IDR picture -- if (m_sps_pps_context.first_idr && unit_type == 5) -- { -- bitstream_alloc_and_copy(poutbuf, poutbuf_size, -- m_sps_pps_context.sps_pps_data, m_sps_pps_context.size, buf, nal_size); -- m_sps_pps_context.first_idr = 0; -- } -- else -- { -- bitstream_alloc_and_copy(poutbuf, poutbuf_size, NULL, 0, buf, nal_size); -- if (!m_sps_pps_context.first_idr && unit_type == 1) -- m_sps_pps_context.first_idr = 1; -- } -- -- buf += nal_size; -- cumul_size += nal_size + m_sps_pps_context.length_size; -- } while (cumul_size < buf_size); -- -- return true; -- --fail: -- free(*poutbuf); -- *poutbuf = NULL; -- *poutbuf_size = 0; -- return false; -+ return m_omx_decoder->ClearPicture(pDvdVideoPicture); - } - --void CDVDVideoCodecOpenMax::bitstream_alloc_and_copy( -- uint8_t **poutbuf, int *poutbuf_size, -- const uint8_t *sps_pps, uint32_t sps_pps_size, -- const uint8_t *in, uint32_t in_size) -+bool CDVDVideoCodecOpenMax::GetCodecStats(double &pts, int &droppedPics) - { -- // based on h264_mp4toannexb_bsf.c (ffmpeg) -- // which is Copyright (c) 2007 Benoit Fouet -- // and Licensed GPL 2.1 or greater -- -- #define CHD_WB32(p, d) { \ -- ((uint8_t*)(p))[3] = (d); \ -- ((uint8_t*)(p))[2] = (d) >> 8; \ -- ((uint8_t*)(p))[1] = (d) >> 16; \ -- ((uint8_t*)(p))[0] = (d) >> 24; } -- -- uint32_t offset = *poutbuf_size; -- uint8_t nal_header_size = offset ? 3 : 4; -- -- *poutbuf_size += sps_pps_size + in_size + nal_header_size; -- *poutbuf = (uint8_t*)realloc(*poutbuf, *poutbuf_size); -- if (sps_pps) -- memcpy(*poutbuf + offset, sps_pps, sps_pps_size); -- -- memcpy(*poutbuf + sps_pps_size + nal_header_size + offset, in, in_size); -- if (!offset) -- { -- CHD_WB32(*poutbuf + sps_pps_size, 1); -- } -- else -- { -- (*poutbuf + offset + sps_pps_size)[0] = 0; -- (*poutbuf + offset + sps_pps_size)[1] = 0; -- (*poutbuf + offset + sps_pps_size)[2] = 1; -- } -+ return m_omx_decoder->GetCodecStats(pts, droppedPics); - } - - #endif -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h -index fb80d02..4f243df 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h -@@ -22,8 +22,9 @@ - #if defined(HAVE_LIBOPENMAX) - - #include "DVDVideoCodec.h" -+#include "OpenMaxVideo.h" - --class COpenVideoMax; -+class COpenMaxVideo; - class CDVDVideoCodecOpenMax : public CDVDVideoCodec - { - public: -@@ -36,39 +37,14 @@ class CDVDVideoCodecOpenMax : public CDVDVideoCodec - virtual int Decode(uint8_t *pData, int iSize, double dts, double pts); - virtual void Reset(void); - virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture); ++ CLog::Log(LOGDEBUG, "%s::%s %p\n", CLASSNAME, __func__, this); ++ Dispose(); ++} ++ ++bool CDVDVideoCodecMMAL::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) ++{ ++ return m_decoder->Open(hints, options, m_decoder); ++} ++ ++const char* CDVDVideoCodecMMAL::GetName(void) ++{ ++ return m_decoder ? m_decoder->GetName() : "mmal-xxx"; ++} ++ ++void CDVDVideoCodecMMAL::Dispose() ++{ ++ m_decoder->Dispose(); ++} ++ ++void CDVDVideoCodecMMAL::SetDropState(bool bDrop) ++{ ++ m_decoder->SetDropState(bDrop); ++} ++ ++int CDVDVideoCodecMMAL::Decode(uint8_t* pData, int iSize, double dts, double pts) ++{ ++ return m_decoder->Decode(pData, iSize, dts, pts); ++} ++ ++unsigned CDVDVideoCodecMMAL::GetAllowedReferences() ++{ ++ return m_decoder->GetAllowedReferences(); ++} ++ ++void CDVDVideoCodecMMAL::Reset(void) ++{ ++ m_decoder->Reset(); ++} ++ ++bool CDVDVideoCodecMMAL::GetPicture(DVDVideoPicture* pDvdVideoPicture) ++{ ++ return m_decoder->GetPicture(pDvdVideoPicture); ++} ++ ++bool CDVDVideoCodecMMAL::ClearPicture(DVDVideoPicture* pDvdVideoPicture) ++{ ++ return m_decoder->ClearPicture(pDvdVideoPicture); ++} ++ ++bool CDVDVideoCodecMMAL::GetCodecStats(double &pts, int &droppedPics) ++{ ++ return m_decoder->GetCodecStats(pts, droppedPics); ++} ++ ++#endif +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h +new file mode 100644 +index 0000000..67aa505 +--- /dev/null ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h +@@ -0,0 +1,50 @@ ++#pragma once ++/* ++ * Copyright (C) 2010-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#if defined(HAS_MMAL) ++ ++#include "DVDVideoCodec.h" ++#include "MMALCodec.h" ++ ++class CMMALVideo; ++class CDVDVideoCodecMMAL : public CDVDVideoCodec ++{ ++public: ++ CDVDVideoCodecMMAL(); ++ virtual ~CDVDVideoCodecMMAL(); ++ ++ // Required overrides ++ virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options); ++ virtual void Dispose(void); ++ virtual int Decode(uint8_t *pData, int iSize, double dts, double pts); ++ virtual void Reset(void); ++ virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture); + virtual bool ClearPicture(DVDVideoPicture* pDvdVideoPicture); + virtual unsigned GetAllowedReferences(); - virtual void SetDropState(bool bDrop); -- virtual const char* GetName(void) { return (const char*)m_pFormatName; } ++ virtual void SetDropState(bool bDrop); + virtual const char* GetName(void); + virtual bool GetCodecStats(double &pts, int &droppedPics); - - protected: -- const char *m_pFormatName; -- COpenMaxVideo *m_omx_decoder; -- DVDVideoPicture m_videobuffer; -- -- // bitstream to bytestream (Annex B) conversion support. -- bool bitstream_convert_init(void *in_extradata, int in_extrasize); -- bool bitstream_convert(uint8_t* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size); -- static void bitstream_alloc_and_copy( uint8_t **poutbuf, int *poutbuf_size, -- const uint8_t *sps_pps, uint32_t sps_pps_size, const uint8_t *in, uint32_t in_size); -- -- typedef struct omx_bitstream_ctx { -- uint8_t length_size; -- uint8_t first_idr; -- uint8_t *sps_pps_data; -- uint32_t size; -- -- omx_bitstream_ctx() -- { -- length_size = 0; -- first_idr = 0; -- sps_pps_data = NULL; -- size = 0; -- } -- -- } omx_bitstream_ctx; -- -- uint32_t m_sps_pps_size; -- omx_bitstream_ctx m_sps_pps_context; -- bool m_convert_bitstream; -+ OpenMaxVideoPtr m_omx_decoder; - }; - - #endif -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -index 50dc8b7..b4ae0bb 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -@@ -16,7 +16,6 @@ SRCS += DVDVideoCodecVDA.cpp - SRCS += VDA.cpp - endif - ifeq (@USE_OPENMAX@,1) --SRCS += OpenMax.cpp - SRCS += OpenMaxVideo.cpp - SRCS += DVDVideoCodecOpenMax.cpp - endif -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -index dcbdb1e..3218b63 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -@@ -32,1019 +32,1068 @@ - #include "DVDVideoCodec.h" - #include "utils/log.h" - #include "utils/TimeUtils.h" ++ ++protected: ++ MMALVideoPtr m_decoder; ++}; ++ ++#endif +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +new file mode 100644 +index 0000000..00f174a +--- /dev/null ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -0,0 +1,1084 @@ ++/* ++ * Copyright (C) 2010-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS) ++ #include "config.h" ++#elif defined(TARGET_WINDOWS) ++#include "system.h" ++#endif ++ ++#include "MMALCodec.h" ++ ++#include "DVDClock.h" ++#include "DVDStreamInfo.h" ++#include "windowing/WindowingFactory.h" ++#include "DVDVideoCodec.h" ++#include "utils/log.h" ++#include "utils/TimeUtils.h" +#include "settings/Settings.h" +#include "settings/MediaSettings.h" - #include "ApplicationMessenger.h" - #include "Application.h" ++#include "ApplicationMessenger.h" ++#include "Application.h" +#include "threads/Atomics.h" +#include "guilib/GUIWindowManager.h" +#include "cores/VideoRenderers/RenderFlags.h" +#include "settings/DisplaySettings.h" +#include "cores/VideoRenderers/RenderManager.h" - --#include --#include --#include --#include ++ +#include "linux/RBP.h" - -+#define DTS_QUEUE - --#define CLASSNAME "COpenMaxVideo" ++ +#ifdef _DEBUG -+#define OMX_DEBUG_VERBOSE ++#define MMAL_DEBUG_VERBOSE +#endif - --// TODO: These are Nvidia Tegra2 dependent, need to dynamiclly find the --// right codec matched to video format. --#define OMX_H264BASE_DECODER "OMX.Nvidia.h264.decode" --// OMX.Nvidia.h264ext.decode segfaults, not sure why. --//#define OMX_H264MAIN_DECODER "OMX.Nvidia.h264ext.decode" --#define OMX_H264MAIN_DECODER "OMX.Nvidia.h264.decode" --#define OMX_H264HIGH_DECODER "OMX.Nvidia.h264ext.decode" --#define OMX_MPEG4_DECODER "OMX.Nvidia.mp4.decode" --#define OMX_MPEG4EXT_DECODER "OMX.Nvidia.mp4ext.decode" --#define OMX_MPEG2V_DECODER "OMX.Nvidia.mpeg2v.decode" --#define OMX_VC1_DECODER "OMX.Nvidia.vc1.decode" -- --// EGL extension functions --static PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; --static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; --#define GETEXTENSION(type, ext) \ --do \ --{ \ -- ext = (type) eglGetProcAddress(#ext); \ -- if (!ext) \ -- { \ -- CLog::Log(LOGERROR, "%s::%s - ERROR getting proc addr of " #ext "\n", CLASSNAME, __func__); \ -- } \ --} while (0); -- --#define OMX_INIT_STRUCTURE(a) \ -- memset(&(a), 0, sizeof(a)); \ -- (a).nSize = sizeof(a); \ -- (a).nVersion.s.nVersionMajor = OMX_VERSION_MAJOR; \ -- (a).nVersion.s.nVersionMinor = OMX_VERSION_MINOR; \ -- (a).nVersion.s.nRevision = OMX_VERSION_REVISION; \ -- (a).nVersion.s.nStep = OMX_VERSION_STEP -+#define CLASSNAME "COpenMaxVideoBuffer" - -+COpenMaxVideoBuffer::COpenMaxVideoBuffer(COpenMaxVideo *omv) ++ ++#define CLASSNAME "CMMALVideoBuffer" ++ ++CMMALVideoBuffer::CMMALVideoBuffer(CMMALVideo *omv) + : m_omv(omv), m_refs(0) +{ -+#if defined(OMX_DEBUG_VERBOSE) ++#if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this); +#endif + mmal_buffer = NULL; @@ -7477,67 +6162,56 @@ index dcbdb1e..3218b63 100644 + m_changed_count = 0; + dts = DVD_NOPTS_VALUE; +} - --COpenMaxVideo::COpenMaxVideo() -+COpenMaxVideoBuffer::~COpenMaxVideoBuffer() ++ ++CMMALVideoBuffer::~CMMALVideoBuffer() +{ -+#if defined(OMX_DEBUG_VERBOSE) ++#if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this); +#endif +} + + -+COpenMaxVideoBuffer* COpenMaxVideoBuffer::Acquire() - { -- m_portChanging = false; ++CMMALVideoBuffer* CMMALVideoBuffer::Acquire() ++{ + long count = AtomicIncrement(&m_refs); -+ #if defined(OMX_DEBUG_VERBOSE) ++ #if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s %p (%p) ref:%ld", CLASSNAME, __func__, this, mmal_buffer, count); + #endif + (void)count; + return this; +} - -- pthread_mutex_init(&m_omx_input_mutex, NULL); -+long COpenMaxVideoBuffer::Release() ++ ++long CMMALVideoBuffer::Release() +{ + long count = AtomicDecrement(&m_refs); -+#if defined(OMX_DEBUG_VERBOSE) ++#if defined(MMAL_DEBUG_VERBOSE) +CLog::Log(LOGDEBUG, "%s::%s %p (%p) ref:%ld", CLASSNAME, __func__, this, mmal_buffer, count); +#endif + if (count == 0) + { -+ m_omv->ReleaseOpenMaxBuffer(this); ++ m_omv->ReleaseBuffer(this); + } + return count; +} + +#undef CLASSNAME -+#define CLASSNAME "COpenMaxVideo" ++#define CLASSNAME "CMMALVideo" + -+COpenMaxVideo::COpenMaxVideo() ++CMMALVideo::CMMALVideo() +{ -+ #if defined(OMX_DEBUG_VERBOSE) ++ #if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this); + #endif - pthread_mutex_init(&m_omx_output_mutex, NULL); - -- m_omx_decoder_state_change = (sem_t*)malloc(sizeof(sem_t)); -- sem_init(m_omx_decoder_state_change, 0, 0); -- memset(&m_videobuffer, 0, sizeof(DVDVideoPicture)); - m_drop_state = false; - m_decoded_width = 0; - m_decoded_height = 0; -- m_omx_input_eos = false; -- m_omx_input_port = 0; -- m_omx_output_eos = false; -- m_omx_output_port = 0; -- m_videoplayback_done = false; ++ pthread_mutex_init(&m_output_mutex, NULL); ++ ++ m_drop_state = false; ++ m_decoded_width = 0; ++ m_decoded_height = 0; + + m_finished = false; + m_pFormatName = "mmal-xxxx"; + -+ //m_interlace_mode = MMAL_InterlaceProgressive; ++ m_interlace_mode = MMAL_InterlaceProgressive; + m_startframe = false; + m_decoderPts = DVD_NOPTS_VALUE; + m_droppedPics = 0; @@ -7556,365 +6230,151 @@ index dcbdb1e..3218b63 100644 + + m_changed_count = 0; + m_changed_count_dec = 0; -+ m_omx_output_busy = 0; ++ m_output_busy = 0; + m_es_format = mmal_format_alloc(); - } - - COpenMaxVideo::~COpenMaxVideo() - { - #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__); ++} ++ ++CMMALVideo::~CMMALVideo() ++{ ++ #if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this); - #endif -- if (m_is_open) -- Close(); -- pthread_mutex_destroy(&m_omx_input_mutex); ++ #endif + assert(m_finished); + Reset(); + - pthread_mutex_destroy(&m_omx_output_mutex); -- sem_destroy(m_omx_decoder_state_change); -- free(m_omx_decoder_state_change); --} - --bool COpenMaxVideo::Open(CDVDStreamInfo &hints) --{ -- #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__); -- #endif ++ pthread_mutex_destroy(&m_output_mutex); ++ + if (m_deint && m_deint->control && m_deint->control->is_enabled) + mmal_port_disable(m_deint->control); - -- OMX_ERRORTYPE omx_err = OMX_ErrorNone; -- std::string decoder_name; ++ + if (m_dec && m_dec->control && m_dec->control->is_enabled) + mmal_port_disable(m_dec->control); - -- m_decoded_width = hints.width; -- m_decoded_height = hints.height; ++ + if (m_dec_input && m_dec_input->is_enabled) + mmal_port_disable(m_dec_input); + m_dec_input = NULL; - -- switch (hints.codec) -- { -- case AV_CODEC_ID_H264: -- { -- switch(hints.profile) -- { -- case FF_PROFILE_H264_BASELINE: -- // (role name) video_decoder.avc -- // H.264 Baseline profile -- decoder_name = OMX_H264BASE_DECODER; -- break; -- case FF_PROFILE_H264_MAIN: -- // (role name) video_decoder.avc -- // H.264 Main profile -- decoder_name = OMX_H264MAIN_DECODER; -- break; -- case FF_PROFILE_H264_HIGH: -- // (role name) video_decoder.avc -- // H.264 Main profile -- decoder_name = OMX_H264HIGH_DECODER; -- break; -- default: -- return false; -- break; -- } -- } -- break; -- case AV_CODEC_ID_MPEG4: -- // (role name) video_decoder.mpeg4 -- // MPEG-4, DivX 4/5 and Xvid compatible -- decoder_name = OMX_MPEG4_DECODER; -- break; -- /* -- TODO: what mpeg4 formats are "ext" ???? -- case NvxStreamType_MPEG4Ext: -- // (role name) video_decoder.mpeg4 -- // MPEG-4, DivX 4/5 and Xvid compatible -- decoder_name = OMX_MPEG4EXT_DECODER; -- m_pFormatName = "omx-mpeg4"; -- break; -- */ -- case AV_CODEC_ID_MPEG2VIDEO: -- // (role name) video_decoder.mpeg2 -- // MPEG-2 -- decoder_name = OMX_MPEG2V_DECODER; -- break; -- case AV_CODEC_ID_VC1: -- // (role name) video_decoder.vc1 -- // VC-1, WMV9 -- decoder_name = OMX_VC1_DECODER; -- break; -- default: -- return false; -- break; -- } ++ + if (m_dec_output && m_dec_output->is_enabled) + mmal_port_disable(m_dec_output); + m_dec_output = NULL; - -- // initialize OpenMAX. -- if (!Initialize(decoder_name)) -- { -- return false; -- } ++ + if (m_deint_connection) + mmal_connection_destroy(m_deint_connection); + m_deint_connection = NULL; - -- // TODO: Find component from role name. -- // Get the port information. This will obtain information about the -- // number of ports and index of the first port. -- OMX_PORT_PARAM_TYPE port_param; -- OMX_INIT_STRUCTURE(port_param); -- omx_err = OMX_GetParameter(m_omx_decoder, OMX_IndexParamVideoInit, &port_param); -- if (omx_err) -- { -- Deinitialize(); -- return false; -- } -- m_omx_input_port = port_param.nStartPortNumber; -- m_omx_output_port = m_omx_input_port + 1; -- #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, -- "%s::%s - decoder_component(0x%p), input_port(0x%x), output_port(0x%x)\n", -- CLASSNAME, __func__, m_omx_decoder, m_omx_input_port, m_omx_output_port); -- #endif ++ + if (m_deint && m_deint->is_enabled) + mmal_component_disable(m_deint); - -- // TODO: Set role for the component because components could have multiple roles. -- //QueryCodec(); ++ + if (m_dec && m_dec->is_enabled) + mmal_component_disable(m_dec); - -- // Component will be in OMX_StateLoaded now so we can alloc omx input/output buffers. -- // we can only alloc them in OMX_StateLoaded state or if the component port is disabled -- // Alloc buffers for the omx input port. -- omx_err = AllocOMXInputBuffers(); -- if (omx_err) -- { -- Deinitialize(); -- return false; -- } -- // Alloc buffers for the omx output port. -- m_egl_display = g_Windowing.GetEGLDisplay(); -- m_egl_context = g_Windowing.GetEGLContext(); -- omx_err = AllocOMXOutputBuffers(); -- if (omx_err) -- { -- FreeOMXInputBuffers(false); -- Deinitialize(); -- return false; -- } ++ + if (m_dec_input_pool) + mmal_pool_destroy(m_dec_input_pool); + m_dec_input_pool = NULL; - -- m_is_open = true; -- m_drop_state = false; -- m_videoplayback_done = false; ++ + if (m_dec_output_pool) + mmal_pool_destroy(m_dec_output_pool); + m_dec_output_pool = NULL; - -- // crank it up. -- StartDecoder(); ++ + if (m_deint) + mmal_component_destroy(m_deint); + m_deint = NULL; - -- return true; ++ + if (m_dec) + mmal_component_destroy(m_dec); + m_dec = NULL; + mmal_format_free(m_es_format); + m_es_format = NULL; - } - --void COpenMaxVideo::Close() -+void COpenMaxVideo::PortSettingsChanged(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) - { -- #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__); -- #endif -- if (m_omx_decoder) ++} ++ ++void CMMALVideo::PortSettingsChanged(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) ++{ + MMAL_EVENT_FORMAT_CHANGED_T *fmt = mmal_event_format_changed_get(buffer); + mmal_format_copy(m_es_format, fmt->format); + m_changed_count++; + + if (m_es_format->es->video.crop.width && m_es_format->es->video.crop.height) - { -- if (m_omx_decoder_state != OMX_StateLoaded) -- StopDecoder(); -- Deinitialize(); ++ { + if (m_es_format->es->video.par.num && m_es_format->es->video.par.den) + m_aspect_ratio = (float)(m_es_format->es->video.par.num * m_es_format->es->video.crop.width) / (m_es_format->es->video.par.den * m_es_format->es->video.crop.height); + m_decoded_width = m_es_format->es->video.crop.width; + m_decoded_height = m_es_format->es->video.crop.height; + CLog::Log(LOGDEBUG, "%s::%s format changed: %dx%d %.2f frame:%d", CLASSNAME, __func__, m_decoded_width, m_decoded_height, m_aspect_ratio, m_changed_count); - } -- m_is_open = false; ++ } + else + CLog::Log(LOGERROR, "%s::%s format changed: Unexpected %dx%d", CLASSNAME, __func__, m_es_format->es->video.crop.width, m_es_format->es->video.crop.height); - } - --void COpenMaxVideo::SetDropState(bool bDrop) -+void COpenMaxVideo::dec_control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) - { -- m_drop_state = bDrop; ++} ++ ++void CMMALVideo::dec_control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) ++{ + MMAL_STATUS_T status; - -- if (m_drop_state) ++ + if (buffer->cmd == MMAL_EVENT_ERROR) + { + status = (MMAL_STATUS_T)*(uint32_t *)buffer->data; + CLog::Log(LOGERROR, "%s::%s Error (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); + } + else if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) - { -- OMX_ERRORTYPE omx_err; ++ { + CLog::Log(LOGDEBUG, "%s::%s format changed", CLASSNAME, __func__); + PortSettingsChanged(port, buffer); + } + else + CLog::Log(LOGERROR, "%s::%s other (cmd:%x data:%x)", CLASSNAME, __func__, buffer->cmd, *(uint32_t *)buffer->data); - -- // blow all but the last ready video frame -- pthread_mutex_lock(&m_omx_output_mutex); -- while (m_omx_output_ready.size() > 1) -- { -- m_dts_queue.pop(); -- OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_output_ready.front()->omx_buffer; -- m_omx_output_ready.pop(); -- // return the omx buffer back to OpenMax to fill. -- omx_err = OMX_FillThisBuffer(m_omx_decoder, omx_buffer); -- if (omx_err) -- CLog::Log(LOGERROR, "%s::%s - OMX_FillThisBuffer, omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); -- } -- pthread_mutex_unlock(&m_omx_output_mutex); ++ + mmal_buffer_header_release(buffer); +} - -- #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s - m_drop_state(%d)\n", -- CLASSNAME, __func__, m_drop_state); -- #endif -- } ++ +static void dec_control_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) +{ -+ COpenMaxVideo *omx = reinterpret_cast(port->userdata); -+ omx->dec_control_port_cb(port, buffer); - } - --int COpenMaxVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) ++ CMMALVideo *mmal = reinterpret_cast(port->userdata); ++ mmal->dec_control_port_cb(port, buffer); ++} ++ + +static void dec_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) - { -- if (pData) -- { -- int demuxer_bytes = iSize; -- uint8_t *demuxer_content = pData; -+#if defined(OMX_DEBUG_VERBOSE) ++{ ++#if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s port:%p buffer %p, len %d cmd:%x", CLASSNAME, __func__, port, buffer, buffer->length, buffer->cmd); +#endif + mmal_buffer_header_release(buffer); +} - -- // we need to queue then de-queue the demux packet, seems silly but -- // omx might not have a omx input buffer avaliable when we are called -- // and we must store the demuxer packet and try again later. -- omx_demux_packet demux_packet; -- demux_packet.dts = dts; -- demux_packet.pts = pts; - -- demux_packet.size = demuxer_bytes; -- demux_packet.buff = new OMX_U8[demuxer_bytes]; -- memcpy(demux_packet.buff, demuxer_content, demuxer_bytes); -- m_demux_queue.push(demux_packet); -+void COpenMaxVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) ++ ++ ++void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) +{ -+#if defined(OMX_DEBUG_VERBOSE) ++#if defined(MMAL_DEBUG_VERBOSE) + if (!(buffer->cmd == 0 && buffer->length > 0)) + CLog::Log(LOGDEBUG, "%s::%s port:%p buffer %p, len %d cmd:%x", CLASSNAME, __func__, port, buffer, buffer->length, buffer->cmd); +#endif + bool kept = false; - -- // we can look at m_omx_input_avaliable.empty without needing to lock/unlock -- // try to send any/all demux packets to omx decoder. -- while (!m_omx_input_avaliable.empty() && !m_demux_queue.empty() ) ++ + if (buffer->cmd == 0) + { + if (buffer->length > 0) - { -- OMX_ERRORTYPE omx_err; -- OMX_BUFFERHEADERTYPE* omx_buffer; -- -- demux_packet = m_demux_queue.front(); -- m_demux_queue.pop(); -- // need to lock here to retreve an input buffer and pop the queue -- pthread_mutex_lock(&m_omx_input_mutex); -- omx_buffer = m_omx_input_avaliable.front(); -- m_omx_input_avaliable.pop(); -- pthread_mutex_unlock(&m_omx_input_mutex); -- -- // delete the previous demuxer buffer -- delete [] omx_buffer->pBuffer; -- // setup a new omx_buffer. -- omx_buffer->nFlags = m_omx_input_eos ? OMX_BUFFERFLAG_EOS : 0; -- omx_buffer->nOffset = 0; -- omx_buffer->pBuffer = demux_packet.buff; -- omx_buffer->nAllocLen = demux_packet.size; -- omx_buffer->nFilledLen = demux_packet.size; -- omx_buffer->nTimeStamp = (demux_packet.pts == DVD_NOPTS_VALUE) ? 0 : demux_packet.pts * 1000.0; // in microseconds; -- omx_buffer->pAppPrivate = omx_buffer; -- omx_buffer->nInputPortIndex = m_omx_input_port; -- -- #if defined(OMX_DEBUG_EMPTYBUFFERDONE) -- CLog::Log(LOGDEBUG, -- "%s::%s - feeding decoder, omx_buffer->pBuffer(0x%p), demuxer_bytes(%d)\n", -- CLASSNAME, __func__, omx_buffer->pBuffer, demuxer_bytes); -- #endif -- // Give this omx_buffer to OpenMax to be decoded. -- omx_err = OMX_EmptyThisBuffer(m_omx_decoder, omx_buffer); -- if (omx_err) ++ { + assert(!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_DECODEONLY)); + double dts = DVD_NOPTS_VALUE; -+ #ifdef DTS_QUEUE -+ pthread_mutex_lock(&m_omx_output_mutex); ++ pthread_mutex_lock(&m_output_mutex); + if (!m_dts_queue.empty()) - { -- CLog::Log(LOGDEBUG, -- "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", -- CLASSNAME, __func__, omx_err); -- return VC_ERROR; ++ { + dts = m_dts_queue.front(); + m_dts_queue.pop(); - } -- // only push if we are successful with feeding OMX_EmptyThisBuffer -- m_dts_queue.push(demux_packet.dts); ++ } + else assert(0); -+ pthread_mutex_unlock(&m_omx_output_mutex); -+ #endif - -- // if m_omx_input_avaliable and/or demux_queue are now empty, -- // wait up to 20ms for OpenMax to consume a demux packet -- if (m_omx_input_avaliable.empty() || m_demux_queue.empty()) -- m_input_consumed_event.WaitMSec(1); ++ pthread_mutex_unlock(&m_output_mutex); ++ + if (m_drop_state) + { + CLog::Log(LOGDEBUG, "%s::%s - dropping %p (drop:%d)", CLASSNAME, __func__, buffer, m_drop_state); + } + else + { -+ COpenMaxVideoBuffer *omvb = new COpenMaxVideoBuffer(this); -+ m_omx_output_busy++; -+#if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s - %p (%p) buffer_size(%u) dts:%.3f pts:%.3f flags:%x:%x frame:%d", -+ CLASSNAME, __func__, buffer, omvb, buffer->length, dts*1e-6, buffer->pts*1e-6, buffer->flags, buffer->type->video.flags, omvb->m_changed_count); ++ CMMALVideoBuffer *omvb = new CMMALVideoBuffer(this); ++ m_output_busy++; ++#if defined(MMAL_DEBUG_VERBOSE) ++ CLog::Log(LOGDEBUG, "%s::%s - %p (%p) buffer_size(%u) dts:%.3f pts:%.3f flags:%x:%x frame:%d", ++ CLASSNAME, __func__, buffer, omvb, buffer->length, dts*1e-6, buffer->pts*1e-6, buffer->flags, buffer->type->video.flags, omvb->m_changed_count); +#endif + omvb->mmal_buffer = buffer; + buffer->user_data = (void *)omvb; @@ -7923,195 +6383,71 @@ index dcbdb1e..3218b63 100644 + omvb->width = m_decoded_width; + omvb->height = m_decoded_height; + omvb->m_aspect_ratio = m_aspect_ratio; -+ pthread_mutex_lock(&m_omx_output_mutex); -+ m_omx_output_ready.push(omvb); -+ pthread_mutex_unlock(&m_omx_output_mutex); ++ pthread_mutex_lock(&m_output_mutex); ++ m_output_ready.push(omvb); ++ pthread_mutex_unlock(&m_output_mutex); + kept = true; + } - } -- if (m_omx_input_avaliable.empty() && !m_demux_queue.empty()) -- m_input_consumed_event.WaitMSec(1); -- -- #if defined(OMX_DEBUG_VERBOSE) -- if (m_omx_input_avaliable.empty()) -- CLog::Log(LOGDEBUG, -- "%s::%s - buffering demux, m_demux_queue_size(%d), demuxer_bytes(%d)\n", -- CLASSNAME, __func__, m_demux_queue.size(), demuxer_bytes); -- #endif - } -- -- if (m_omx_output_ready.empty()) -- return VC_BUFFER; -- -- return VC_PICTURE | VC_BUFFER; --} -- --void COpenMaxVideo::Reset(void) --{ -- #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__); -- #endif --/* -- // only reset OpenMax decoder if it's running -- if (m_omx_decoder_state == OMX_StateExecuting) ++ } ++ } + else if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) - { -- OMX_ERRORTYPE omx_err; -- -- omx_err = StopDecoder(); -- // Alloc OpenMax input buffers. -- omx_err = AllocOMXInputBuffers(); -- // Alloc OpenMax output buffers. -- omx_err = AllocOMXOutputBuffers(); -- -- omx_err = StartDecoder(); ++ { + PortSettingsChanged(port, buffer); - } --*/ -- ::Sleep(100); ++ } + if (!kept) + mmal_buffer_header_release(buffer); - } - --bool COpenMaxVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) -+static void dec_output_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) - { -- while (m_omx_output_busy.size() > 1) -- { -- // fetch a output buffer and pop it off the busy list -- pthread_mutex_lock(&m_omx_output_mutex); -- OpenMaxVideoBuffer *buffer = m_omx_output_busy.front(); -- m_omx_output_busy.pop(); -- pthread_mutex_unlock(&m_omx_output_mutex); -+ COpenMaxVideo *omx = reinterpret_cast(port->userdata); -+ omx->dec_output_port_cb(port, buffer); +} - -- bool done = buffer->omx_buffer->nFlags & OMX_BUFFERFLAG_EOS; -- if (!done) -- { -- // return the omx buffer back to OpenMax to fill. -- OMX_ERRORTYPE omx_err = OMX_FillThisBuffer(m_omx_decoder, buffer->omx_buffer); -- if (omx_err) -- CLog::Log(LOGERROR, "%s::%s - OMX_FillThisBuffer, omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); -- } -- } -+bool COpenMaxVideo::change_dec_output_format() ++ ++static void dec_output_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) ++{ ++ CMMALVideo *mmal = reinterpret_cast(port->userdata); ++ mmal->dec_output_port_cb(port, buffer); ++} ++ ++bool CMMALVideo::change_dec_output_format() +{ + MMAL_STATUS_T status; + CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); - -- if (!m_omx_output_ready.empty()) -+#if 0 - { -- OpenMaxVideoBuffer *buffer; -- // fetch a output buffer and pop it off the ready list -- pthread_mutex_lock(&m_omx_output_mutex); -- buffer = m_omx_output_ready.front(); -- m_omx_output_ready.pop(); -- m_omx_output_busy.push(buffer); -- pthread_mutex_unlock(&m_omx_output_mutex); ++ + MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T interlace_type = {{ MMAL_PARAMETER_VIDEO_INTERLACE_TYPE, sizeof( interlace_type )}}; + status = mmal_port_parameter_get( m_dec_output, &interlace_type.hdr ); - -- pDvdVideoPicture->dts = DVD_NOPTS_VALUE; -- pDvdVideoPicture->pts = DVD_NOPTS_VALUE; -- pDvdVideoPicture->format = RENDER_FMT_OMXEGL; -- pDvdVideoPicture->openMax = this; -- pDvdVideoPicture->openMaxBuffer = buffer; -- -- if (!m_dts_queue.empty()) ++ + if (status == MMAL_SUCCESS) + { + if (m_interlace_mode != interlace_type.eMode) - { -- pDvdVideoPicture->dts = m_dts_queue.front(); -- m_dts_queue.pop(); ++ { + CLog::Log(LOGDEBUG, "%s::%s Interlace mode %d->%d", CLASSNAME, __func__, m_interlace_mode, interlace_type.eMode); + m_interlace_mode = interlace_type.eMode; - } -- // nTimeStamp is in microseconds -- pDvdVideoPicture->pts = (buffer->omx_buffer->nTimeStamp == 0) ? DVD_NOPTS_VALUE : (double)buffer->omx_buffer->nTimeStamp / 1000.0; - } -- #if defined(OMX_DEBUG_VERBOSE) - else -+ CLog::Log(LOGERROR, "%s::%s Failed to query interlace type on %s (status=%x %s)", CLASSNAME, __func__, m_dec_output->name, status, mmal_status_to_string(status)); ++ } + } -+#endif ++ else ++ CLog::Log(LOGERROR, "%s::%s Failed to query interlace type on %s (status=%x %s)", CLASSNAME, __func__, m_dec_output->name, status, mmal_status_to_string(status)); ++ + // todo: if we don't disable/enable we can do this from callback + mmal_format_copy(m_dec_output->format, m_es_format); + status = mmal_port_format_commit(m_dec_output); + if (status != MMAL_SUCCESS) - { -- CLog::Log(LOGDEBUG, "%s::%s - called but m_omx_output_ready is empty\n", -- CLASSNAME, __func__); ++ { + CLog::Log(LOGERROR, "%s::%s Failed to commit decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); + return false; - } -- #endif -- -- pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; -- pDvdVideoPicture->iFlags |= m_drop_state ? DVP_FLAG_DROPPED : 0; -- - return true; - } - -- --// DecoderEmptyBufferDone -- OpenMax input buffer has been emptied --OMX_ERRORTYPE COpenMaxVideo::DecoderEmptyBufferDone( -- OMX_HANDLETYPE hComponent, -- OMX_PTR pAppData, -- OMX_BUFFERHEADERTYPE* pBuffer) --{ -- COpenMaxVideo *ctx = static_cast(pAppData); --/* -- #if defined(OMX_DEBUG_EMPTYBUFFERDONE) -- CLog::Log(LOGDEBUG, "%s::%s - buffer_size(%lu), timestamp(%f)\n", -- CLASSNAME, __func__, pBuffer->nFilledLen, (double)pBuffer->nTimeStamp / 1000.0); -- #endif --*/ -- // queue free input buffer to avaliable list. -- pthread_mutex_lock(&ctx->m_omx_input_mutex); -- ctx->m_omx_input_avaliable.push(pBuffer); -- ctx->m_input_consumed_event.Set(); -- pthread_mutex_unlock(&ctx->m_omx_input_mutex); -- -- return OMX_ErrorNone; --} -- --// DecoderFillBufferDone -- OpenMax output buffer has been filled --OMX_ERRORTYPE COpenMaxVideo::DecoderFillBufferDone( -- OMX_HANDLETYPE hComponent, -- OMX_PTR pAppData, -- OMX_BUFFERHEADERTYPE* pBuffer) -+bool COpenMaxVideo::CreateDeinterlace() - { -- COpenMaxVideo *ctx = static_cast(pAppData); -- OpenMaxVideoBuffer *buffer = (OpenMaxVideoBuffer*)pBuffer->pAppPrivate; ++ } ++ return true; ++} ++ ++bool CMMALVideo::CreateDeinterlace() ++{ + MMAL_STATUS_T status; - -- #if defined(OMX_DEBUG_FILLBUFFERDONE) -- CLog::Log(LOGDEBUG, "%s::%s - buffer_size(%lu), timestamp(%f)\n", -- CLASSNAME, __func__, pBuffer->nFilledLen, (double)pBuffer->nTimeStamp / 1000.0); -- #endif ++ + assert(!m_deint); + assert(m_dec_output == m_dec->output[0]); - -- if (!ctx->m_portChanging) ++ + status = mmal_port_disable(m_dec_output); + if (status != MMAL_SUCCESS) - { -- // queue output omx buffer to ready list. -- pthread_mutex_lock(&ctx->m_omx_output_mutex); -- ctx->m_omx_output_ready.push(buffer); -- pthread_mutex_unlock(&ctx->m_omx_output_mutex); ++ { + CLog::Log(LOGERROR, "%s::%s Failed to disable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); + return false; - } - -- return OMX_ErrorNone; --} ++ } ++ + /* Create deinterlace filter */ + status = mmal_component_create("vc.ril.image_fx", &m_deint); + if (status != MMAL_SUCCESS) @@ -8126,16 +6462,10 @@ index dcbdb1e..3218b63 100644 + CLog::Log(LOGERROR, "%s::%s Failed to set deinterlace parameters (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); + return false; + } - --void COpenMaxVideo::QueryCodec(void) --{ -- OMX_ERRORTYPE omx_err = OMX_ErrorNone; -- OMX_VIDEO_PARAM_PROFILELEVELTYPE port_param; -- OMX_INIT_STRUCTURE(port_param); ++ + MMAL_PORT_T *m_deint_input = m_deint->input[0]; + m_deint_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; - -- port_param.nPortIndex = m_omx_input_port; ++ + // Now connect the decoder output port to deinterlace input port + status = mmal_connection_create(&m_deint_connection, m_dec->output[0], m_deint->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT); + if (status != MMAL_SUCCESS) @@ -8143,165 +6473,73 @@ index dcbdb1e..3218b63 100644 + CLog::Log(LOGERROR, "%s::%s Failed to connect deinterlacer component %s (status=%x %s)", CLASSNAME, __func__, m_deint->name, status, mmal_status_to_string(status)); + return false; + } - -- for (port_param.nProfileIndex = 0;; port_param.nProfileIndex++) ++ + status = mmal_connection_enable(m_deint_connection); + if (status != MMAL_SUCCESS) - { -- omx_err = OMX_GetParameter(m_omx_decoder, -- OMX_IndexParamVideoProfileLevelQuerySupported, &port_param); -- if (omx_err) -- break; ++ { + CLog::Log(LOGERROR, "%s::%s Failed to enable connection %s (status=%x %s)", CLASSNAME, __func__, m_deint->name, status, mmal_status_to_string(status)); + return false; + } - -- omx_codec_capability omx_capability; -- omx_capability.level = port_param.eLevel; -- omx_capability.profile = port_param.eProfile; -- m_omx_decoder_capabilities.push_back(omx_capability); ++ + mmal_format_copy(m_deint->output[0]->format, m_es_format); + status = mmal_port_format_commit(m_deint->output[0]); + if (status != MMAL_SUCCESS) + { + CLog::Log(LOGERROR, "%s::%s Failed to commit deint output format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); + return false; - } --} - --OMX_ERRORTYPE COpenMaxVideo::PrimeFillBuffers(void) --{ -- OMX_ERRORTYPE omx_err = OMX_ErrorNone; -- OpenMaxVideoBuffer *buffer; ++ } ++ + status = mmal_component_enable(m_deint); + if (status != MMAL_SUCCESS) + { + CLog::Log(LOGERROR, "%s::%s Failed to enable deinterlacer component %s (status=%x %s)", CLASSNAME, __func__, m_deint->name, status, mmal_status_to_string(status)); + return false; + } - -- #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__); -- #endif -- // tell OpenMax to start filling output buffers -- for (size_t i = 0; i < m_omx_output_buffers.size(); i++) ++ + m_deint->output[0]->buffer_size = m_deint->output[0]->buffer_size_min; + m_deint->output[0]->buffer_num = m_deint->output[0]->buffer_num_recommended; + m_deint->output[0]->userdata = (struct MMAL_PORT_USERDATA_T *)this; + status = mmal_port_enable(m_deint->output[0], dec_output_port_cb_static); + if (status != MMAL_SUCCESS) - { -- buffer = m_omx_output_buffers[i]; -- // always set the port index. -- buffer->omx_buffer->nOutputPortIndex = m_omx_output_port; -- // Need to clear the EOS flag. -- buffer->omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS; -- buffer->omx_buffer->pAppPrivate = buffer; -- -- omx_err = OMX_FillThisBuffer(m_omx_decoder, buffer->omx_buffer); -- if (omx_err) -- CLog::Log(LOGERROR, "%s::%s - OMX_FillThisBuffer failed with omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); ++ { + CLog::Log(LOGERROR, "%s::%s Failed to enable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); + return false; - } - -- return omx_err; ++ } ++ + m_dec_output = m_deint->output[0]; + + return true; - } - --OMX_ERRORTYPE COpenMaxVideo::AllocOMXInputBuffers(void) -+bool COpenMaxVideo::DestroyDeinterlace() - { -- OMX_ERRORTYPE omx_err = OMX_ErrorNone; ++} ++ ++bool CMMALVideo::DestroyDeinterlace() ++{ + MMAL_STATUS_T status; - -- // Obtain the information about the decoder input port. -- OMX_PARAM_PORTDEFINITIONTYPE port_format; -- OMX_INIT_STRUCTURE(port_format); -- port_format.nPortIndex = m_omx_input_port; -- OMX_GetParameter(m_omx_decoder, OMX_IndexParamPortDefinition, &port_format); ++ + assert(m_deint); + assert(m_dec_output == m_deint->output[0]); - -- #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, -- "%s::%s - iport(%d), nBufferCountMin(%lu), nBufferSize(%lu)\n", -- CLASSNAME, __func__, m_omx_input_port, port_format.nBufferCountMin, port_format.nBufferSize); -- #endif -- for (size_t i = 0; i < port_format.nBufferCountMin; i++) ++ + status = mmal_port_disable(m_dec_output); + if (status != MMAL_SUCCESS) - { -- OMX_BUFFERHEADERTYPE *buffer = NULL; -- // use an external buffer that's sized according to actual demux -- // packet size, start at internal's buffer size, will get deleted when -- // we start pulling demuxer packets and using demux packet sized buffers. -- OMX_U8* data = new OMX_U8[port_format.nBufferSize]; -- omx_err = OMX_UseBuffer(m_omx_decoder, &buffer, m_omx_input_port, NULL, port_format.nBufferSize, data); -- if (omx_err) -- { -- CLog::Log(LOGERROR, "%s::%s - OMX_UseBuffer failed with omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); -- return(omx_err); -- } -- m_omx_input_buffers.push_back(buffer); -- // don't have to lock/unlock here, we are not decoding -- m_omx_input_avaliable.push(buffer); ++ { + CLog::Log(LOGERROR, "%s::%s Failed to disable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); + return false; - } -- m_omx_input_eos = false; - -- return(omx_err); --} --OMX_ERRORTYPE COpenMaxVideo::FreeOMXInputBuffers(bool wait) --{ -- OMX_ERRORTYPE omx_err = OMX_ErrorNone; -- -- /* -- omx_err = OMX_SendCommand(m_omx_decoder, OMX_CommandFlush, m_omx_input_port, 0); -- if (omx_err) -- CLog::Log(LOGERROR, "%s::%s - OMX_CommandFlush failed with omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); -- else if (wait) -- sem_wait(m_omx_flush_input); -- */ -- -- // free omx input port buffers. -- for (size_t i = 0; i < m_omx_input_buffers.size(); i++) ++ } ++ + status = mmal_connection_destroy(m_deint_connection); + if (status != MMAL_SUCCESS) - { -- // using external buffers (OMX_UseBuffer), free our external buffers -- // before calling OMX_FreeBuffer which frees the omx buffer. -- delete [] m_omx_input_buffers[i]->pBuffer; -- m_omx_input_buffers[i]->pBuffer = NULL; -- omx_err = OMX_FreeBuffer(m_omx_decoder, m_omx_input_port, m_omx_input_buffers[i]); ++ { + CLog::Log(LOGERROR, "%s::%s Failed to destroy deinterlace connection (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); + return false; - } -- m_omx_input_buffers.clear(); ++ } + m_deint_connection = NULL; - -- // empty input buffer queue. not decoding so don't need lock/unlock. -- while (!m_omx_input_avaliable.empty()) -- m_omx_input_avaliable.pop(); -- while (!m_demux_queue.empty()) -- m_demux_queue.pop(); -- while (!m_dts_queue.empty()) -- m_dts_queue.pop(); ++ + status = mmal_component_disable(m_deint); + if (status != MMAL_SUCCESS) + { + CLog::Log(LOGERROR, "%s::%s Failed to disable deinterlace component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); + return false; + } - -- return(omx_err); --} ++ + status = mmal_component_destroy(m_deint); + if (status != MMAL_SUCCESS) + { @@ -8309,12 +6547,7 @@ index dcbdb1e..3218b63 100644 + return false; + } + m_deint = NULL; - --void COpenMaxVideo::CallbackAllocOMXEGLTextures(void *userdata) --{ -- COpenMaxVideo *omx = static_cast(userdata); -- omx->AllocOMXOutputEGLTextures(); --} ++ + m_dec->output[0]->buffer_size = m_dec->output[0]->buffer_size_min; + m_dec->output[0]->buffer_num = m_dec->output[0]->buffer_num_recommended; + m_dec->output[0]->userdata = (struct MMAL_PORT_USERDATA_T *)this; @@ -8324,83 +6557,61 @@ index dcbdb1e..3218b63 100644 + CLog::Log(LOGERROR, "%s::%s Failed to enable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); + return false; + } - --void COpenMaxVideo::CallbackFreeOMXEGLTextures(void *userdata) --{ -- COpenMaxVideo *omx = static_cast(userdata); -- omx->FreeOMXOutputEGLTextures(true); ++ + m_dec_output = m_dec->output[0]; + return true; - } - --OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputBuffers(void) -+bool COpenMaxVideo::SendCodecConfigData() - { -- OMX_ERRORTYPE omx_err; -- -- if ( g_application.IsCurrentThread() ) ++} ++ ++bool CMMALVideo::SendCodecConfigData() ++{ + MMAL_STATUS_T status; ++ if (!m_dec_input_pool) ++ return true; + // send code config data + MMAL_BUFFER_HEADER_T *buffer = mmal_queue_timedwait(m_dec_input_pool->queue, 500); + if (!buffer) - { -- omx_err = AllocOMXOutputEGLTextures(); ++ { + CLog::Log(LOGERROR, "%s::%s - mmal_queue_get failed", CLASSNAME, __func__); + return false; - } -- else ++ } + + mmal_buffer_header_reset(buffer); + buffer->cmd = 0; + buffer->length = std::min(m_hints.extrasize, buffer->alloc_size); + memcpy(buffer->data, m_hints.extradata, buffer->length); + buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END | MMAL_BUFFER_HEADER_FLAG_CONFIG; -+#if defined(OMX_DEBUG_VERBOSE) ++#if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d flags:%x", CLASSNAME, __func__, buffer, buffer->length, buffer->flags); +#endif + status = mmal_port_send_buffer(m_dec_input, buffer); + if (status != MMAL_SUCCESS) - { -- ThreadMessageCallback callbackData; -- callbackData.callback = &CallbackAllocOMXEGLTextures; -- callbackData.userptr = (void *)this; ++ { + CLog::Log(LOGERROR, "%s::%s Failed send buffer to decoder input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); + return false; + } + return true; +} - -- ThreadMessage tMsg; -- tMsg.dwMessage = TMSG_CALLBACK; -- tMsg.lpVoid = (void*)&callbackData; -+bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenMaxVideoPtr myself) ++ ++bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVideoPtr myself) +{ -+ #if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s useomx:%d software:%d %dx%d", CLASSNAME, __func__, CSettings::Get().GetBool("videoplayer.useomx"), hints.software, hints.width, hints.height); ++ #if defined(MMAL_DEBUG_VERBOSE) ++ CLog::Log(LOGDEBUG, "%s::%s usemmal:%d software:%d %dx%d", CLASSNAME, __func__, CSettings::Get().GetBool("videoplayer.usemmal"), hints.software, hints.width, hints.height); + #endif - -- g_application.getApplicationMessenger().SendMessage(tMsg, true); ++ + // we always qualify even if DVDFactoryCodec does this too. -+ if (!CSettings::Get().GetBool("videoplayer.useomx") || hints.software) ++ if (!CSettings::Get().GetBool("videoplayer.usemmal") || hints.software) + return false; - -- omx_err = OMX_ErrorNone; -- } ++ + m_hints = hints; + MMAL_STATUS_T status; + MMAL_PARAMETER_BOOLEAN_T error_concealment; - -- return omx_err; --} ++ + m_myself = myself; + m_decoded_width = hints.width; + m_decoded_height = hints.height; + m_forced_aspect_ratio = hints.forced_aspect; + m_aspect_ratio = hints.aspect; - --OMX_ERRORTYPE COpenMaxVideo::FreeOMXOutputBuffers(bool wait) --{ -- OMX_ERRORTYPE omx_err = FreeOMXOutputEGLTextures(wait); ++ + switch (hints.codec) + { + case AV_CODEC_ID_H264: @@ -8456,19 +6667,14 @@ index dcbdb1e..3218b63 100644 + return false; + break; + } - -- return omx_err; --} ++ + if ( (m_codingType == MMAL_ENCODING_MP2V && !g_RBP.GetCodecMpg2() ) || + (m_codingType == MMAL_ENCODING_WVC1 && !g_RBP.GetCodecWvc1() ) ) + { + CLog::Log(LOGWARNING, "%s::%s Codec %s is not supported", CLASSNAME, __func__, m_pFormatName); + return false; + } - --OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputEGLTextures(void) --{ -- OMX_ERRORTYPE omx_err; ++ + // initialize mmal. + status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &m_dec); + if (status != MMAL_SUCCESS) @@ -8476,40 +6682,24 @@ index dcbdb1e..3218b63 100644 + CLog::Log(LOGERROR, "%s::%s Failed to create MMAL decoder component %s (status=%x %s)", CLASSNAME, __func__, MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, status, mmal_status_to_string(status)); + return false; + } - -- if (!eglCreateImageKHR) ++ + m_dec->control->userdata = (struct MMAL_PORT_USERDATA_T *)this; + status = mmal_port_enable(m_dec->control, dec_control_port_cb_static); + if (status != MMAL_SUCCESS) - { -- GETEXTENSION(PFNEGLCREATEIMAGEKHRPROC, eglCreateImageKHR); ++ { + CLog::Log(LOGERROR, "%s::%s Failed to enable decoder control port %s (status=%x %s)", CLASSNAME, __func__, MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, status, mmal_status_to_string(status)); + return false; - } - -- EGLint attrib = EGL_NONE; -- OpenMaxVideoBuffer *egl_buffer; ++ } ++ + m_dec_input = m_dec->input[0]; - -- // Obtain the information about the output port. -- OMX_PARAM_PORTDEFINITIONTYPE port_format; -- OMX_INIT_STRUCTURE(port_format); -- port_format.nPortIndex = m_omx_output_port; -- omx_err = OMX_GetParameter(m_omx_decoder, OMX_IndexParamPortDefinition, &port_format); ++ + m_dec_input->format->type = MMAL_ES_TYPE_VIDEO; + m_dec_input->format->encoding = m_codingType; + if (m_hints.width && m_hints.height) + { + m_dec_input->format->es->video.crop.width = m_hints.width; + m_dec_input->format->es->video.crop.height = m_hints.height; - -- #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, -- "%s::%s (1) - oport(%d), nFrameWidth(%lu), nFrameHeight(%lu), nStride(%lx), nBufferCountMin(%lu), nBufferSize(%lu)\n", -- CLASSNAME, __func__, m_omx_output_port, -- port_format.format.video.nFrameWidth, port_format.format.video.nFrameHeight,port_format.format.video.nStride, -- port_format.nBufferCountMin, port_format.nBufferSize); -- #endif ++ + m_dec_input->format->es->video.width = ALIGN_UP(m_hints.width, 32); + m_dec_input->format->es->video.height = ALIGN_UP(m_hints.height, 16); + } @@ -8521,67 +6711,20 @@ index dcbdb1e..3218b63 100644 + status = mmal_port_parameter_set(m_dec_input, &error_concealment.hdr); + if (status != MMAL_SUCCESS) + CLog::Log(LOGERROR, "%s::%s Failed to disable error concealment on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); - -- glActiveTexture(GL_TEXTURE0); ++ + status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_EXTRA_BUFFERS, 5); + if (status != MMAL_SUCCESS) + CLog::Log(LOGERROR, "%s::%s Failed to enable extra buffers on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); - -- for (size_t i = 0; i < port_format.nBufferCountMin; i++) ++ + status = mmal_port_format_commit(m_dec_input); + if (status != MMAL_SUCCESS) - { -- egl_buffer = new OpenMaxVideoBuffer; -- memset(egl_buffer, 0, sizeof(*egl_buffer)); -- egl_buffer->width = m_decoded_width; -- egl_buffer->height = m_decoded_height; -- -- glGenTextures(1, &egl_buffer->texture_id); -- glBindTexture(GL_TEXTURE_2D, egl_buffer->texture_id); -- -- // create space for buffer with a texture -- glTexImage2D( -- GL_TEXTURE_2D, // target -- 0, // level -- GL_RGBA, // internal format -- m_decoded_width, // width -- m_decoded_height, // height -- 0, // border -- GL_RGBA, // format -- GL_UNSIGNED_BYTE, // type -- NULL); // pixels -- will be provided later -- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); -- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); -- -- // create EGLImage from texture -- egl_buffer->egl_image = eglCreateImageKHR( -- m_egl_display, -- m_egl_context, -- EGL_GL_TEXTURE_2D_KHR, -- (EGLClientBuffer)(egl_buffer->texture_id), -- &attrib); -- if (!egl_buffer->egl_image) -- { -- CLog::Log(LOGERROR, "%s::%s - ERROR creating EglImage\n", CLASSNAME, __func__); -- return(OMX_ErrorUndefined); -- } -- egl_buffer->index = i; ++ { + CLog::Log(LOGERROR, "%s::%s Failed to commit format for decoder input port %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); + return false; + } + m_dec_input->buffer_size = m_dec_input->buffer_size_recommended; + m_dec_input->buffer_num = m_dec_input->buffer_num_recommended; - -- // tell decoder output port that it will be using EGLImage -- omx_err = OMX_UseEGLImage( -- m_omx_decoder, &egl_buffer->omx_buffer, m_omx_output_port, egl_buffer, egl_buffer->egl_image); -- if (omx_err) -- { -- CLog::Log(LOGERROR, "%s::%s - OMX_UseEGLImage failed with omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); -- return(omx_err); -- } -- m_omx_output_buffers.push_back(egl_buffer); ++ + m_dec_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; + status = mmal_port_enable(m_dec_input, dec_input_port_cb); + if (status != MMAL_SUCCESS) @@ -8595,23 +6738,14 @@ index dcbdb1e..3218b63 100644 + // set up initial decoded frame format - will likely change from this + m_dec_output->format->encoding = MMAL_ENCODING_OPAQUE; + mmal_format_copy(m_es_format, m_dec_output->format); - -- CLog::Log(LOGDEBUG, "%s::%s - Texture %p Width %d Height %d\n", -- CLASSNAME, __func__, egl_buffer->egl_image, egl_buffer->width, egl_buffer->height); ++ + status = mmal_port_format_commit(m_dec_output); + if (status != MMAL_SUCCESS) + { + CLog::Log(LOGERROR, "%s::%s Failed to commit decoder output format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); + return false; - } -- m_omx_output_eos = false; -- while (!m_omx_output_busy.empty()) -- m_omx_output_busy.pop(); -- while (!m_omx_output_ready.empty()) -- m_omx_output_ready.pop(); - -- return omx_err; --} ++ } ++ + m_dec_output->buffer_size = m_dec_output->buffer_size_min; + m_dec_output->buffer_num = m_dec_output->buffer_num_recommended; + m_dec_output->userdata = (struct MMAL_PORT_USERDATA_T *)this; @@ -8621,312 +6755,92 @@ index dcbdb1e..3218b63 100644 + CLog::Log(LOGERROR, "%s::%s Failed to enable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); + return false; + } - --OMX_ERRORTYPE COpenMaxVideo::FreeOMXOutputEGLTextures(bool wait) --{ -- OMX_ERRORTYPE omx_err = OMX_ErrorNone; -- OpenMaxVideoBuffer *egl_buffer; ++ + status = mmal_component_enable(m_dec); + if (status != MMAL_SUCCESS) + { + CLog::Log(LOGERROR, "%s::%s Failed to enable decoder component %s (status=%x %s)", CLASSNAME, __func__, m_dec->name, status, mmal_status_to_string(status)); + return false; + } - -- if (!eglDestroyImageKHR) ++ + m_dec_input_pool = mmal_pool_create(m_dec_input->buffer_num, m_dec_input->buffer_size); + if (!m_dec_input_pool) - { -- GETEXTENSION(PFNEGLDESTROYIMAGEKHRPROC, eglDestroyImageKHR); ++ { + CLog::Log(LOGERROR, "%s::%s Failed to create pool for decoder input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); + return false; - } - -- for (size_t i = 0; i < m_omx_output_buffers.size(); i++) ++ } ++ + m_dec_output_pool = mmal_pool_create(m_dec_output->buffer_num, m_dec_output->buffer_size); + if(!m_dec_output_pool) - { -- egl_buffer = m_omx_output_buffers[i]; -- // tell decoder output port to stop using the EGLImage -- omx_err = OMX_FreeBuffer(m_omx_decoder, m_omx_output_port, egl_buffer->omx_buffer); -- // destroy egl_image -- eglDestroyImageKHR(m_egl_display, egl_buffer->egl_image); -- // free texture -- glDeleteTextures(1, &egl_buffer->texture_id); -- delete egl_buffer; ++ { + CLog::Log(LOGERROR, "%s::%s Failed to create pool for decode output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); + return false; - } -- m_omx_output_buffers.clear(); - -- return omx_err; --} ++ } ++ + if (!SendCodecConfigData()) + return false; - ++ + m_drop_state = false; + m_startframe = false; - --//////////////////////////////////////////////////////////////////////////////////////////// --// DecoderEventHandler -- OMX event callback --OMX_ERRORTYPE COpenMaxVideo::DecoderEventHandler( -- OMX_HANDLETYPE hComponent, -- OMX_PTR pAppData, -- OMX_EVENTTYPE eEvent, -- OMX_U32 nData1, -- OMX_U32 nData2, -- OMX_PTR pEventData) --{ -- OMX_ERRORTYPE omx_err; -- COpenMaxVideo *ctx = static_cast(pAppData); ++ + return true; +} - --/* -+void COpenMaxVideo::Dispose() ++ ++void CMMALVideo::Dispose() +{ + // we are happy to exit, but let last shared pointer being deleted trigger the destructor + bool done = false; + Reset(); -+ pthread_mutex_lock(&m_omx_output_mutex); -+ if (!m_omx_output_busy) ++ pthread_mutex_lock(&m_output_mutex); ++ if (!m_output_busy) + done = true; + m_finished = true; -+ pthread_mutex_unlock(&m_omx_output_mutex); - #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, -- "COpenMax::%s - hComponent(0x%p), eEvent(0x%x), nData1(0x%lx), nData2(0x%lx), pEventData(0x%p)\n", -- __func__, hComponent, eEvent, nData1, nData2, pEventData); -+ CLog::Log(LOGDEBUG, "%s::%s dts_queue(%d) ready_queue(%d) busy_queue(%d) done:%d", CLASSNAME, __func__, m_dts_queue.size(), m_omx_output_ready.size(), m_omx_output_busy, done); - #endif --*/ ++ pthread_mutex_unlock(&m_output_mutex); ++ #if defined(MMAL_DEBUG_VERBOSE) ++ CLog::Log(LOGDEBUG, "%s::%s dts_queue(%d) ready_queue(%d) busy_queue(%d) done:%d", CLASSNAME, __func__, m_dts_queue.size(), m_output_ready.size(), m_output_busy, done); ++ #endif + if (done) + { + assert(m_dts_queue.empty()); + m_myself.reset(); + } +} - -- switch (eEvent) -+void COpenMaxVideo::SetDropState(bool bDrop) ++ ++void CMMALVideo::SetDropState(bool bDrop) +{ -+#if defined(OMX_DEBUG_VERBOSE) ++#if defined(MMAL_DEBUG_VERBOSE) + if (m_drop_state != bDrop) + CLog::Log(LOGDEBUG, "%s::%s - m_drop_state(%d)", CLASSNAME, __func__, bDrop); +#endif + m_drop_state = bDrop; + if (m_drop_state) - { -- case OMX_EventCmdComplete: -- switch(nData1) -- { -- case OMX_CommandStateSet: -- ctx->m_omx_decoder_state = (int)nData2; -- switch (ctx->m_omx_decoder_state) -- { -- case OMX_StateInvalid: -- CLog::Log(LOGDEBUG, "%s::%s - OMX_StateInvalid\n", CLASSNAME, __func__); -- break; -- case OMX_StateLoaded: -- CLog::Log(LOGDEBUG, "%s::%s - OMX_StateLoaded\n", CLASSNAME, __func__); -- break; -- case OMX_StateIdle: -- CLog::Log(LOGDEBUG, "%s::%s - OMX_StateIdle\n", CLASSNAME, __func__); -- break; -- case OMX_StateExecuting: -- CLog::Log(LOGDEBUG, "%s::%s - OMX_StateExecuting\n", CLASSNAME, __func__); -- break; -- case OMX_StatePause: -- CLog::Log(LOGDEBUG, "%s::%s - OMX_StatePause\n", CLASSNAME, __func__); -- break; -- case OMX_StateWaitForResources: -- CLog::Log(LOGDEBUG, "%s::%s - OMX_StateWaitForResources\n", CLASSNAME, __func__); -- break; -- default: -- CLog::Log(LOGDEBUG, -- "%s::%s - Unknown OMX_Statexxxxx, state(%d)\n", -- CLASSNAME, __func__, ctx->m_omx_decoder_state); -- break; -- } -- sem_post(ctx->m_omx_decoder_state_change); -- break; -- case OMX_CommandFlush: -- /* -- if (OMX_ALL == (int)nData2) -- { -- sem_post(ctx->m_omx_flush_input); -- sem_post(ctx->m_omx_flush_output); -- CLog::Log(LOGDEBUG, "COpenMax::%s - OMX_CommandFlush input/output\n",__func__); -- } -- else if (ctx->m_omx_input_port == (int)nData2) -- { -- sem_post(ctx->m_omx_flush_input); -- CLog::Log(LOGDEBUG, "COpenMax::%s - OMX_CommandFlush input\n",__func__); -- } -- else if (ctx->m_omx_output_port == (int)nData2) -- { -- sem_post(ctx->m_omx_flush_output); -- CLog::Log(LOGDEBUG, "COpenMax::%s - OMX_CommandFlush ouput\n",__func__); -- } -- else -- */ -- { -- #if defined(OMX_DEBUG_EVENTHANDLER) -- CLog::Log(LOGDEBUG, -- "%s::%s - OMX_CommandFlush, nData2(0x%lx)\n", -- CLASSNAME, __func__, nData2); -- #endif -- } -- break; -- case OMX_CommandPortDisable: -- #if defined(OMX_DEBUG_EVENTHANDLER) -- CLog::Log(LOGDEBUG, -- "%s::%s - OMX_CommandPortDisable, nData1(0x%lx), nData2(0x%lx)\n", -- CLASSNAME, __func__, nData1, nData2); -- #endif -- if (ctx->m_omx_output_port == (int)nData2) -- { -- // Got OMX_CommandPortDisable event, alloc new buffers for the output port. -- ctx->AllocOMXOutputBuffers(); -- omx_err = OMX_SendCommand(ctx->m_omx_decoder, OMX_CommandPortEnable, ctx->m_omx_output_port, NULL); -- } -- break; -- case OMX_CommandPortEnable: -- #if defined(OMX_DEBUG_EVENTHANDLER) -- CLog::Log(LOGDEBUG, -- "%s::%s - OMX_CommandPortEnable, nData1(0x%lx), nData2(0x%lx)\n", -- CLASSNAME, __func__, nData1, nData2); -- #endif -- if (ctx->m_omx_output_port == (int)nData2) -- { -- // Got OMX_CommandPortEnable event. -- // OMX_CommandPortDisable will have re-alloced new ones so re-prime -- ctx->PrimeFillBuffers(); -- } -- ctx->m_portChanging = false; -- break; -- #if defined(OMX_DEBUG_EVENTHANDLER) -- case OMX_CommandMarkBuffer: -- CLog::Log(LOGDEBUG, -- "%s::%s - OMX_CommandMarkBuffer, nData1(0x%lx), nData2(0x%lx)\n", -- CLASSNAME, __func__, nData1, nData2); -- break; -- #endif -- } -- break; -- case OMX_EventBufferFlag: -- if (ctx->m_omx_decoder == hComponent && (nData2 & OMX_BUFFERFLAG_EOS)) { -- #if defined(OMX_DEBUG_EVENTHANDLER) -- if(ctx->m_omx_input_port == (int)nData1) -- CLog::Log(LOGDEBUG, "%s::%s - OMX_EventBufferFlag(input)\n", -- CLASSNAME, __func__); -- #endif -- if(ctx->m_omx_output_port == (int)nData1) -- { -- ctx->m_videoplayback_done = true; -- #if defined(OMX_DEBUG_EVENTHANDLER) -- CLog::Log(LOGDEBUG, "%s::%s - OMX_EventBufferFlag(output)\n", -- CLASSNAME, __func__); -- #endif -- } -- } -- break; -- case OMX_EventPortSettingsChanged: -- #if defined(OMX_DEBUG_EVENTHANDLER) -- CLog::Log(LOGDEBUG, -- "%s::%s - OMX_EventPortSettingsChanged(output)\n", CLASSNAME, __func__); -- #endif -- // not sure nData2 is the input/output ports in this call, docs don't say -- if (ctx->m_omx_output_port == (int)nData2) ++ { + while (1) + { -+ COpenMaxVideoBuffer *buffer = NULL; -+ pthread_mutex_lock(&m_omx_output_mutex); ++ CMMALVideoBuffer *buffer = NULL; ++ pthread_mutex_lock(&m_output_mutex); + // fetch a output buffer and pop it off the ready list -+ if (!m_omx_output_ready.empty()) - { -- // free the current OpenMax output buffers, you must do this before sending -- // OMX_CommandPortDisable to component as it expects output buffers -- // to be freed before it will issue a OMX_CommandPortDisable event. -- ctx->m_portChanging = true; -- OMX_SendCommand(ctx->m_omx_decoder, OMX_CommandPortDisable, ctx->m_omx_output_port, NULL); -- omx_err = ctx->FreeOMXOutputBuffers(false); -+ buffer = m_omx_output_ready.front(); -+ m_omx_output_ready.pop(); - } -- break; -- #if defined(OMX_DEBUG_EVENTHANDLER) -- case OMX_EventMark: -- CLog::Log(LOGDEBUG, "%s::%s - OMX_EventMark\n", CLASSNAME, __func__); -- break; -- case OMX_EventResourcesAcquired: -- CLog::Log(LOGDEBUG, "%s::%s - OMX_EventResourcesAcquired\n", CLASSNAME, __func__); -- break; -- #endif -- case OMX_EventError: -- switch((OMX_S32)nData1) -- { -- case OMX_ErrorInsufficientResources: -- CLog::Log(LOGERROR, "%s::%s - OMX_EventError, insufficient resources\n", -- CLASSNAME, __func__); -- // we are so frack'ed -- //exit(0); -- break; -- case OMX_ErrorFormatNotDetected: -- CLog::Log(LOGERROR, "%s::%s - OMX_EventError, cannot parse input stream\n", -- CLASSNAME, __func__); -- break; -- case OMX_ErrorPortUnpopulated: -- // silently ignore these. We can get them when setting OMX_CommandPortDisable -- // on the output port and the component flushes the output buffers. -- break; -- case OMX_ErrorStreamCorrupt: -- CLog::Log(LOGERROR, "%s::%s - OMX_EventError, Bitstream corrupt\n", -- CLASSNAME, __func__); -- ctx->m_videoplayback_done = true; -+ pthread_mutex_unlock(&m_omx_output_mutex); ++ if (!m_output_ready.empty()) ++ { ++ buffer = m_output_ready.front(); ++ m_output_ready.pop(); ++ } ++ pthread_mutex_unlock(&m_output_mutex); + if (buffer) -+ ReleaseOpenMaxBuffer(buffer); ++ ReleaseBuffer(buffer); + else - break; -- default: -- CLog::Log(LOGERROR, "%s::%s - OMX_EventError detected, nData1(0x%lx), nData2(0x%lx)\n", -- CLASSNAME, __func__, nData1, nData2); -- break; -- } -- // do this so we don't hang on errors -- /* -- sem_post(ctx->m_omx_flush_input); -- sem_post(ctx->m_omx_flush_output); -- */ -- sem_post(ctx->m_omx_decoder_state_change); -- break; -- default: -- CLog::Log(LOGWARNING, -- "%s::%s - Unknown eEvent(0x%x), nData1(0x%lx), nData2(0x%lx)\n", -- CLASSNAME, __func__, eEvent, nData1, nData2); -- break; ++ break; + } - } -- -- return OMX_ErrorNone; - } - --// StartPlayback -- Kick off video playback. --OMX_ERRORTYPE COpenMaxVideo::StartDecoder(void) -+int COpenMaxVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) - { -- OMX_ERRORTYPE omx_err; -- - #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__); ++ } ++} ++ ++int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) ++{ ++ #if defined(MMAL_DEBUG_VERBOSE) + //CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d dts:%.3f pts:%.3f dts_queue(%d) ready_queue(%d) busy_queue(%d)", -+ // CLASSNAME, __func__, pData, iSize, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, m_dts_queue.size(), m_omx_output_ready.size(), m_omx_output_busy); - #endif - -- // transition decoder component to IDLE state -- omx_err = SetStateForComponent(OMX_StateIdle); -- if (omx_err) ++ // CLASSNAME, __func__, pData, iSize, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, m_dts_queue.size(), m_output_ready.size(), m_output_busy); ++ #endif ++ + unsigned int demuxer_bytes = 0; + uint8_t *demuxer_content = NULL; + MMAL_BUFFER_HEADER_T *buffer; @@ -8935,32 +6849,26 @@ index dcbdb1e..3218b63 100644 + while (buffer = mmal_queue_get(m_dec_output_pool->queue), buffer) + Recycle(buffer); + // we need to queue then de-queue the demux packet, seems silly but -+ // omx might not have a omx input buffer available when we are called ++ // mmal might not have an input buffer available when we are called + // and we must store the demuxer packet and try again later. -+ // try to send any/all demux packets to omx decoder. ++ // try to send any/all demux packets to mmal decoder. + unsigned space = mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size; + if (pData && m_demux_queue.empty() && space >= (unsigned int)iSize) - { -- CLog::Log(LOGERROR, "%s::%s - setting OMX_StateIdle failed with omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); -- return omx_err; ++ { + demuxer_bytes = iSize; + demuxer_content = pData; + } + else if (pData && iSize) + { -+ omx_demux_packet demux_packet; ++ mmal_demux_packet demux_packet; + demux_packet.dts = dts; + demux_packet.pts = pts; + demux_packet.size = iSize; + demux_packet.buff = new uint8_t[iSize]; + memcpy(demux_packet.buff, pData, iSize); + m_demux_queue.push(demux_packet); - } - -- // transition decoder component to executing state -- omx_err = SetStateForComponent(OMX_StateExecuting); -- if (omx_err) ++ } ++ + uint8_t *buffer_to_free = NULL; + + while (1) @@ -8971,7 +6879,7 @@ index dcbdb1e..3218b63 100644 + space = mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size; + if (!demuxer_bytes && !m_demux_queue.empty()) + { -+ omx_demux_packet &demux_packet = m_demux_queue.front(); ++ mmal_demux_packet &demux_packet = m_demux_queue.front(); + if (space >= (unsigned int)demux_packet.size) + { + // need to lock here to retrieve an input buffer and pop the queue @@ -9013,9 +6921,9 @@ index dcbdb1e..3218b63 100644 + if (demuxer_bytes == 0) + buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END; + -+ #if defined(OMX_DEBUG_VERBOSE) ++ #if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d/%-6d dts:%.3f pts:%.3f flags:%x dts_queue(%d) ready_queue(%d) busy_queue(%d)", -+ CLASSNAME, __func__, buffer, iSize-demuxer_bytes, iSize, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, buffer->flags, m_dts_queue.size(), m_omx_output_ready.size(), m_omx_output_busy); ++ CLASSNAME, __func__, buffer, iSize-demuxer_bytes, iSize, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, buffer->flags, m_dts_queue.size(), m_output_ready.size(), m_output_busy); + #endif + status = mmal_port_send_buffer(m_dec_input, buffer); + if (status != MMAL_SUCCESS) @@ -9028,22 +6936,20 @@ index dcbdb1e..3218b63 100644 + { + m_decode_frame_number++; + m_startframe = true; -+ #ifdef DTS_QUEUE + if (m_drop_state) + { + m_droppedPics += m_deint ? 2:1; + } + else + { -+ // only push if we are successful with feeding OMX_EmptyThisBuffer -+ pthread_mutex_lock(&m_omx_output_mutex); ++ // only push if we are successful with feeding mmal ++ pthread_mutex_lock(&m_output_mutex); + m_dts_queue.push(dts); + if (m_deint) + m_dts_queue.push(DVD_NOPTS_VALUE); + //assert(m_dts_queue.size() < 5000); -+ pthread_mutex_unlock(&m_omx_output_mutex); ++ pthread_mutex_unlock(&m_output_mutex); + } -+ #endif + if (m_changed_count_dec != m_changed_count) + { + CLog::Log(LOGDEBUG, "%s::%s format changed frame:%d(%d)", CLASSNAME, __func__, m_changed_count_dec, m_changed_count); @@ -9055,21 +6961,19 @@ index dcbdb1e..3218b63 100644 + } + } + EDEINTERLACEMODE deinterlace_request = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; -+#if 0 -+ { -+ bool deinterlace = m_interlace_mode != MMAL_InterlaceProgressive; + -+ if (deinterlace_request == VS_DEINTERLACEMODE_OFF) -+ deinterlace = false; -+ else if (deinterlace_request == VS_DEINTERLACEMODE_FORCE) -+ deinterlace = true; ++ bool deinterlace = m_interlace_mode != MMAL_InterlaceProgressive; ++ ++ if (deinterlace_request == VS_DEINTERLACEMODE_OFF) ++ deinterlace = false; ++ else if (deinterlace_request == VS_DEINTERLACEMODE_FORCE) ++ deinterlace = true; ++ ++ if (!deinterlace && m_deint) ++ DestroyDeinterlace(); ++ else if (deinterlace && !m_deint) ++ CreateDeinterlace(); + -+ if (!deinterlace && m_deint) -+ DestroyDeinterlace(); -+ else if (deinterlace && !m_deint) -+ CreateDeinterlace(); -+ } -+#endif + if (buffer_to_free) + { + delete [] buffer_to_free; @@ -9085,29 +6989,26 @@ index dcbdb1e..3218b63 100644 + break; + } + int ret = 0; -+ if (!m_omx_output_ready.empty()) ++ if (!m_output_ready.empty()) + { -+ #if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s - got output picture:%d", CLASSNAME, __func__, m_omx_output_ready.size()); ++ #if defined(MMAL_DEBUG_VERBOSE) ++ CLog::Log(LOGDEBUG, "%s::%s - got output picture:%d", CLASSNAME, __func__, m_output_ready.size()); + #endif + ret |= VC_PICTURE; + } + if (mmal_queue_length(m_dec_input_pool->queue) > 0) - { -- CLog::Log(LOGERROR, "%s::%s - setting OMX_StateExecuting failed with omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); -- return omx_err; -+ #if defined(OMX_DEBUG_VERBOSE) ++ { ++ #if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s - got space for output:%d", CLASSNAME, __func__, mmal_queue_length(m_dec_input_pool->queue)); + #endif + ret |= VC_BUFFER; - } ++ } + return ret; +} + -+void COpenMaxVideo::Reset(void) ++void CMMALVideo::Reset(void) +{ -+ #if defined(OMX_DEBUG_VERBOSE) ++ #if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); + #endif + @@ -9127,14 +7028,12 @@ index dcbdb1e..3218b63 100644 + // blow all ready video frames + bool old_drop_state = m_drop_state; + SetDropState(true); -+#ifdef DTS_QUEUE -+ pthread_mutex_lock(&m_omx_output_mutex); ++ pthread_mutex_lock(&m_output_mutex); + while(!m_dts_queue.empty()) + m_dts_queue.pop(); + while (!m_demux_queue.empty()) + m_demux_queue.pop(); -+ pthread_mutex_unlock(&m_omx_output_mutex); -+#endif ++ pthread_mutex_unlock(&m_output_mutex); + if (!old_drop_state) + SetDropState(false); + @@ -9145,102 +7044,74 @@ index dcbdb1e..3218b63 100644 + m_droppedPics = 0; + m_decode_frame_number = 1; +} - -- //prime the omx output buffers. -- PrimeFillBuffers(); - -- return omx_err; -+void COpenMaxVideo::ReturnOpenMaxBuffer(COpenMaxVideoBuffer *buffer) ++ ++ ++void CMMALVideo::ReturnBuffer(CMMALVideoBuffer *buffer) +{ -+#if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s %p (%d)", CLASSNAME, __func__, buffer, m_omx_output_busy); ++#if defined(MMAL_DEBUG_VERBOSE) ++ CLog::Log(LOGDEBUG, "%s::%s %p (%d)", CLASSNAME, __func__, buffer, m_output_busy); +#endif + + mmal_buffer_header_release(buffer->mmal_buffer); - } - --// StopPlayback -- Stop video playback --OMX_ERRORTYPE COpenMaxVideo::StopDecoder(void) -+void COpenMaxVideo::Recycle(MMAL_BUFFER_HEADER_T *buffer) - { -- OMX_ERRORTYPE omx_err; -+#if defined(OMX_DEBUG_VERBOSE) ++} ++ ++void CMMALVideo::Recycle(MMAL_BUFFER_HEADER_T *buffer) ++{ ++#if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, buffer); +#endif - ++ + MMAL_STATUS_T status; + mmal_buffer_header_reset(buffer); + buffer->cmd = 0; - #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__); ++ #if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s Send buffer %p from pool to decoder output port %p dts_queue(%d) ready_queue(%d) busy_queue(%d)", CLASSNAME, __func__, buffer, m_dec_output, -+ m_dts_queue.size(), m_omx_output_ready.size(), m_omx_output_busy); - #endif -- // transition decoder component from executing to idle -- omx_err = SetStateForComponent(OMX_StateIdle); -- if (omx_err) ++ m_dts_queue.size(), m_output_ready.size(), m_output_busy); ++ #endif + status = mmal_port_send_buffer(m_dec_output, buffer); + if (status != MMAL_SUCCESS) - { -- CLog::Log(LOGERROR, "%s::%s - setting OMX_StateIdle failed with omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); -- return omx_err; ++ { + CLog::Log(LOGERROR, "%s::%s - Failed send buffer to decoder output port (status=0%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); + return; - } ++ } +} - -- // we can free our allocated port buffers in OMX_StateIdle state. -- // free OpenMax input buffers. -- FreeOMXInputBuffers(true); -- // free OpenMax output buffers. -- FreeOMXOutputBuffers(true); -+void COpenMaxVideo::ReleaseOpenMaxBuffer(COpenMaxVideoBuffer *buffer) ++ ++void CMMALVideo::ReleaseBuffer(CMMALVideoBuffer *buffer) +{ + // remove from busy list -+ pthread_mutex_lock(&m_omx_output_mutex); -+ assert(m_omx_output_busy > 0); -+ m_omx_output_busy--; -+ pthread_mutex_unlock(&m_omx_output_mutex); -+ ReturnOpenMaxBuffer(buffer); ++ pthread_mutex_lock(&m_output_mutex); ++ assert(m_output_busy > 0); ++ m_output_busy--; ++ pthread_mutex_unlock(&m_output_mutex); ++ ReturnBuffer(buffer); + bool done = false; -+ pthread_mutex_lock(&m_omx_output_mutex); -+ if (m_finished && !m_omx_output_busy) ++ pthread_mutex_lock(&m_output_mutex); ++ if (m_finished && !m_output_busy) + done = true; -+ pthread_mutex_unlock(&m_omx_output_mutex); ++ pthread_mutex_unlock(&m_output_mutex); + if (done) + m_myself.reset(); -+ #if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s %p (%p) dts_queue(%d) ready_queue(%d) busy_queue(%d) done:%d", CLASSNAME, __func__, buffer, buffer->mmal_buffer, m_dts_queue.size(), m_omx_output_ready.size(), m_omx_output_busy, done); ++ #if defined(MMAL_DEBUG_VERBOSE) ++ CLog::Log(LOGDEBUG, "%s::%s %p (%p) dts_queue(%d) ready_queue(%d) busy_queue(%d) done:%d", CLASSNAME, __func__, buffer, buffer->mmal_buffer, m_dts_queue.size(), m_output_ready.size(), m_output_busy, done); + #endif + delete buffer; +} - -- // transition decoder component from idle to loaded -- omx_err = SetStateForComponent(OMX_StateLoaded); -- if (omx_err) -- CLog::Log(LOGERROR, -- "%s::%s - setting OMX_StateLoaded failed with omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); -+bool COpenMaxVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) ++ ++bool CMMALVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) +{ -+ //CLog::Log(LOGDEBUG, "%s::%s - m_omx_output_busy=%d m_omx_output_ready.size()=%d", CLASSNAME, __func__, m_omx_output_busy, m_omx_output_ready.size()); -+ //CLog::Log(LOGDEBUG, "%s::%s - full: buffers:%d", CLASSNAME, __func__, m_omx_output_ready.size()); - -- return omx_err; -+ if (!m_omx_output_ready.empty()) ++ if (!m_output_ready.empty()) + { -+ COpenMaxVideoBuffer *buffer; ++ CMMALVideoBuffer *buffer; + // fetch a output buffer and pop it off the ready list -+ pthread_mutex_lock(&m_omx_output_mutex); -+ buffer = m_omx_output_ready.front(); -+ m_omx_output_ready.pop(); -+ pthread_mutex_unlock(&m_omx_output_mutex); ++ pthread_mutex_lock(&m_output_mutex); ++ buffer = m_output_ready.front(); ++ m_output_ready.pop(); ++ pthread_mutex_unlock(&m_output_mutex); + + assert(buffer->mmal_buffer); + memset(pDvdVideoPicture, 0, sizeof *pDvdVideoPicture); -+ pDvdVideoPicture->format = RENDER_FMT_OMXEGL; -+ pDvdVideoPicture->openMaxBuffer = buffer; ++ pDvdVideoPicture->format = RENDER_FMT_MMAL; ++ pDvdVideoPicture->MMALBuffer = buffer; + pDvdVideoPicture->color_range = 0; + pDvdVideoPicture->color_matrix = 4; + pDvdVideoPicture->iWidth = buffer->width ? buffer->width : m_decoded_width; @@ -9263,18 +7134,18 @@ index dcbdb1e..3218b63 100644 + pDvdVideoPicture->dts = buffer->dts; + pDvdVideoPicture->pts = buffer->mmal_buffer->pts == MMAL_TIME_UNKNOWN || buffer->mmal_buffer->pts == 0 ? DVD_NOPTS_VALUE : buffer->mmal_buffer->pts; + -+ pDvdVideoPicture->openMaxBuffer->Acquire(); ++ pDvdVideoPicture->MMALBuffer->Acquire(); + pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; -+#if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGINFO, "%s::%s dts:%.3f pts:%.3f flags:%x:%x openMaxBuffer:%p mmal_buffer:%p", CLASSNAME, __func__, ++#if defined(MMAL_DEBUG_VERBOSE) ++ CLog::Log(LOGINFO, "%s::%s dts:%.3f pts:%.3f flags:%x:%x MMALBuffer:%p mmal_buffer:%p", CLASSNAME, __func__, + pDvdVideoPicture->dts == DVD_NOPTS_VALUE ? 0.0 : pDvdVideoPicture->dts*1e-6, pDvdVideoPicture->pts == DVD_NOPTS_VALUE ? 0.0 : pDvdVideoPicture->pts*1e-6, -+ pDvdVideoPicture->iFlags, buffer->mmal_buffer->flags, pDvdVideoPicture->openMaxBuffer, pDvdVideoPicture->openMaxBuffer->mmal_buffer); ++ pDvdVideoPicture->iFlags, buffer->mmal_buffer->flags, pDvdVideoPicture->MMALBuffer, pDvdVideoPicture->MMALBuffer->mmal_buffer); +#endif + assert(!(buffer->mmal_buffer->flags & MMAL_BUFFER_HEADER_FLAG_DECODEONLY)); + } + else + { -+ CLog::Log(LOGERROR, "%s::%s - called but m_omx_output_ready is empty", CLASSNAME, __func__); ++ CLog::Log(LOGERROR, "%s::%s - called but m_output_ready is empty", CLASSNAME, __func__); + return false; + } + @@ -9286,41 +7157,58 @@ index dcbdb1e..3218b63 100644 + return true; +} + -+bool COpenMaxVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture) ++bool CMMALVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture) +{ -+#if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s - %p (%p)", CLASSNAME, __func__, pDvdVideoPicture->openMaxBuffer, pDvdVideoPicture->openMaxBuffer ? pDvdVideoPicture->openMaxBuffer->mmal_buffer : 0); -+#endif -+ if (pDvdVideoPicture->format == RENDER_FMT_OMXEGL) ++ if (pDvdVideoPicture->format == RENDER_FMT_MMAL) + { -+ pDvdVideoPicture->openMaxBuffer->Release(); ++#if defined(MMAL_DEBUG_VERBOSE) ++ CLog::Log(LOGDEBUG, "%s::%s - %p (%p)", CLASSNAME, __func__, pDvdVideoPicture->MMALBuffer, pDvdVideoPicture->MMALBuffer->mmal_buffer); ++#endif ++ pDvdVideoPicture->MMALBuffer->Release(); + } + memset(pDvdVideoPicture, 0, sizeof *pDvdVideoPicture); + return true; +} + -+bool COpenMaxVideo::GetCodecStats(double &pts, int &droppedPics) ++bool CMMALVideo::GetCodecStats(double &pts, int &droppedPics) +{ + pts = m_decoderPts; + droppedPics = m_droppedPics; + m_droppedPics = 0; -+#if defined(OMX_DEBUG_VERBOSE) ++#if defined(MMAL_DEBUG_VERBOSE) + //CLog::Log(LOGDEBUG, "%s::%s - pts:%.0f droppedPics:%d", CLASSNAME, __func__, pts, droppedPics); +#endif + return true; - } - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -index e06c41d..f931419 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -@@ -21,93 +21,136 @@ - - #if defined(HAVE_LIBOPENMAX) - --#include "OpenMax.h" --#include --#include ++} +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +new file mode 100644 +index 0000000..4b98be2 +--- /dev/null ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +@@ -0,0 +1,157 @@ ++#pragma once ++/* ++ * Copyright (C) 2010-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#if defined(HAS_MMAL) ++ +#include +#include +#include @@ -9340,75 +7228,46 @@ index e06c41d..f931419 100644 +#include "guilib/Geometry.h" +#include "rendering/RenderSystem.h" + -+class COpenMaxVideo; -+typedef boost::shared_ptr OpenMaxVideoPtr; - - // an omx egl video frame --typedef struct OpenMaxVideoBuffer { -- OMX_BUFFERHEADERTYPE *omx_buffer; -+class COpenMaxVideoBuffer ++class CMMALVideo; ++typedef boost::shared_ptr MMALVideoPtr; ++ ++// a mmal video frame ++class CMMALVideoBuffer +{ +public: -+ COpenMaxVideoBuffer(COpenMaxVideo *omv); -+ virtual ~COpenMaxVideoBuffer(); ++ CMMALVideoBuffer(CMMALVideo *omv); ++ virtual ~CMMALVideoBuffer(); + + MMAL_BUFFER_HEADER_T *mmal_buffer; - int width; - int height; ++ int width; ++ int height; + float m_aspect_ratio; - int index; ++ int index; + double dts; + uint32_t m_changed_count; + // reference counting -+ COpenMaxVideoBuffer* Acquire(); -+ long Release(); -+ COpenMaxVideo *m_omv; ++ CMMALVideoBuffer* Acquire(); ++ long Release(); ++ CMMALVideo *m_omv; + long m_refs; +private: +}; - -- // used for egl based rendering if active -- EGLImageKHR egl_image; -- GLuint texture_id; --} OpenMaxVideoBuffer; -- --class COpenMaxVideo : public COpenMax -+class COpenMaxVideo - { -+ typedef struct omx_demux_packet { ++ ++class CMMALVideo ++{ ++ typedef struct mmal_demux_packet { + uint8_t *buff; + int size; + double dts; + double pts; -+ } omx_demux_packet; ++ } mmal_demux_packet; + - public: - COpenMaxVideo(); - virtual ~COpenMaxVideo(); - - // Required overrides -- bool Open(CDVDStreamInfo &hints); -- void Close(void); -- int Decode(uint8_t *pData, int iSize, double dts, double pts); -- void Reset(void); -- bool GetPicture(DVDVideoPicture *pDvdVideoPicture); -- void SetDropState(bool bDrop); --protected: -- void QueryCodec(void); -- OMX_ERRORTYPE PrimeFillBuffers(void); -- OMX_ERRORTYPE AllocOMXInputBuffers(void); -- OMX_ERRORTYPE FreeOMXInputBuffers(bool wait); -- OMX_ERRORTYPE AllocOMXOutputBuffers(void); -- OMX_ERRORTYPE FreeOMXOutputBuffers(bool wait); -- static void CallbackAllocOMXEGLTextures(void*); -- OMX_ERRORTYPE AllocOMXOutputEGLTextures(void); -- static void CallbackFreeOMXEGLTextures(void*); -- OMX_ERRORTYPE FreeOMXOutputEGLTextures(bool wait); -- -- // TODO Those should move into the base class. After start actions can be executed by callbacks. -- OMX_ERRORTYPE StartDecoder(void); -- OMX_ERRORTYPE StopDecoder(void); -+ virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenMaxVideoPtr myself); ++public: ++ CMMALVideo(); ++ virtual ~CMMALVideo(); ++ ++ // Required overrides ++ virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVideoPtr myself); + virtual void Dispose(void); + virtual int Decode(uint8_t *pData, int iSize, double dts, double pts); + virtual void Reset(void); @@ -9418,15 +7277,9 @@ index e06c41d..f931419 100644 + virtual void SetDropState(bool bDrop); + virtual const char* GetName(void) { return (const char*)m_pFormatName; } + virtual bool GetCodecStats(double &pts, int &droppedPics); - - // OpenMax decoder callback routines. -- virtual OMX_ERRORTYPE DecoderEventHandler(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, -- OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData); -- virtual OMX_ERRORTYPE DecoderEmptyBufferDone( -- OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBuffer); -- virtual OMX_ERRORTYPE DecoderFillBufferDone( -- OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBufferHeader); -+ void ReleaseOpenMaxBuffer(COpenMaxVideoBuffer *buffer); ++ ++ // MMAL decoder callback routines. ++ void ReleaseBuffer(CMMALVideoBuffer *buffer); + void Recycle(MMAL_BUFFER_HEADER_T *buffer); + + // MMAL decoder callback routines. @@ -9434,64 +7287,41 @@ index e06c41d..f931419 100644 + void dec_control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer); + uint32_t m_changed_count; + uint32_t m_changed_count_dec; - -- // EGL Resources -- EGLDisplay m_egl_display; -- EGLContext m_egl_context; ++ +protected: + void QueryCodec(void); -+ void ReturnOpenMaxBuffer(COpenMaxVideoBuffer *buffer); ++ void ReturnBuffer(CMMALVideoBuffer *buffer); + bool CreateDeinterlace(); + bool DestroyDeinterlace(); - - // Video format -- DVDVideoPicture m_videobuffer; - bool m_drop_state; - int m_decoded_width; - int m_decoded_height; ++ ++ // Video format ++ bool m_drop_state; ++ int m_decoded_width; ++ int m_decoded_height; + unsigned int m_egl_buffer_count; + bool m_finished; + float m_aspect_ratio; + bool m_forced_aspect_ratio; + const char *m_pFormatName; -+ OpenMaxVideoPtr m_myself; - - std::queue m_dts_queue; - std::queue m_demux_queue; - -- // OpenMax input buffers (demuxer packets) -- pthread_mutex_t m_omx_input_mutex; -- std::queue m_omx_input_avaliable; -- std::vector m_omx_input_buffers; -- bool m_omx_input_eos; -- int m_omx_input_port; -- //sem_t *m_omx_flush_input; -- CEvent m_input_consumed_event; -- - // OpenMax output buffers (video frames) - pthread_mutex_t m_omx_output_mutex; -- std::queue m_omx_output_busy; -- std::queue m_omx_output_ready; -- std::vector m_omx_output_buffers; -- bool m_omx_output_eos; -- int m_omx_output_port; -- //sem_t *m_omx_flush_output; -- -- bool m_portChanging; -- -- volatile bool m_videoplayback_done; -+ int m_omx_output_busy; -+ std::queue m_omx_output_ready; -+ std::vector m_omx_output_buffers; ++ MMALVideoPtr m_myself; + -+ // initialize OpenMax and get decoder component ++ std::queue m_dts_queue; ++ std::queue m_demux_queue; ++ ++ // mmal output buffers (video frames) ++ pthread_mutex_t m_output_mutex; ++ int m_output_busy; ++ std::queue m_output_ready; ++ std::vector m_output_buffers; ++ ++ // initialize mmal and get decoder component + bool Initialize( const CStdString &decoder_name); + void PortSettingsChanged(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer); + bool SendCodecConfigData(); + + CDVDStreamInfo m_hints; + // Components -+ //MMAL_INTERLACETYPE_T m_interlace_mode; ++ MMAL_INTERLACETYPE_T m_interlace_mode; + bool m_startframe; + unsigned int m_decode_frame_number; + double m_decoderPts; @@ -9509,33 +7339,68 @@ index e06c41d..f931419 100644 + + MMAL_FOURCC_T m_codingType; + bool change_dec_output_format(); - }; ++}; ++ ++// defined(HAS_MMAL) ++#endif +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in +index 50dc8b7..6f5d3e8 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in +@@ -37,6 +37,11 @@ ifeq (@USE_LIBSTAGEFRIGHT@,1) + SRCS += DVDVideoCodecStageFright.cpp + endif - // defined(HAVE_LIBOPENMAX) ++ifeq (@USE_MMAL@,1) ++SRCS += MMALCodec.cpp ++SRCS += DVDVideoCodecMMAL.cpp ++endif ++ + LIB=Video.a + + include @abs_top_srcdir@/Makefile.include diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 3bfa7f1..8b60288 100644 +index d3d37d1..374f4bd 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -194,7 +194,7 @@ bool CDVDPlayerVideo::OpenStream( CDVDStreamInfo &hint ) - if(hint.flags & AV_DISPOSITION_ATTACHED_PIC) - return false; - -- CLog::Log(LOGNOTICE, "Creating video codec with codec id: %i", hint.codec); -+ CLog::Log(LOGNOTICE, "Creating video codec with codec id: %i %dx%d", hint.codec, hint.width, hint.height); - CDVDVideoCodec* codec = CDVDFactoryCodec::CreateVideoCodec(hint, surfaces, formats); - if(!codec) - { +@@ -1016,6 +1016,7 @@ static std::string GetRenderFormatName(ERenderFormat format) + case RENDER_FMT_BYPASS: return "BYPASS"; + case RENDER_FMT_MEDIACODEC:return "MEDIACODEC"; + case RENDER_FMT_IMXMAP: return "IMXMAP"; ++ case RENDER_FMT_MMAL: return "MMAL"; + case RENDER_FMT_NONE: return "NONE"; + } + return "UNKNOWN"; -From 4bbd1790c53efb19d551d13e366cdd00242d06e1 Mon Sep 17 00:00:00 2001 +From 2ee235762c433f3415a57d1be9b458bc8391226d Mon Sep 17 00:00:00 2001 From: popcornmix -Date: Tue, 12 Aug 2014 00:31:36 +0100 -Subject: [PATCH 33/77] [omxcodec] Fix for stills with hardware codec +Date: Wed, 10 Sep 2014 22:07:21 +0100 +Subject: [PATCH 30/82] [mmal] Allow mmal codec for dvd stills +--- + xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 4 ++++ + 1 file changed, 4 insertions(+) -From 3e0e029ac15454d5a662f37ef875e8fc33a518cc Mon Sep 17 00:00:00 2001 +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp +index 6ef941f..116ff8a 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp +@@ -192,6 +192,10 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne + #endif + CLog::Log(LOGDEBUG, "CDVDFactoryCodec: compiled in hardware support: %s", hwSupport.c_str()); + ++#if defined(HAS_MMAL) ++ // mmal can handle dvd playback including stills ++ if (!CSettings::Get().GetBool("videoplayer.usemmal")) ++#endif + if (hint.stills && (hint.codec == AV_CODEC_ID_MPEG2VIDEO || hint.codec == AV_CODEC_ID_MPEG1VIDEO)) + { + // If dvd is an mpeg2 and hint.stills + +From 75cb478f97c533fd61d4fb0a8f473baf32bb703c Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 2 Aug 2014 17:47:38 +0100 -Subject: [PATCH 34/77] [VideoReferenceClock] Add OMX support +Subject: [PATCH 32/82] [VideoReferenceClock] Add OMX support --- xbmc/linux/RBP.cpp | 34 ++++++++++++++++++++++++ @@ -9734,10 +7599,10 @@ index 6027031..2dabac1 100644 }; -From 368010b61ed9b84fd9ad667cbae70f1f418ca016 Mon Sep 17 00:00:00 2001 +From 3b52bbd76f7a37530d3c2f6ae82d50164e38ca0b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 12 Aug 2014 00:03:18 +0100 -Subject: [PATCH 35/77] videoreferenceclock: Boost priority +Subject: [PATCH 33/82] videoreferenceclock: Boost priority --- xbmc/video/VideoReferenceClock.cpp | 3 +++ @@ -9758,10 +7623,10 @@ index 916a15c..c491d29 100644 //register callback m_D3dCallback.Reset(); -From 28cd39d1b3695fdd464e7a5b200817115be4e5b1 Mon Sep 17 00:00:00 2001 +From c0a5c4353a8b4705a2a47fade882a6d642bec4f5 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 5 Feb 2014 11:46:33 +0000 -Subject: [PATCH 36/77] [rbp/settings] Allow av sync type to be enabled +Subject: [PATCH 34/82] [rbp/settings] Allow av sync type to be enabled It works for dvdplayer --- @@ -9769,7 +7634,7 @@ It works for dvdplayer 1 file changed, 7 deletions(-) diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml -index 28e68eb..60086d8 100644 +index bbb2076..ce5c423 100644 --- a/system/settings/rbp.xml +++ b/system/settings/rbp.xml @@ -1,13 +1,6 @@ @@ -9787,11 +7652,10 @@ index 28e68eb..60086d8 100644 false - -From 162a1d6ee9b5603e6df798289d6843380e3a5cf0 Mon Sep 17 00:00:00 2001 +From 1f0d35f1c1a27a09e3a83ffc3d3a72258d18c254 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 16 Apr 2014 21:18:06 +0100 -Subject: [PATCH 41/77] [omxplayer] Don't propagate 3d flags based on supported +Subject: [PATCH 39/82] [omxplayer] Don't propagate 3d flags based on supported 3d modes --- @@ -9844,10 +7708,10 @@ index 2c25fd9..c2bd788 100644 unsigned int iDisplayWidth = width; unsigned int iDisplayHeight = height; -From b4b030a3c528926f1a66c22e4a03a5a69aac5f94 Mon Sep 17 00:00:00 2001 +From 9e2ab2ce2b563fa459bc6a37e267ee34147b36aa Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 17 Apr 2014 13:00:52 +0100 -Subject: [PATCH 42/77] [graphics] Don't set stereo mode based on resolution +Subject: [PATCH 40/82] [graphics] Don't set stereo mode based on resolution The resolution change should follow stereo mode --- @@ -9905,10 +7769,10 @@ index 5bffdf5..4be1c8b 100644 m_iScreenWidth = info_mod.iWidth; -From b0d51a841696f2a2ecc303ef5bd233f21d6d0f42 Mon Sep 17 00:00:00 2001 +From d91488c3547dae3de14c35793683c8943354824a Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 17 Apr 2014 13:01:51 +0100 -Subject: [PATCH 43/77] [graphics] Allow switching to a more suitable 3D +Subject: [PATCH 41/82] [graphics] Allow switching to a more suitable 3D resolution --- @@ -9994,10 +7858,10 @@ index 0a27643..ef5bc74 100644 void ResetOverscan(RESOLUTION_INFO &resinfo); void ResetScreenParameters(RESOLUTION res); -From 7278fb51a95d2f6d07cd4bca238d0a148887c5c3 Mon Sep 17 00:00:00 2001 +From 0bf86871ae90bd5754a6773c8446c91eb2b931ed Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 17 Apr 2014 13:38:55 +0100 -Subject: [PATCH 44/77] [3D] Support switching to 3D resolutions +Subject: [PATCH 42/82] [3D] Support switching to 3D resolutions Include matching 3D flags (SBS/TAB) in the score of a resolution to switch to, to enable switching to 3d modes. Also remove the old code that treated 3D modes differently when assigning a score. @@ -10079,10 +7943,10 @@ index 83c3adb..8076e76 100644 return current; } -From d9820ca27cef34a9dc0025487290e36768f0fbd4 Mon Sep 17 00:00:00 2001 +From f7ed2957a4f5efe3f21c8bcf6537c90c94be8c53 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 23 Apr 2014 00:05:07 +0100 -Subject: [PATCH 45/77] [graphics] Make pixel ratio for 3d modes consistent +Subject: [PATCH 43/82] [graphics] Make pixel ratio for 3d modes consistent Note: Use the stored stereo flags from lists of resolutions. Use current stereo mode for current resolution. @@ -10285,10 +8149,10 @@ index c58c28a..bf1e589 100644 AddUniqueResolution(res2, resolutions); -From 19cb0dcb9e872daf649154166104d0ee6c857e75 Mon Sep 17 00:00:00 2001 +From 65d3b36df1cd3ae2f82e985f1b28573505dba8c0 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 10 Aug 2014 16:45:16 +0100 -Subject: [PATCH 46/77] filesystem: Make support of browsing into archives +Subject: [PATCH 44/82] filesystem: Make support of browsing into archives optional The ability to browse, scan and play content in archives can cause problems on low powered/low memory devices. @@ -10304,10 +8168,10 @@ Add a settings option to enable this feature and default to disabled on Pi 4 files changed, 29 insertions(+) diff --git a/language/English/strings.po b/language/English/strings.po -index ade855e..325ed2d 100755 +index 03b4146..0631393 100755 --- a/language/English/strings.po +++ b/language/English/strings.po -@@ -15874,3 +15874,13 @@ msgstr "" +@@ -15890,3 +15890,13 @@ msgstr "" msgctxt "#37030" msgid "Unlimited" msgstr "" @@ -10322,7 +8186,7 @@ index ade855e..325ed2d 100755 +msgid "Allow viewing and playing files in archives (e.g. zip, rar)" +msgstr "" diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml -index 60086d8..b65136a 100644 +index ce5c423..5526931 100644 --- a/system/settings/rbp.xml +++ b/system/settings/rbp.xml @@ -1,5 +1,15 @@ @@ -10342,7 +8206,7 @@ index 60086d8..b65136a 100644 diff --git a/system/settings/settings.xml b/system/settings/settings.xml -index af05fb7..f87373a 100644 +index 547d214..92d05aa 100644 --- a/system/settings/settings.xml +++ b/system/settings/settings.xml @@ -226,6 +226,11 @@ @@ -10387,11 +8251,10 @@ index 2fd8777..3b294cd 100644 { // XBMC Smart playlist - just XML renamed to XSP // read the name of the playlist in - -From 860ade05ad1104e01a1266cd5cf0231e9332fc4a Mon Sep 17 00:00:00 2001 +From 3364a36b6a8dcc9671a288eefef44ad492887207 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 11 Aug 2014 22:56:13 +0100 -Subject: [PATCH 48/77] [omxplayer] Add acceleration option to choose +Subject: [PATCH 46/82] [omxplayer] Add acceleration option to choose omxplayer/dvdplayer automatically --- @@ -10401,10 +8264,10 @@ Subject: [PATCH 48/77] [omxplayer] Add acceleration option to choose 3 files changed, 77 insertions(+) diff --git a/language/English/strings.po b/language/English/strings.po -index 325ed2d..1b13a9b 100755 +index 0631393..38a2388 100755 --- a/language/English/strings.po +++ b/language/English/strings.po -@@ -15884,3 +15884,13 @@ msgstr "" +@@ -15900,3 +15900,13 @@ msgstr "" msgctxt "#37032" msgid "Allow viewing and playing files in archives (e.g. zip, rar)" msgstr "" @@ -10419,10 +8282,10 @@ index 325ed2d..1b13a9b 100755 +msgid "Uses codec information and audio setting to choose dvdplayer or omxplayer as appropriate" +msgstr "" diff --git a/system/settings/settings.xml b/system/settings/settings.xml -index f87373a..bd7858e 100644 +index 92d05aa..16edb6f 100644 --- a/system/settings/settings.xml +++ b/system/settings/settings.xml -@@ -757,6 +757,15 @@ +@@ -754,6 +754,15 @@ true @@ -10439,7 +8302,7 @@ index f87373a..bd7858e 100644 HAS_OMXPLAYER diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp -index de49617..b274756 100644 +index c2654c3b..6547880 100644 --- a/xbmc/cores/dvdplayer/DVDPlayer.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp @@ -490,6 +490,62 @@ void CSelectionStreams::Update(CDVDInputStream* input, CDVDDemux* demuxer) @@ -10515,10 +8378,10 @@ index de49617..b274756 100644 // allow renderer to switch to fullscreen if requested m_dvdPlayerVideo->EnableFullscreen(m_PlayerOptions.fullscreen); -From 03adf05c7efb63bd728dd31dbe7eeac7da0e247a Mon Sep 17 00:00:00 2001 +From 1306ab6444aef4543629b8ae4f7b665f841dc395 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 12 Aug 2014 16:51:18 +0100 -Subject: [PATCH 49/77] AE: Add some logging for suspend/resume +Subject: [PATCH 47/82] AE: Add some logging for suspend/resume --- xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp | 5 +++++ @@ -10526,10 +8389,10 @@ Subject: [PATCH 49/77] AE: Add some logging for suspend/resume 2 files changed, 7 insertions(+) diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp -index fe5e893..3e89523 100644 +index de07de5..9d641c2 100644 --- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp +++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp -@@ -345,6 +345,7 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg) +@@ -346,6 +346,7 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg) switch (signal) { case CActiveAEControlProtocol::INIT: @@ -10537,7 +8400,7 @@ index fe5e893..3e89523 100644 m_extError = false; m_sink.EnumerateSinkList(false); LoadSettings(); -@@ -430,6 +431,7 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg) +@@ -431,6 +432,7 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg) m_extDeferData = true; return; case CActiveAEControlProtocol::SUSPEND: @@ -10545,7 +8408,7 @@ index fe5e893..3e89523 100644 UnconfigureSink(); m_stats.SetSuspended(true); m_state = AE_TOP_CONFIGURED_SUSPEND; -@@ -655,6 +657,7 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg) +@@ -656,6 +658,7 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg) CLog::Log(LOGDEBUG,"CActiveAE - display reset event"); displayReset = true; case CActiveAEControlProtocol::INIT: @@ -10553,7 +8416,7 @@ index fe5e893..3e89523 100644 m_extError = false; if (!displayReset) { -@@ -2332,12 +2335,14 @@ void CActiveAE::Shutdown() +@@ -2333,12 +2336,14 @@ void CActiveAE::Shutdown() bool CActiveAE::Suspend() { @@ -10589,10 +8452,10 @@ index 7e85441..a73dd0a 100644 } -From 7c39ab7b84943aeace23e0488b6f21b73ffc1653 Mon Sep 17 00:00:00 2001 +From c1542bb7cf46439c56a471ac2c01ee3f5ffdc25c Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 9 Jul 2014 22:45:43 +0100 -Subject: [PATCH 50/77] [rbp] Make cachemembuffersize default depend on memory +Subject: [PATCH 48/82] [rbp] Make cachemembuffersize default depend on memory size --- @@ -10631,10 +8494,10 @@ index 11376fc..b67fbb1 100644 response[sizeof(response) - 1] = '\0'; CLog::Log(LOGNOTICE, "Config:\n%s", response); diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp -index 4af3c7a..c003c5a 100644 +index 237e903..8e32a68 100644 --- a/xbmc/settings/AdvancedSettings.cpp +++ b/xbmc/settings/AdvancedSettings.cpp -@@ -364,7 +364,12 @@ void CAdvancedSettings::Initialize() +@@ -363,7 +363,12 @@ void CAdvancedSettings::Initialize() m_measureRefreshrate = false; @@ -10648,10 +8511,10 @@ index 4af3c7a..c003c5a 100644 // the following setting determines the readRate of a player data // as multiply of the default data read rate -From 8f2f06af909adfada148cca51e9195b9461a037c Mon Sep 17 00:00:00 2001 +From 26449067777a0df7389ff82ecc3410e2226b90d5 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 16 Jun 2014 19:06:00 +0100 -Subject: [PATCH 53/77] [experimental] Disable quiet-noise generation +Subject: [PATCH 50/82] [experimental] Disable quiet-noise generation --- xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp | 2 ++ @@ -10678,10 +8541,10 @@ index 488a0df..d9f4a43 100644 void CActiveAESink::SetSilenceTimer() -From 0a2b78734e0e04fbc18edbfd7efc0813c98715ae Mon Sep 17 00:00:00 2001 +From f778f20535652c690940cb59cea744f4396c94aa Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 30 May 2014 14:58:43 +0100 -Subject: [PATCH 54/77] [settings] Experiment: Report DESKTOP resolution in +Subject: [PATCH 51/82] [settings] Experiment: Report DESKTOP resolution in video settings --- @@ -10689,10 +8552,10 @@ Subject: [PATCH 54/77] [settings] Experiment: Report DESKTOP resolution in 1 file changed, 3 insertions(+) diff --git a/xbmc/settings/DisplaySettings.cpp b/xbmc/settings/DisplaySettings.cpp -index bb31f15..eae549b 100644 +index e43445b..a5e4dc7 100644 --- a/xbmc/settings/DisplaySettings.cpp +++ b/xbmc/settings/DisplaySettings.cpp -@@ -650,6 +650,9 @@ void CDisplaySettings::SettingOptionsResolutionsFiller(const CSetting *setting, +@@ -655,6 +655,9 @@ void CDisplaySettings::SettingOptionsResolutionsFiller(const CSetting *setting, vector resolutions = g_Windowing.ScreenResolutions(info.iScreen, info.fRefreshRate); for (vector::const_iterator resolution = resolutions.begin(); resolution != resolutions.end(); ++resolution) { @@ -10703,10 +8566,10 @@ index bb31f15..eae549b 100644 StringUtils::Format("%dx%d%s", resolution->width, resolution->height, ModeFlagsToString(resolution->flags, false).c_str()), -From 069d3bbd3f6fb99311923b22001faa2e1d53b106 Mon Sep 17 00:00:00 2001 +From 12748588e74711da5d596b1aff7177a030179ec3 Mon Sep 17 00:00:00 2001 From: macrule Date: Thu, 11 Apr 2013 18:24:42 +0200 -Subject: [PATCH 55/77] Added some vc_tv_* functions that were missing in +Subject: [PATCH 52/82] Added some vc_tv_* functions that were missing in DllBCM. --- @@ -10741,10 +8604,10 @@ index b92fdb8..9c7e293 100644 HDMI_INTERLACED_T scan_mode, EDID_MODE_MATCH_FLAG_T match_flags) { return ::vc_tv_hdmi_power_on_best(width, height, frame_rate, scan_mode, match_flags); }; -From f0c6be3fc275077081157e3bece35c6718c57559 Mon Sep 17 00:00:00 2001 +From 470654ed88a0c1b4246d37ce1dec26d79a21b20a Mon Sep 17 00:00:00 2001 From: macrule Date: Thu, 11 Apr 2013 18:29:03 +0200 -Subject: [PATCH 56/77] Added private utility function to map a float display +Subject: [PATCH 53/82] Added private utility function to map a float display aspect, to the respective SDTV_ASPECT_* enum value. --- @@ -10782,10 +8645,10 @@ index bf1e589..518a87d 100644 bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &resolutions) -From 24cd5274f8465c64f3f984fa5a1ada139f1d762a Mon Sep 17 00:00:00 2001 +From 9264b64ba64cfff82e23b119c41ac17446b5f638 Mon Sep 17 00:00:00 2001 From: macrule Date: Thu, 11 Apr 2013 19:50:58 +0200 -Subject: [PATCH 57/77] Changed SDTV resolutions to be treated similarly to +Subject: [PATCH 54/82] Changed SDTV resolutions to be treated similarly to HDMI resolutions in SetNativeResolution. This means that the SDTV interface is powered up and set to the right mode. @@ -10882,10 +8745,10 @@ index 59401f5..a0acb1a 100644 int m_width; int m_height; -From f068e06b096f1d09070abe714dcb9da4aeb41130 Mon Sep 17 00:00:00 2001 +From 9738a4a5e0d4f25af9c06a7e47a67908c7115908 Mon Sep 17 00:00:00 2001 From: macrule Date: Thu, 11 Apr 2013 19:54:59 +0200 -Subject: [PATCH 58/77] Added methods SuspendVideoOutput() and +Subject: [PATCH 55/82] Added methods SuspendVideoOutput() and ResumeVideoOutput() to CRBP class, which can be used to power down the Raspberry PI's video interface, and restore it at a later point. @@ -10949,10 +8812,10 @@ index 9dc39d5..ca36082 100644 CEGLNativeTypeRaspberryPI::CEGLNativeTypeRaspberryPI() { -From 35cc5ae9e5e5914c0084a79cc6bd41853a59e086 Mon Sep 17 00:00:00 2001 +From 252fa0c4408bd8da64704f98b94c8e67736ae5e0 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 11 Aug 2013 15:03:36 +0100 -Subject: [PATCH 59/77] PowerManager (and its IPowerSyscall instance) now gets +Subject: [PATCH 56/82] PowerManager (and its IPowerSyscall instance) now gets called from CApplication::OnKey() and can process and suppress key presses. This is a requirement to implement a virtual sleep state. @@ -11045,10 +8908,10 @@ index 0b1f10a..e42b143 100644 void OnSleep(); void OnWake(); -From 4ba5eadbae5505f85254ad58f3abb0a8a6d7ff62 Mon Sep 17 00:00:00 2001 +From 689876eb5e09acbf35ad547c4ec5d6874d5965b3 Mon Sep 17 00:00:00 2001 From: macrule Date: Wed, 17 Apr 2013 13:23:01 +0200 -Subject: [PATCH 60/77] Added CPowerSyscallVirtualSleep class, which acts as a +Subject: [PATCH 57/82] Added CPowerSyscallVirtualSleep class, which acts as a base class for devices that have no native standby mode, and need to fake it in some way. @@ -11224,10 +9087,10 @@ index 0000000..ef6e682 + +#endif // _POWER_SYSCALL_VIRTUAL_SLEEP_H_ -From 53a5805f8e8e2d24b35a50c8a6733898d4a5a375 Mon Sep 17 00:00:00 2001 +From 7806d8ddcb8c92ae69af9021305969c0c17b4fe7 Mon Sep 17 00:00:00 2001 From: macrule Date: Wed, 17 Apr 2013 13:24:22 +0200 -Subject: [PATCH 61/77] Added power management support for the Raspberry Pi. +Subject: [PATCH 58/82] Added power management support for the Raspberry Pi. Since it doesn't support true standby, we fake it by turning video on or off, and ignoring remote inputs during the standby phase. @@ -11373,10 +9236,10 @@ index 0000000..fd1d67c + +#endif // _RASPBERRY_PI_POWER_SYSCALL_H_ -From 514c8d47d50d43d065ec77ef3f7fa34e3d465a9b Mon Sep 17 00:00:00 2001 +From 0b1c63d165e31f4509e2eb87df682f946699df3b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 3 Mar 2014 16:16:29 +0000 -Subject: [PATCH 62/77] [power] hack - don't kill lirc or cec +Subject: [PATCH 59/82] [power] hack - don't kill lirc or cec --- xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 37 +++++++++++++++++++++++ @@ -11460,10 +9323,10 @@ index 2d8c750..901f449 100644 CBuiltins::Execute("LIRC.Start"); #endif -From 3e41f1b5cd582be0b60a630cc00418cdbed3825a Mon Sep 17 00:00:00 2001 +From 0a80339f64e206cd1364a58e203958aeb649b9d1 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 3 Mar 2014 16:47:54 +0000 -Subject: [PATCH 63/77] [power] hack - wake on any action +Subject: [PATCH 60/82] [power] hack - wake on any action --- xbmc/powermanagement/PowerSyscallVirtualSleep.cpp | 6 +++--- @@ -11492,10 +9355,10 @@ index 6a1e47b..a717a09 100644 if(VirtualWake()) { -From 02a91126f1e132933a7e51e6d667a6824f81379f Mon Sep 17 00:00:00 2001 +From a9df2c2944c5131c82567b46de2c0364cee1e215 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 3 Mar 2014 17:30:07 +0000 -Subject: [PATCH 64/77] [power] hack - Make suspend toggle suspend state +Subject: [PATCH 61/82] [power] hack - Make suspend toggle suspend state --- xbmc/powermanagement/PowerSyscallVirtualSleep.cpp | 5 +++++ @@ -11518,10 +9381,10 @@ index a717a09..d39c3ed 100644 return false; } -From 3c3d10199293eaf3cba04ca241c9dfb77a9c5475 Mon Sep 17 00:00:00 2001 +From 91c03000f2cd251aecdae4263b01403308e37976 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 4 Mar 2014 19:33:44 +0000 -Subject: [PATCH 65/77] [power] Add back in powerdown and reboot +Subject: [PATCH 62/82] [power] Add back in powerdown and reboot --- .../linux/RaspberryPIPowerSyscall.cpp | 34 ++++++++++++++++++++++ @@ -11599,10 +9462,10 @@ index fd1d67c..062132e 100644 virtual bool CanReboot() { return true; } -From 5187a8e86050670abd3669590383f2f9958eef5d Mon Sep 17 00:00:00 2001 +From 665b6d3e2bab90895727c4ff62856fbe120da426 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 26 Apr 2014 17:27:52 +0100 -Subject: [PATCH 70/77] [cec] Don't suspend pi on tv switch off - it can't wake +Subject: [PATCH 67/82] [cec] Don't suspend pi on tv switch off - it can't wake up --- @@ -11623,10 +9486,10 @@ index a906628..9b5271a 100644 -From 63179060ddac85446753a50f4b8a92e899cbc944 Mon Sep 17 00:00:00 2001 +From ef14f6b4fa9be071c4989e3f8668f39249ed29c2 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 18 Aug 2014 19:09:32 +0100 -Subject: [PATCH 71/77] rbp: Use new dispmanx function for vsync callbacks +Subject: [PATCH 68/82] rbp: Use new dispmanx function for vsync callbacks --- xbmc/linux/RBP.cpp | 85 ++++++++++++++----------- @@ -11838,10 +9701,10 @@ index ca36082..4b74ea0 100644 } DLOG("CEGLNativeTypeRaspberryPI::DestroyDispmaxWindow\n"); -From d929ed74688c7b51f0281f9d9641581c4c687180 Mon Sep 17 00:00:00 2001 +From ed6cb3734548b385c04f753bdd06b37fbada90f5 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 19 Aug 2014 17:56:45 +0100 -Subject: [PATCH 72/77] Revert "rbp: Use new dispmanx function for vsync +Subject: [PATCH 69/82] Revert "rbp: Use new dispmanx function for vsync callbacks" This reverts commit afbf8fbceaa6649fb4a6bbd9a1cee6087590412b. @@ -12055,37 +9918,10 @@ index 4b74ea0..ca36082 100644 } DLOG("CEGLNativeTypeRaspberryPI::DestroyDispmaxWindow\n"); -From 587a18598ba8d407646394b8afa8e0aa66602cc8 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 20 Aug 2014 21:05:05 +0100 -Subject: [PATCH 73/77] [omxplayer] Use 0 for video timestamps when using - trickplay - ---- - xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp -index c2bd788..2c0a86f 100644 ---- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp -+++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp -@@ -506,7 +506,10 @@ void OMXPlayerVideo::Process() - if (pts != DVD_NOPTS_VALUE) - pts += m_iVideoDelay; - -- m_omxVideo.Decode(pPacket->pData, pPacket->iSize, pts); -+ if (m_speed != DVD_PLAYSPEED_NORMAL && m_speed != DVD_PLAYSPEED_PAUSE) -+ m_omxVideo.Decode(pPacket->pData, pPacket->iSize, 0.0); -+ else -+ m_omxVideo.Decode(pPacket->pData, pPacket->iSize, pts); - Output(pts, bRequestDrop); - if(pts != DVD_NOPTS_VALUE) - m_iCurrentPts = pts; - -From e2ed2cb0b3745661b74a1fdb8facaa9eaecd07b0 Mon Sep 17 00:00:00 2001 +From 5d99df1b9669fc9990a0f8e95fd78e60fbbdc46e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 27 Jun 2014 00:01:05 +0100 -Subject: [PATCH 74/77] [rbp] Resume video output on startup +Subject: [PATCH 70/82] [rbp] Resume video output on startup --- xbmc/linux/RBP.cpp | 3 +++ @@ -12106,10 +9942,10 @@ index 2ff6078..34e0108 100644 m_omx_image_init = true; return true; -From 1873caef5f16969652483140ce5b2365f3cc9887 Mon Sep 17 00:00:00 2001 +From 66c86059637ce3a9606ffac2fad84984987db1c6 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 16 Aug 2014 21:01:42 +0100 -Subject: [PATCH 75/77] omxrender: Hacks to reduce GUI rendering rate when +Subject: [PATCH 71/82] omxrender: Hacks to reduce GUI rendering rate when playing video --- @@ -12119,10 +9955,10 @@ Subject: [PATCH 75/77] omxrender: Hacks to reduce GUI rendering rate when 3 files changed, 60 insertions(+) diff --git a/language/English/strings.po b/language/English/strings.po -index 1b13a9b..06d425d 100755 +index 38a2388..8252473 100755 --- a/language/English/strings.po +++ b/language/English/strings.po -@@ -15894,3 +15894,30 @@ msgstr "" +@@ -15910,3 +15910,30 @@ msgstr "" msgctxt "#37034" msgid "Uses codec information and audio setting to choose dvdplayer or omxplayer as appropriate" msgstr "" @@ -12154,11 +9990,11 @@ index 1b13a9b..06d425d 100755 +msgid "24 fps" +msgstr "" diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml -index b65136a..9269dec 100644 +index 5526931..634aa4f 100644 --- a/system/settings/rbp.xml +++ b/system/settings/rbp.xml -@@ -20,6 +20,22 @@ - false +@@ -28,6 +28,22 @@ + + @@ -12209,93 +10045,702 @@ index e68c80f..6a280d5 100644 int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync"); -From eab1aae1889ddc167e7fb5702a750a3f9c492f77 Mon Sep 17 00:00:00 2001 +From b48a641ca4c6e99bcd9de75e18bcda0af663229e Mon Sep 17 00:00:00 2001 From: popcornmix -Date: Fri, 29 Aug 2014 18:11:14 +0100 -Subject: [PATCH 76/77] omxcodec: experimental: enable deinterlace +Date: Tue, 9 Sep 2014 12:04:26 +0100 +Subject: [PATCH 72/82] egl: Treat unknown display aspect ratio as square pixel --- - xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp | 11 ++++------- - xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h | 2 +- - 2 files changed, 5 insertions(+), 8 deletions(-) + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -index 3218b63..84799e2 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -@@ -115,7 +115,7 @@ COpenMaxVideo::COpenMaxVideo() - m_finished = false; - m_pFormatName = "mmal-xxxx"; +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +index ca36082..1529045 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +@@ -493,7 +493,7 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r + m_desktopRes.iScreenWidth = tv_state.display.hdmi.width; + m_desktopRes.iScreenHeight= tv_state.display.hdmi.height; + m_desktopRes.dwFlags = MAKEFLAGS(tv_state.display.hdmi.group, tv_state.display.hdmi.mode, tv_state.display.hdmi.scan_mode); +- m_desktopRes.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv_state.display.hdmi.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight); ++ m_desktopRes.fPixelRatio = tv_state.display.hdmi.display_options.aspect == 0 ? 1.0f : get_display_aspect_ratio((HDMI_ASPECT_T)tv_state.display.hdmi.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight); + // Also add 3D flags + if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_SBS_HALF) + m_desktopRes.dwFlags |= D3DPRESENTFLAG_MODE3DSBS; +@@ -514,7 +514,7 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r + m_desktopRes.iScreenHeight= tv_state.display.sdtv.height; + m_desktopRes.dwFlags = MAKEFLAGS(HDMI_RES_GROUP_INVALID, tv_state.display.sdtv.mode, 1); + m_desktopRes.fRefreshRate = (float)tv_state.display.sdtv.frame_rate; +- m_desktopRes.fPixelRatio = get_display_aspect_ratio((SDTV_ASPECT_T)tv_state.display.sdtv.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight); ++ m_desktopRes.fPixelRatio = tv_state.display.hdmi.display_options.aspect == 0 ? 1.0f : get_display_aspect_ratio((SDTV_ASPECT_T)tv_state.display.sdtv.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight); + } -- //m_interlace_mode = MMAL_InterlaceProgressive; -+ m_interlace_mode = MMAL_InterlaceProgressive; - m_startframe = false; - m_decoderPts = DVD_NOPTS_VALUE; - m_droppedPics = 0; -@@ -315,8 +315,6 @@ bool COpenMaxVideo::change_dec_output_format() - MMAL_STATUS_T status; - CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); + SetResolutionString(m_desktopRes); + +From 009c3343c69e5565dcfb43095c42a5083651ae8b Mon Sep 17 00:00:00 2001 +From: anaconda +Date: Thu, 11 Sep 2014 21:30:43 +0200 +Subject: [PATCH 73/82] Disable textbox autoscrolling while on screensaver. + +--- + xbmc/guilib/GUITextBox.cpp | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/xbmc/guilib/GUITextBox.cpp b/xbmc/guilib/GUITextBox.cpp +index b7ef051..ba68fad 100644 +--- a/xbmc/guilib/GUITextBox.cpp ++++ b/xbmc/guilib/GUITextBox.cpp +@@ -23,6 +23,7 @@ + #include "utils/XBMCTinyXML.h" + #include "utils/MathUtils.h" + #include "utils/StringUtils.h" ++#include "Application.h" --#if 0 -- { - MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T interlace_type = {{ MMAL_PARAMETER_VIDEO_INTERLACE_TYPE, sizeof( interlace_type )}}; - status = mmal_port_parameter_get( m_dec_output, &interlace_type.hdr ); + using namespace std; -@@ -330,8 +328,7 @@ bool COpenMaxVideo::change_dec_output_format() +@@ -132,7 +133,7 @@ void CGUITextBox::Process(unsigned int currentTime, CDirtyRegionList &dirtyregio + // update our auto-scrolling as necessary + if (m_autoScrollTime && m_lines.size() > m_itemsPerPage) + { +- if (!m_autoScrollCondition || m_autoScrollCondition->Get()) ++ if ((!m_autoScrollCondition || m_autoScrollCondition->Get()) && !g_application.IsInScreenSaver()) + { + if (m_lastRenderTime) + m_autoScrollDelayTime += currentTime - m_lastRenderTime; + +From 1f2171c506c343ad66989bad5e159274fad10b64 Mon Sep 17 00:00:00 2001 +From: anaconda +Date: Sat, 13 Sep 2014 19:49:01 +0200 +Subject: [PATCH 74/82] SQUASH: only if dim or black + +--- + xbmc/Application.cpp | 7 +++++++ + xbmc/Application.h | 2 ++ + xbmc/guilib/GUITextBox.cpp | 4 +++- + 3 files changed, 12 insertions(+), 1 deletion(-) + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index 6a280d5..ab6e1be 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -5881,3 +5881,10 @@ void CApplication::CloseNetworkShares() + CSFTPSessionManager::DisconnectAllSessions(); + #endif + } ++ ++std::string CApplication::GetScreenSaverId() ++{ ++ if (m_screenSaver) ++ return m_screenSaver->ID(); ++ return ""; ++} +diff --git a/xbmc/Application.h b/xbmc/Application.h +index b788471..ed19b79 100644 +--- a/xbmc/Application.h ++++ b/xbmc/Application.h +@@ -356,6 +356,8 @@ class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMs + + void SetLoggingIn(bool loggingIn) { m_loggingIn = loggingIn; } + ++ std::string GetScreenSaverId(); ++ + protected: + virtual bool OnSettingsSaving() const; + +diff --git a/xbmc/guilib/GUITextBox.cpp b/xbmc/guilib/GUITextBox.cpp +index ba68fad..e149418 100644 +--- a/xbmc/guilib/GUITextBox.cpp ++++ b/xbmc/guilib/GUITextBox.cpp +@@ -133,7 +133,9 @@ void CGUITextBox::Process(unsigned int currentTime, CDirtyRegionList &dirtyregio + // update our auto-scrolling as necessary + if (m_autoScrollTime && m_lines.size() > m_itemsPerPage) + { +- if ((!m_autoScrollCondition || m_autoScrollCondition->Get()) && !g_application.IsInScreenSaver()) ++ if ((!m_autoScrollCondition || m_autoScrollCondition->Get()) && !(g_application.IsInScreenSaver() && ++ (g_application.GetScreenSaverId() == "screensaver.xbmc.builtin.black" || ++ g_application.GetScreenSaverId() == "screensaver.xbmc.builtin.dim"))) + { + if (m_lastRenderTime) + m_autoScrollDelayTime += currentTime - m_lastRenderTime; + +From ea6435d09d8ecb64a134a4fd4c18b10852369702 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 15 Sep 2014 14:37:09 +0100 +Subject: [PATCH 75/82] mmal: squash: UnInit before second configuration + +--- + xbmc/cores/VideoRenderers/MMALRenderer.cpp | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +index 9a81eb9..2c97806 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +@@ -250,7 +250,8 @@ bool CMMALRenderer::Configure(unsigned int width, unsigned int height, unsigned + else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_240M) + es_format->es->video.color_space = MMAL_COLOR_SPACE_SMPTE240M; + } +- assert(!m_vout); ++ if (m_bConfigured) ++ UnInit(); + m_bConfigured = init_vout(es_format); + mmal_format_free(es_format); } - else - CLog::Log(LOGERROR, "%s::%s Failed to query interlace type on %s (status=%x %s)", CLASSNAME, __func__, m_dec_output->name, status, mmal_status_to_string(status)); -- } --#endif -+ - // todo: if we don't disable/enable we can do this from callback - mmal_format_copy(m_dec_output->format, m_es_format); - status = mmal_port_format_commit(m_dec_output); -@@ -870,7 +867,7 @@ int COpenMaxVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) - } - } - EDEINTERLACEMODE deinterlace_request = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; --#if 0 -+ if (1) - { - bool deinterlace = m_interlace_mode != MMAL_InterlaceProgressive; - -@@ -884,7 +881,7 @@ int COpenMaxVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) - else if (deinterlace && !m_deint) - CreateDeinterlace(); - } --#endif -+ - if (buffer_to_free) - { - delete [] buffer_to_free; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -index f931419..3c9b8a1 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -@@ -133,7 +133,7 @@ class COpenMaxVideo - - CDVDStreamInfo m_hints; - // Components -- //MMAL_INTERLACETYPE_T m_interlace_mode; -+ MMAL_INTERLACETYPE_T m_interlace_mode; - bool m_startframe; - unsigned int m_decode_frame_number; - double m_decoderPts; -From 2d19a382695fbc6c222f99a4870bfb003e321413 Mon Sep 17 00:00:00 2001 +From bf7f64c23fe73b21649fdceac8c073544ebf74cf Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 16 Sep 2014 00:52:02 +0100 +Subject: [PATCH 76/82] [PiSink] Initial dual audio support + +--- + system/settings/rbp.xml | 7 - + xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp | 219 ++++++++++++++++++++++++------ + xbmc/cores/AudioEngine/Sinks/AESinkPi.h | 5 + + xbmc/cores/omxplayer/OMXAudio.cpp | 12 +- + 4 files changed, 186 insertions(+), 57 deletions(-) + +diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml +index 634aa4f..7f0f282 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -82,13 +82,6 @@ + + + +- +- +- 2 +- false +- +- +- + + + +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +index b199acd..fd9a03d 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +@@ -43,7 +43,8 @@ CAEDeviceInfo CAESinkPi::m_info; + CAESinkPi::CAESinkPi() : + m_sinkbuffer_sec_per_byte(0), + m_Initialized(false), +- m_submitted(0) ++ m_submitted(0), ++ m_omx_output(NULL) + { + } + +@@ -56,13 +57,26 @@ void CAESinkPi::SetAudioDest() + OMX_ERRORTYPE omx_err = OMX_ErrorNone; + OMX_CONFIG_BRCMAUDIODESTINATIONTYPE audioDest; + OMX_INIT_STRUCTURE(audioDest); +- if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue") +- strncpy((char *)audioDest.sName, "local", strlen("local")); +- else +- strncpy((char *)audioDest.sName, "hdmi", strlen("hdmi")); +- omx_err = m_omx_render.SetConfig(OMX_IndexConfigBrcmAudioDestination, &audioDest); +- if (omx_err != OMX_ErrorNone) +- CLog::Log(LOGERROR, "%s::%s - m_omx_render.SetConfig omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ if ( m_omx_render.IsInitialized() ) ++ { ++ if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue") ++ strncpy((char *)audioDest.sName, "local", strlen("local")); ++ else ++ strncpy((char *)audioDest.sName, "hdmi", strlen("hdmi")); ++ omx_err = m_omx_render.SetConfig(OMX_IndexConfigBrcmAudioDestination, &audioDest); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s::%s - m_omx_render.SetConfig omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ } ++ if ( m_omx_render_slave.IsInitialized() ) ++ { ++ if (CSettings::Get().GetString("audiooutput.audiodevice") != "PI:Analogue") ++ strncpy((char *)audioDest.sName, "local", strlen("local")); ++ else ++ strncpy((char *)audioDest.sName, "hdmi", strlen("hdmi")); ++ omx_err = m_omx_render_slave.SetConfig(OMX_IndexConfigBrcmAudioDestination, &audioDest); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s::%s - m_omx_render_slave.SetConfig omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ } + } + + static void SetAudioProps(bool stream_channels, uint32_t channel_map) +@@ -176,8 +190,11 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) + m_initFormat = format; + + // analogue only supports stereo +- if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue") ++ if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue" || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") ++ { + format.m_channelLayout = AE_CH_LAYOUT_2_0; ++ m_passthrough = false; ++ } + + // setup for a 50ms sink feed from SoftAE + if (format.m_dataFormat != AE_FMT_FLOATP && format.m_dataFormat != AE_FMT_FLOAT && +@@ -196,18 +213,29 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) + m_format = format; + m_sinkbuffer_sec_per_byte = 1.0 / (double)(m_format.m_frameSize * m_format.m_sampleRate); + +- CLog::Log(LOGDEBUG, "%s:%s Format:%d Channels:%d Samplerate:%d framesize:%d bufsize:%d bytes/s=%.2f", CLASSNAME, __func__, +- m_format.m_dataFormat, channels, m_format.m_sampleRate, m_format.m_frameSize, m_format.m_frameSize * m_format.m_frames, 1.0/m_sinkbuffer_sec_per_byte); +- +- CLog::Log(LOGDEBUG, "%s:%s", CLASSNAME, __func__); ++ CLog::Log(LOGDEBUG, "%s:%s Format:%d Channels:%d Samplerate:%d framesize:%d bufsize:%d bytes/s=%.2f dest=%s", CLASSNAME, __func__, ++ m_format.m_dataFormat, channels, m_format.m_sampleRate, m_format.m_frameSize, m_format.m_frameSize * m_format.m_frames, 1.0/m_sinkbuffer_sec_per_byte, ++ CSettings::Get().GetString("audiooutput.audiodevice").c_str()); + + OMX_ERRORTYPE omx_err = OMX_ErrorNone; + + if (!m_omx_render.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit)) + CLog::Log(LOGERROR, "%s::%s - m_omx_render.Initialize omx_err(0x%08x)", CLASSNAME, __func__, omx_err); + ++ if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") ++ { ++ if (!m_omx_splitter.Initialize("OMX.broadcom.audio_splitter", OMX_IndexParamAudioInit)) ++ CLog::Log(LOGERROR, "%s::%s - m_omx_splitter.Initialize omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ if (!m_omx_render_slave.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit)) ++ CLog::Log(LOGERROR, "%s::%s - m_omx_render.Initialize omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ m_omx_output = &m_omx_splitter; ++ } ++ else ++ m_omx_output = &m_omx_render; ++ ++ SetAudioDest(); ++ + OMX_INIT_STRUCTURE(m_pcm_input); +- m_pcm_input.nPortIndex = m_omx_render.GetInputPort(); + m_pcm_input.eNumData = OMX_NumericalDataSigned; + m_pcm_input.eEndian = OMX_EndianLittle; + m_pcm_input.bInterleaved = OMX_TRUE; +@@ -222,37 +250,100 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) + m_pcm_input.nChannels = channels; + m_pcm_input.nSamplingRate = m_format.m_sampleRate; + +- omx_err = m_omx_render.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_input); +- if (omx_err != OMX_ErrorNone) +- CLog::Log(LOGERROR, "%s::%s - error m_omx_render SetParameter in omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ if ( m_omx_splitter.IsInitialized() ) ++ { ++ m_pcm_input.nPortIndex = m_omx_splitter.GetInputPort(); ++ omx_err = m_omx_splitter.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_input); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s::%s - error m_omx_splitter SetParameter in omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ ++ m_pcm_input.nPortIndex = m_omx_splitter.GetOutputPort(); ++ omx_err = m_omx_splitter.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_input); ++ if(omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s::%s - error m_omx_splitter SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ ++ m_pcm_input.nPortIndex = m_omx_splitter.GetOutputPort() + 1; ++ omx_err = m_omx_splitter.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_input); ++ if(omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s::%s - error m_omx_splitter SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ } + +- m_omx_render.ResetEos(); ++ if ( m_omx_render_slave.IsInitialized() ) ++ { ++ m_pcm_input.nPortIndex = m_omx_render_slave.GetInputPort(); ++ omx_err = m_omx_render_slave.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_input); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s::%s - error m_omx_render_slave SetParameter in omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ } + +- SetAudioDest(); ++ if ( m_omx_render.IsInitialized() ) ++ { ++ m_pcm_input.nPortIndex = m_omx_render.GetInputPort(); ++ omx_err = m_omx_render.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_input); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s::%s - error m_omx_render SetParameter in omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ } + +- // set up the number/size of buffers for decoder input +- OMX_PARAM_PORTDEFINITIONTYPE port_param; +- OMX_INIT_STRUCTURE(port_param); +- port_param.nPortIndex = m_omx_render.GetInputPort(); ++ if ( m_omx_output->IsInitialized() ) ++ { ++ // set up the number/size of buffers for decoder input ++ OMX_PARAM_PORTDEFINITIONTYPE port_param; ++ OMX_INIT_STRUCTURE(port_param); ++ port_param.nPortIndex = m_omx_output->GetInputPort(); + +- omx_err = m_omx_render.GetParameter(OMX_IndexParamPortDefinition, &port_param); +- if (omx_err != OMX_ErrorNone) +- CLog::Log(LOGERROR, "%s:%s - error get OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ omx_err = m_omx_output->GetParameter(OMX_IndexParamPortDefinition, &port_param); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s:%s - error get OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); + +- port_param.nBufferCountActual = std::max((unsigned int)port_param.nBufferCountMin, (unsigned int)NUM_OMX_BUFFERS); +- port_param.nBufferSize = m_format.m_frameSize * m_format.m_frames; ++ port_param.nBufferCountActual = std::max((unsigned int)port_param.nBufferCountMin, (unsigned int)NUM_OMX_BUFFERS); ++ port_param.nBufferSize = ALIGN_UP(m_format.m_frameSize * m_format.m_frames, port_param.nBufferAlignment); + +- omx_err = m_omx_render.SetParameter(OMX_IndexParamPortDefinition, &port_param); +- if (omx_err != OMX_ErrorNone) +- CLog::Log(LOGERROR, "%s:%s - error set OMX_IndexParamPortDefinition (intput) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ omx_err = m_omx_output->SetParameter(OMX_IndexParamPortDefinition, &port_param); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s:%s - error set OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); + +- omx_err = m_omx_render.AllocInputBuffers(); +- if (omx_err != OMX_ErrorNone) +- CLog::Log(LOGERROR, "%s:%s - Error alloc buffers 0x%08x", CLASSNAME, __func__, omx_err); ++ omx_err = m_omx_output->AllocInputBuffers(); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s:%s - Error alloc buffers 0x%08x", CLASSNAME, __func__, omx_err); ++ } + +- omx_err = m_omx_render.SetStateForComponent(OMX_StateExecuting); +- if (omx_err != OMX_ErrorNone) +- CLog::Log(LOGERROR, "%s:%s - m_omx_render OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ if ( m_omx_splitter.IsInitialized() ) ++ { ++ m_omx_tunnel_splitter.Initialize(&m_omx_splitter, m_omx_splitter.GetOutputPort(), &m_omx_render, m_omx_render.GetInputPort()); ++ omx_err = m_omx_tunnel_splitter.Establish(); ++ if (omx_err != OMX_ErrorNone) ++ { ++ CLog::Log(LOGERROR, "COMXAudio::Initialize - Error m_omx_tunnel_splitter.Establish 0x%08x", omx_err); ++ return false; ++ } ++ ++ m_omx_tunnel_splitter_slave.Initialize(&m_omx_splitter, m_omx_splitter.GetOutputPort() + 1, &m_omx_render_slave, m_omx_render_slave.GetInputPort()); ++ omx_err = m_omx_tunnel_splitter_slave.Establish(); ++ if (omx_err != OMX_ErrorNone) ++ { ++ CLog::Log(LOGERROR, "COMXAudio::Initialize - Error m_omx_tunnel_splitter_slave.Establish 0x%08x", omx_err); ++ return false; ++ } ++ } ++ ++ if ( m_omx_splitter.IsInitialized() ) ++ { ++ omx_err = m_omx_splitter.SetStateForComponent(OMX_StateExecuting); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s:%s - m_omx_splitter OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ } ++ if ( m_omx_render.IsInitialized() ) ++ { ++ omx_err = m_omx_render.SetStateForComponent(OMX_StateExecuting); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s:%s - m_omx_render OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ } ++ if ( m_omx_render_slave.IsInitialized() ) ++ { ++ omx_err = m_omx_render_slave.SetStateForComponent(OMX_StateExecuting); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s:%s - m_omx_render_slave OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ } + + m_Initialized = true; + return true; +@@ -263,12 +354,32 @@ void CAESinkPi::Deinitialize() + { + CLog::Log(LOGDEBUG, "%s:%s", CLASSNAME, __func__); + SetAudioProps(false, 0); +- if (m_Initialized) +- { ++ ++ if ( m_omx_render.IsInitialized() ) ++ m_omx_render.IgnoreNextError(OMX_ErrorPortUnpopulated); ++ if ( m_omx_render_slave.IsInitialized() ) ++ m_omx_render_slave.IgnoreNextError(OMX_ErrorPortUnpopulated); ++ ++ if ( m_omx_tunnel_splitter.IsInitialized() ) ++ m_omx_tunnel_splitter.Deestablish(); ++ if ( m_omx_tunnel_splitter_slave.IsInitialized() ) ++ m_omx_tunnel_splitter_slave.Deestablish(); ++ ++ if ( m_omx_splitter.IsInitialized() ) ++ m_omx_splitter.FlushAll(); ++ if ( m_omx_render.IsInitialized() ) + m_omx_render.FlushAll(); ++ if ( m_omx_render_slave.IsInitialized() ) ++ m_omx_render_slave.FlushAll(); ++ ++ if ( m_omx_splitter.IsInitialized() ) ++ m_omx_splitter.Deinitialize(); ++ if ( m_omx_render.IsInitialized() ) + m_omx_render.Deinitialize(); +- m_Initialized = false; +- } ++ if ( m_omx_render_slave.IsInitialized() ) ++ m_omx_render_slave.Deinitialize(); ++ ++ m_Initialized = false; + } + + bool CAESinkPi::IsCompatible(const AEAudioFormat &format, const std::string &device) +@@ -314,7 +425,7 @@ double CAESinkPi::GetCacheTotal() + + unsigned int CAESinkPi::AddPackets(uint8_t **data, unsigned int frames, unsigned int offset) + { +- if (!m_Initialized || !frames) ++ if (!m_Initialized || !m_omx_output || !frames) + return frames; + + OMX_ERRORTYPE omx_err = OMX_ErrorNone; +@@ -332,7 +443,7 @@ unsigned int CAESinkPi::AddPackets(uint8_t **data, unsigned int frames, unsigned + if (delay <= 0.0 && m_submitted) + CLog::Log(LOGNOTICE, "%s:%s Underrun (delay:%.2f frames:%d)", CLASSNAME, __func__, delay, frames); + +- omx_buffer = m_omx_render.GetInputBuffer(1000); ++ omx_buffer = m_omx_output->GetInputBuffer(1000); + if (omx_buffer == NULL) + { + CLog::Log(LOGERROR, "CAESinkPi::AddPackets timeout"); +@@ -351,7 +462,7 @@ unsigned int CAESinkPi::AddPackets(uint8_t **data, unsigned int frames, unsigned + for (int i=0; i < planes; i++) + memcpy((uint8_t *)omx_buffer->pBuffer + i * planesize, data[i] + offset * pitch, planesize); + } +- omx_err = m_omx_render.EmptyThisBuffer(omx_buffer); ++ omx_err = m_omx_output->EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + CLog::Log(LOGERROR, "%s:%s frames=%d err=%x", CLASSNAME, __func__, frames, omx_err); + m_submitted++; +@@ -419,6 +530,26 @@ void CAESinkPi::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) + m_info.m_dataFormats.push_back(AE_FMT_S16NEP); + + list.push_back(m_info); ++ ++ m_info.m_channels.Reset(); ++ m_info.m_dataFormats.clear(); ++ m_info.m_sampleRates.clear(); ++ ++ m_info.m_deviceType = AE_DEVTYPE_PCM; ++ m_info.m_deviceName = "Both"; ++ m_info.m_displayName = "HDMI and Analogue"; ++ m_info.m_displayNameExtra = ""; ++ m_info.m_channels += AE_CH_FL; ++ m_info.m_channels += AE_CH_FR; ++ m_info.m_sampleRates.push_back(48000); ++ m_info.m_dataFormats.push_back(AE_FMT_FLOAT); ++ m_info.m_dataFormats.push_back(AE_FMT_S32LE); ++ m_info.m_dataFormats.push_back(AE_FMT_S16LE); ++ m_info.m_dataFormats.push_back(AE_FMT_FLOATP); ++ m_info.m_dataFormats.push_back(AE_FMT_S32NEP); ++ m_info.m_dataFormats.push_back(AE_FMT_S16NEP); ++ ++ list.push_back(m_info); + } + + #endif +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.h b/xbmc/cores/AudioEngine/Sinks/AESinkPi.h +index 8ab1d08..5c57999 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.h ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.h +@@ -57,8 +57,13 @@ class CAESinkPi : public IAESink + bool m_Initialized; + uint32_t m_submitted; + OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_input; ++ COMXCoreComponent *m_omx_output; ++ COMXCoreComponent m_omx_splitter; + COMXCoreComponent m_omx_render; ++ COMXCoreComponent m_omx_render_slave; + bool m_passthrough; ++ COMXCoreTunel m_omx_tunnel_splitter; ++ COMXCoreTunel m_omx_tunnel_splitter_slave; + }; + + #endif +diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp +index a73dd0a..13899bc 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -124,17 +124,17 @@ bool COMXAudio::PortSettingsChanged() + if(!m_omx_mixer.Initialize("OMX.broadcom.audio_mixer", OMX_IndexParamAudioInit)) + return false; + } +- if(CSettings::Get().GetBool("audiooutput.dualaudio")) ++ if(CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") + { + if(!m_omx_splitter.Initialize("OMX.broadcom.audio_splitter", OMX_IndexParamAudioInit)) + return false; + } +- if (CSettings::Get().GetBool("audiooutput.dualaudio") || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue") ++ if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both" || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue") + { + if(!m_omx_render_analog.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit)) + return false; + } +- if (CSettings::Get().GetBool("audiooutput.dualaudio") || CSettings::Get().GetString("audiooutput.audiodevice") != "PI:Analogue") ++ if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both" || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:HDMI") + { + if(!m_omx_render_hdmi.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit)) + return false; +@@ -252,7 +252,7 @@ bool COMXAudio::PortSettingsChanged() + { + // By default audio_render is the clock master, and if output samples don't fit the timestamps, it will speed up/slow down the clock. + // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync +- if(CSettings::Get().GetBool("videoplayer.usedisplayasclock") || (CSettings::Get().GetBool("audiooutput.dualaudio") && CSettings::Get().GetString("audiooutput.audiodevice") != "PI:Analogue")) ++ if(CSettings::Get().GetBool("videoplayer.usedisplayasclock") || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") + { + OMX_CONFIG_BOOLEANTYPE configBool; + OMX_INIT_STRUCTURE(configBool); +@@ -278,7 +278,7 @@ bool COMXAudio::PortSettingsChanged() + { + // By default audio_render is the clock master, and if output samples don't fit the timestamps, it will speed up/slow down the clock. + // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync +- if(CSettings::Get().GetBool("videoplayer.usedisplayasclock") || (CSettings::Get().GetBool("audiooutput.dualaudio") && CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue")) ++ if(CSettings::Get().GetBool("videoplayer.usedisplayasclock")) + { + OMX_CONFIG_BOOLEANTYPE configBool; + OMX_INIT_STRUCTURE(configBool); +@@ -601,7 +601,7 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + CAEChannelInfo stdLayout = (enum AEStdChLayout)CSettings::Get().GetInt("audiooutput.channels"); + + // ignore layout setting for analogue +- if (CSettings::Get().GetBool("audiooutput.dualaudio") || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue") ++ if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both" || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue") + stdLayout = AE_CH_LAYOUT_2_0; + + // force out layout to stereo if input is not multichannel - it gives the receiver a chance to upmix + +From 94d5b9f2afaec3011abbd702593c14a7863a8aee Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 18 Sep 2014 14:24:56 +0100 +Subject: [PATCH 77/82] [omxplayer] Only enable audio clock master when A/V + sync method is set to audio clock + +--- + xbmc/cores/omxplayer/OMXAudio.cpp | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp +index 13899bc..3c6c73b 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -252,7 +252,8 @@ bool COMXAudio::PortSettingsChanged() + { + // By default audio_render is the clock master, and if output samples don't fit the timestamps, it will speed up/slow down the clock. + // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync +- if(CSettings::Get().GetBool("videoplayer.usedisplayasclock") || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") ++ if((CSettings::Get().GetBool("videoplayer.usedisplayasclock") && CSettings::Get().GetInt("videoplayer.synctype") == SYNC_DISCON) || ++ CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") + { + OMX_CONFIG_BOOLEANTYPE configBool; + OMX_INIT_STRUCTURE(configBool); +@@ -278,7 +279,7 @@ bool COMXAudio::PortSettingsChanged() + { + // By default audio_render is the clock master, and if output samples don't fit the timestamps, it will speed up/slow down the clock. + // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync +- if(CSettings::Get().GetBool("videoplayer.usedisplayasclock")) ++ if(CSettings::Get().GetBool("videoplayer.usedisplayasclock") && CSettings::Get().GetInt("videoplayer.synctype") == SYNC_DISCON) + { + OMX_CONFIG_BOOLEANTYPE configBool; + OMX_INIT_STRUCTURE(configBool); + +From 6593033f28587e9fb14e4a3339c4f44c1f72d50d Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 18 Sep 2014 19:59:42 +0100 +Subject: [PATCH 78/82] [mmal] Avoid busy spinning when no work to do + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 19 +++++++++++++++---- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h | 1 + + 2 files changed, 16 insertions(+), 4 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 00f174a..7326104 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -133,6 +133,7 @@ CMMALVideo::CMMALVideo() + m_changed_count = 0; + m_changed_count_dec = 0; + m_output_busy = 0; ++ m_demux_queue_length = 0; + m_es_format = mmal_format_alloc(); + } + +@@ -768,6 +769,7 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + demux_packet.size = iSize; + demux_packet.buff = new uint8_t[iSize]; + memcpy(demux_packet.buff, pData, iSize); ++ m_demux_queue_length += demux_packet.size; + m_demux_queue.push(demux_packet); + } + +@@ -785,6 +787,7 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + if (space >= (unsigned int)demux_packet.size) + { + // need to lock here to retrieve an input buffer and pop the queue ++ m_demux_queue_length -= demux_packet.size; + m_demux_queue.pop(); + demuxer_bytes = (unsigned int)demux_packet.size; + demuxer_content = demux_packet.buff; +@@ -824,9 +827,10 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END; + + #if defined(MMAL_DEBUG_VERBOSE) +- CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d/%-6d dts:%.3f pts:%.3f flags:%x dts_queue(%d) ready_queue(%d) busy_queue(%d)", +- CLASSNAME, __func__, buffer, iSize-demuxer_bytes, iSize, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, buffer->flags, m_dts_queue.size(), m_output_ready.size(), m_output_busy); ++ CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d/%-6d dts:%.3f pts:%.3f flags:%x dts_queue(%d) ready_queue(%d) busy_queue(%d) demux_queue(%d) space(%d)", ++ CLASSNAME, __func__, buffer, buffer->length, demuxer_bytes, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, buffer->flags, m_dts_queue.size(), m_output_ready.size(), m_output_busy, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size); + #endif ++ assert((int)buffer->length > 0); + status = mmal_port_send_buffer(m_dec_input, buffer); + if (status != MMAL_SUCCESS) + { +@@ -898,13 +902,19 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + #endif + ret |= VC_PICTURE; + } +- if (mmal_queue_length(m_dec_input_pool->queue) > 0) ++ if (mmal_queue_length(m_dec_input_pool->queue) > 0 && !m_demux_queue_length) + { + #if defined(MMAL_DEBUG_VERBOSE) +- CLog::Log(LOGDEBUG, "%s::%s - got space for output:%d", CLASSNAME, __func__, mmal_queue_length(m_dec_input_pool->queue)); ++ CLog::Log(LOGDEBUG, "%s::%s - got space for output: demux_queue(%d) space(%d)", CLASSNAME, __func__, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size); + #endif + ret |= VC_BUFFER; + } ++ if (!ret) ++ { ++ CLog::Log(LOGDEBUG, "%s::%s - Nothing to do: dts_queue(%d) ready_queue(%d) busy_queue(%d) demux_queue(%d) space(%d)", ++ CLASSNAME, __func__, m_dts_queue.size(), m_output_ready.size(), m_output_busy, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size); ++ Sleep(10); // otherwise we busy spin ++ } + return ret; + } + +@@ -935,6 +945,7 @@ void CMMALVideo::Reset(void) + m_dts_queue.pop(); + while (!m_demux_queue.empty()) + m_demux_queue.pop(); ++ m_demux_queue_length = 0; + pthread_mutex_unlock(&m_output_mutex); + if (!old_drop_state) + SetDropState(false); +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +index 4b98be2..982ee14 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +@@ -119,6 +119,7 @@ class CMMALVideo + + std::queue m_dts_queue; + std::queue m_demux_queue; ++ unsigned m_demux_queue_length; + + // mmal output buffers (video frames) + pthread_mutex_t m_output_mutex; + +From 071f3ac540ad4927f85244fc75e02ce8d0aad5a6 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 18 Aug 2014 19:09:32 +0100 -Subject: [PATCH 77/77] rbp: Use new dispmanx function for vsync callbacks +Subject: [PATCH 79/82] rbp: Use new dispmanx function for vsync callbacks +[rbp] Enable vsync handler all the time --- - xbmc/linux/RBP.cpp | 85 ++++++++++++++----------- - xbmc/linux/RBP.h | 5 +- + xbmc/linux/RBP.cpp | 96 ++++++++++++++----------- + xbmc/linux/RBP.h | 7 +- xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 4 +- - 3 files changed, 52 insertions(+), 42 deletions(-) + 3 files changed, 61 insertions(+), 46 deletions(-) diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp -index 34e0108..462bfa2 100644 +index 34e0108..8ce60cb 100644 --- a/xbmc/linux/RBP.cpp +++ b/xbmc/linux/RBP.cpp @@ -33,7 +33,7 @@ CRBP::CRBP() @@ -12317,20 +10762,51 @@ index 34e0108..462bfa2 100644 m_omx_initialized = m_OMX->Initialize(); if(!m_omx_initialized) -@@ -112,13 +111,24 @@ void CRBP::LogFirmwareVerison() +@@ -112,13 +111,55 @@ void CRBP::LogFirmwareVerison() CLog::Log(LOGNOTICE, "Config:\n%s", response); } ++static void vsync_callback(DISPMANX_UPDATE_HANDLE_T u, void *arg) ++{ ++ CEvent *sync = (CEvent *)arg; ++ sync->Set(); ++} ++ ++void CRBP::WaitVsync() ++{ ++ CSingleLock lock (m_critSection); ++ if (m_display == DISPMANX_NO_HANDLE) ++ { ++ // don't busy spin ++ Sleep(10); ++ return; ++ } ++ m_vsync.Reset(); ++ m_vsync.Wait(); ++} ++ +DISPMANX_DISPLAY_HANDLE_T CRBP::OpenDisplay(uint32_t device) +{ ++ CSingleLock lock (m_critSection); + if (m_display == DISPMANX_NO_HANDLE) + m_display = vc_dispmanx_display_open( 0 /*screen*/ ); ++ ++ if (m_display != DISPMANX_NO_HANDLE) ++ { ++ int s = vc_dispmanx_vsync_callback(m_display, vsync_callback, (void *)&m_vsync); ++ assert(s == 0); ++ } + return m_display; +} + +void CRBP::CloseDisplay(DISPMANX_DISPLAY_HANDLE_T display) +{ ++ CSingleLock lock (m_critSection); + assert(display == m_display); ++ ++ int s = vc_dispmanx_vsync_callback(m_display, NULL, NULL); ++ assert(s == 0); ++ + vc_dispmanx_display_close(m_display); + m_display = DISPMANX_NO_HANDLE; +} @@ -12346,7 +10822,7 @@ index 34e0108..462bfa2 100644 { width = info.width; height = info.height; -@@ -128,12 +138,10 @@ void CRBP::GetDisplaySize(int &width, int &height) +@@ -128,12 +169,10 @@ void CRBP::GetDisplaySize(int &width, int &height) width = 0; height = 0; } @@ -12359,7 +10835,7 @@ index 34e0108..462bfa2 100644 DISPMANX_RESOURCE_HANDLE_T resource; VC_RECT_T rect; unsigned char *image = NULL; -@@ -148,7 +156,6 @@ unsigned char *CRBP::CaptureDisplay(int width, int height, int *pstride, bool sw +@@ -148,7 +187,6 @@ unsigned char *CRBP::CaptureDisplay(int width, int height, int *pstride, bool sw if (!pstride) flags |= DISPMANX_SNAPSHOT_PACK; @@ -12367,7 +10843,7 @@ index 34e0108..462bfa2 100644 stride = ((width + 15) & ~15) * 4; image = new unsigned char [height * stride]; -@@ -156,45 +163,44 @@ unsigned char *CRBP::CaptureDisplay(int width, int height, int *pstride, bool sw +@@ -156,56 +194,30 @@ unsigned char *CRBP::CaptureDisplay(int width, int height, int *pstride, bool sw { resource = vc_dispmanx_resource_create( VC_IMAGE_RGBA32, width, height, &vc_image_ptr ); @@ -12386,15 +10862,7 @@ index 34e0108..462bfa2 100644 } -void CRBP::WaitVsync(void) -+ -+static void vsync_callback(DISPMANX_UPDATE_HANDLE_T u, void *arg) -+{ -+ CEvent *sync = (CEvent *)arg; -+ sync->Set(); -+} -+ -+void CRBP::WaitVsync() - { +-{ - DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open( 0 /*screen*/ ); - DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0); - @@ -12420,27 +10888,15 @@ index 34e0108..462bfa2 100644 - - vc_dispmanx_update_submit_sync(update); - vc_dispmanx_display_close( display ); -+ int s; -+ CEvent sync; -+ DISPMANX_DISPLAY_HANDLE_T m_display = vc_dispmanx_display_open( 0 /*screen*/ ); -+ if (m_display == DISPMANX_NO_HANDLE) -+ { -+ CLog::Log(LOGDEBUG, "CRBP::%s skipping while display closed", __func__); -+ return; -+ } -+ s = vc_dispmanx_vsync_callback(m_display, vsync_callback, (void *)&sync); -+ if (s == 0) -+ { -+ sync.Wait(); -+ } -+ else assert(0); -+ s = vc_dispmanx_vsync_callback(m_display, NULL, NULL); -+ assert(s == 0); -+ vc_dispmanx_display_close( m_display ); - } +-} +- +- + void CRBP::Deinitialize() + { ++ CSingleLock lock (m_critSection); + if (m_omx_image_init) + g_OMXImage.Deinitialize(); - -@@ -206,6 +212,9 @@ void CRBP::Deinitialize() if(m_omx_initialized) m_OMX->Deinitialize(); @@ -12451,10 +10907,18 @@ index 34e0108..462bfa2 100644 if(m_initialized) diff --git a/xbmc/linux/RBP.h b/xbmc/linux/RBP.h -index f947acc..ca80045 100644 +index f947acc..029d69c 100644 --- a/xbmc/linux/RBP.h +++ b/xbmc/linux/RBP.h -@@ -53,6 +53,8 @@ class CRBP +@@ -38,6 +38,7 @@ + #include "DllBCM.h" + #include "OMXCore.h" + #include "threads/CriticalSection.h" ++#include "threads/Event.h" + + class CRBP + { +@@ -53,6 +54,8 @@ class CRBP bool GetCodecMpg2() { return m_codec_mpg2_enabled; } bool GetCodecWvc1() { return m_codec_wvc1_enabled; } void GetDisplaySize(int &width, int &height); @@ -12463,7 +10927,7 @@ index f947acc..ca80045 100644 int GetGUIResolutionLimit() { return m_gui_resolution_limit; } // stride can be null for packed output unsigned char *CaptureDisplay(int width, int height, int *stride, bool swap_red_blue, bool video_only = true); -@@ -73,10 +75,9 @@ class CRBP +@@ -73,10 +76,10 @@ class CRBP bool m_codec_mpg2_enabled; bool m_codec_wvc1_enabled; COMXCore *m_OMX; @@ -12472,11 +10936,12 @@ index f947acc..ca80045 100644 class DllLibOMXCore; CCriticalSection m_critSection; + DISPMANX_DISPLAY_HANDLE_T m_display; ++ CEvent m_vsync; }; extern CRBP g_RBP; diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp -index ca36082..4b74ea0 100644 +index 1529045..b6bf1fc 100644 --- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp @@ -306,7 +306,7 @@ bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res) @@ -12497,3 +10962,462 @@ index ca36082..4b74ea0 100644 m_dispman_display = DISPMANX_NO_HANDLE; } DLOG("CEGLNativeTypeRaspberryPI::DestroyDispmaxWindow\n"); + +From 8ae76ca01163bf9552ece9552dc3d546a5fe1894 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 18 Sep 2014 23:14:31 +0100 +Subject: [PATCH 80/82] Revert "rbp: Use new dispmanx function for vsync + callbacks" + +This reverts commit e56163da23b6a844e7eee076e4583bce606f788b. +--- + xbmc/linux/RBP.cpp | 96 +++++++++++-------------- + xbmc/linux/RBP.h | 7 +- + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 4 +- + 3 files changed, 46 insertions(+), 61 deletions(-) + +diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp +index 8ce60cb..34e0108 100644 +--- a/xbmc/linux/RBP.cpp ++++ b/xbmc/linux/RBP.cpp +@@ -33,7 +33,7 @@ CRBP::CRBP() + m_omx_initialized = false; + m_DllBcmHost = new DllBcmHost(); + m_OMX = new COMXCore(); +- m_display = DISPMANX_NO_HANDLE; ++ m_element = 0; + } + + CRBP::~CRBP() +@@ -55,7 +55,8 @@ bool CRBP::Initialize() + + m_DllBcmHost->bcm_host_init(); + +- //OpenDisplay(0 /*screen*/); ++ uint32_t vc_image_ptr; ++ m_resource = vc_dispmanx_resource_create( VC_IMAGE_RGB565, 1, 1, &vc_image_ptr ); + + m_omx_initialized = m_OMX->Initialize(); + if(!m_omx_initialized) +@@ -111,55 +112,13 @@ void CRBP::LogFirmwareVerison() + CLog::Log(LOGNOTICE, "Config:\n%s", response); + } + +-static void vsync_callback(DISPMANX_UPDATE_HANDLE_T u, void *arg) +-{ +- CEvent *sync = (CEvent *)arg; +- sync->Set(); +-} +- +-void CRBP::WaitVsync() +-{ +- CSingleLock lock (m_critSection); +- if (m_display == DISPMANX_NO_HANDLE) +- { +- // don't busy spin +- Sleep(10); +- return; +- } +- m_vsync.Reset(); +- m_vsync.Wait(); +-} +- +-DISPMANX_DISPLAY_HANDLE_T CRBP::OpenDisplay(uint32_t device) +-{ +- CSingleLock lock (m_critSection); +- if (m_display == DISPMANX_NO_HANDLE) +- m_display = vc_dispmanx_display_open( 0 /*screen*/ ); +- +- if (m_display != DISPMANX_NO_HANDLE) +- { +- int s = vc_dispmanx_vsync_callback(m_display, vsync_callback, (void *)&m_vsync); +- assert(s == 0); +- } +- return m_display; +-} +- +-void CRBP::CloseDisplay(DISPMANX_DISPLAY_HANDLE_T display) +-{ +- CSingleLock lock (m_critSection); +- assert(display == m_display); +- +- int s = vc_dispmanx_vsync_callback(m_display, NULL, NULL); +- assert(s == 0); +- +- vc_dispmanx_display_close(m_display); +- m_display = DISPMANX_NO_HANDLE; +-} +- + void CRBP::GetDisplaySize(int &width, int &height) + { ++ DISPMANX_DISPLAY_HANDLE_T display; + DISPMANX_MODEINFO_T info; +- if (vc_dispmanx_display_get_info(m_display, &info) == 0) ++ ++ display = vc_dispmanx_display_open( 0 /*screen*/ ); ++ if (vc_dispmanx_display_get_info(display, &info) == 0) + { + width = info.width; + height = info.height; +@@ -169,10 +128,12 @@ void CRBP::GetDisplaySize(int &width, int &height) + width = 0; + height = 0; + } ++ vc_dispmanx_display_close(display ); + } + + unsigned char *CRBP::CaptureDisplay(int width, int height, int *pstride, bool swap_red_blue, bool video_only) + { ++ DISPMANX_DISPLAY_HANDLE_T display; + DISPMANX_RESOURCE_HANDLE_T resource; + VC_RECT_T rect; + unsigned char *image = NULL; +@@ -187,6 +148,7 @@ unsigned char *CRBP::CaptureDisplay(int width, int height, int *pstride, bool sw + if (!pstride) + flags |= DISPMANX_SNAPSHOT_PACK; + ++ display = vc_dispmanx_display_open( 0 /*screen*/ ); + stride = ((width + 15) & ~15) * 4; + image = new unsigned char [height * stride]; + +@@ -194,30 +156,56 @@ unsigned char *CRBP::CaptureDisplay(int width, int height, int *pstride, bool sw + { + resource = vc_dispmanx_resource_create( VC_IMAGE_RGBA32, width, height, &vc_image_ptr ); + +- assert(m_display != DISPMANX_NO_HANDLE); +- vc_dispmanx_snapshot(m_display, resource, (DISPMANX_TRANSFORM_T)flags); ++ vc_dispmanx_snapshot(display, resource, (DISPMANX_TRANSFORM_T)flags); + + vc_dispmanx_rect_set(&rect, 0, 0, width, height); + vc_dispmanx_resource_read_data(resource, &rect, image, stride); + vc_dispmanx_resource_delete( resource ); ++ vc_dispmanx_display_close(display ); + } + if (pstride) + *pstride = stride; + return image; + } + ++void CRBP::WaitVsync(void) ++{ ++ DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open( 0 /*screen*/ ); ++ DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0); ++ ++ VC_DISPMANX_ALPHA_T alpha = { (DISPMANX_FLAGS_ALPHA_T)(DISPMANX_FLAGS_ALPHA_FROM_SOURCE | DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS), 120, /*alpha 0->255*/ 0 }; ++ VC_RECT_T src_rect; ++ VC_RECT_T dst_rect; ++ vc_dispmanx_rect_set( &src_rect, 0, 0, 1 << 16, 1 << 16 ); ++ vc_dispmanx_rect_set( &dst_rect, 0, 0, 1, 1 ); ++ ++ if (m_element) ++ vc_dispmanx_element_remove( update, m_element ); ++ ++ m_element = vc_dispmanx_element_add( update, ++ display, ++ 2000, // layer ++ &dst_rect, ++ m_resource, ++ &src_rect, ++ DISPMANX_PROTECTION_NONE, ++ &alpha, ++ NULL, // clamp ++ (DISPMANX_TRANSFORM_T)0 ); ++ ++ vc_dispmanx_update_submit_sync(update); ++ vc_dispmanx_display_close( display ); ++} ++ ++ + void CRBP::Deinitialize() + { +- CSingleLock lock (m_critSection); + if (m_omx_image_init) + g_OMXImage.Deinitialize(); + + if(m_omx_initialized) + m_OMX->Deinitialize(); + +- if (m_display) +- CloseDisplay(m_display); +- + m_DllBcmHost->bcm_host_deinit(); + + if(m_initialized) +diff --git a/xbmc/linux/RBP.h b/xbmc/linux/RBP.h +index 029d69c..f947acc 100644 +--- a/xbmc/linux/RBP.h ++++ b/xbmc/linux/RBP.h +@@ -38,7 +38,6 @@ + #include "DllBCM.h" + #include "OMXCore.h" + #include "threads/CriticalSection.h" +-#include "threads/Event.h" + + class CRBP + { +@@ -54,8 +53,6 @@ class CRBP + bool GetCodecMpg2() { return m_codec_mpg2_enabled; } + bool GetCodecWvc1() { return m_codec_wvc1_enabled; } + void GetDisplaySize(int &width, int &height); +- DISPMANX_DISPLAY_HANDLE_T OpenDisplay(uint32_t device); +- void CloseDisplay(DISPMANX_DISPLAY_HANDLE_T display); + int GetGUIResolutionLimit() { return m_gui_resolution_limit; } + // stride can be null for packed output + unsigned char *CaptureDisplay(int width, int height, int *stride, bool swap_red_blue, bool video_only = true); +@@ -76,10 +73,10 @@ class CRBP + bool m_codec_mpg2_enabled; + bool m_codec_wvc1_enabled; + COMXCore *m_OMX; ++ DISPMANX_RESOURCE_HANDLE_T m_resource; ++ DISPMANX_ELEMENT_HANDLE_T m_element; + class DllLibOMXCore; + CCriticalSection m_critSection; +- DISPMANX_DISPLAY_HANDLE_T m_display; +- CEvent m_vsync; + }; + + extern CRBP g_RBP; +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +index b6bf1fc..1529045 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +@@ -306,7 +306,7 @@ bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res) + m_desktopRes = res; + } + +- m_dispman_display = g_RBP.OpenDisplay(0); ++ m_dispman_display = m_DllBcmHost->vc_dispmanx_display_open(0); + + m_width = res.iWidth; + m_height = res.iHeight; +@@ -571,7 +571,7 @@ void CEGLNativeTypeRaspberryPI::DestroyDispmaxWindow() + + if (m_dispman_display != DISPMANX_NO_HANDLE) + { +- g_RBP.CloseDisplay(m_dispman_display); ++ m_DllBcmHost->vc_dispmanx_display_close(m_dispman_display); + m_dispman_display = DISPMANX_NO_HANDLE; + } + DLOG("CEGLNativeTypeRaspberryPI::DestroyDispmaxWindow\n"); + +From 2995a6a3e837c80990dfb779099cbb262b5fe505 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 19 Sep 2014 11:54:49 +0100 +Subject: [PATCH 81/82] [dvdplayer/rbp] Add pi specific option to maintain + vsync with pll adjustment + +New A/V sync option in settings/video/playback to do "Adjust PLL". +This uses video clock (so perfect video syncing) but avoids having to resample +or drop/dupe audio packets which is normally required. + +Needed updated firmware +--- + language/English/strings.po | 5 +++++ + system/settings/rbp.xml | 20 +++++++++++++++++++ + xbmc/cores/AudioEngine/Utils/AEUtil.h | 3 ++- + xbmc/cores/dvdplayer/DVDPlayerAudio.cpp | 34 +++++++++++++++++++++++++++++++-- + xbmc/cores/dvdplayer/DVDPlayerAudio.h | 1 + + xbmc/linux/RBP.cpp | 13 +++++++++++++ + xbmc/linux/RBP.h | 1 + + 7 files changed, 74 insertions(+), 3 deletions(-) + +diff --git a/language/English/strings.po b/language/English/strings.po +index 8252473..0e64c2a 100755 +--- a/language/English/strings.po ++++ b/language/English/strings.po +@@ -15937,3 +15937,8 @@ msgstr "" + msgctxt "#38005" + msgid "24 fps" + msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#38006" ++msgid "Adjust PLL" ++msgstr "" +diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml +index 7f0f282..61b105d 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -11,6 +11,26 @@ + + +
++ ++ ++ ++ 2 ++ 4 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ true ++ ++ ++ ++ ++ + + + false +diff --git a/xbmc/cores/AudioEngine/Utils/AEUtil.h b/xbmc/cores/AudioEngine/Utils/AEUtil.h +index 1e61c50..039cd69 100644 +--- a/xbmc/cores/AudioEngine/Utils/AEUtil.h ++++ b/xbmc/cores/AudioEngine/Utils/AEUtil.h +@@ -53,7 +53,8 @@ enum AVSync + { + SYNC_DISCON = 0, + SYNC_SKIPDUP, +- SYNC_RESAMPLE ++ SYNC_RESAMPLE, ++ SYNC_PLLADJUST + }; + + struct AEDelayStatus +diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp +index 98da461..36b2568 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp +@@ -112,6 +112,7 @@ CDVDPlayerAudio::CDVDPlayerAudio(CDVDClock* pClock, CDVDMessageQueue& parent) + m_started = false; + m_silence = false; + m_resampleratio = 1.0; ++ m_plladjust = 1.0f; + m_synctype = SYNC_DISCON; + m_setsynctype = SYNC_DISCON; + m_prevsynctype = -1; +@@ -472,6 +473,8 @@ void CDVDPlayerAudio::UpdatePlayerInfo() + //if the resample ratio is 0.5, then we're playing twice as fast + if (m_synctype == SYNC_RESAMPLE) + s << ", rr:" << fixed << setprecision(5) << 1.0 / m_resampleratio; ++ if (m_synctype == SYNC_PLLADJUST) ++ s << ", pll:" << fixed << setprecision(5) << 1.0 / m_plladjust; + + s << ", att:" << fixed << setprecision(1) << log(GetCurrentAttenuation()) * 20.0f << " dB"; + +@@ -622,8 +625,8 @@ void CDVDPlayerAudio::SetSyncType(bool passthrough) + + if (m_synctype != m_prevsynctype) + { +- const char *synctypes[] = {"clock feedback", "skip/duplicate", "resample", "invalid"}; +- int synctype = (m_synctype >= 0 && m_synctype <= 2) ? m_synctype : 3; ++ const char *synctypes[] = {"clock feedback", "skip/duplicate", "resample", "pll adjust", "invalid"}; ++ int synctype = (m_synctype >= 0 && m_synctype <= 3) ? m_synctype : 4; + CLog::Log(LOGDEBUG, "CDVDPlayerAudio:: synctype set to %i: %s", m_synctype, synctypes[synctype]); + m_prevsynctype = m_synctype; + } +@@ -697,6 +700,29 @@ void CDVDPlayerAudio::HandleSyncError(double duration) + } + m_resampleratio = 1.0 / m_pClock->GetClockSpeed() + proportional + m_integral; + } ++ else if (m_synctype == SYNC_PLLADJUST) ++ { ++ //reset the integral on big errors, failsafe ++ if (fabs(m_error) > DVD_TIME_BASE) ++ m_integral = 0; ++ else if (fabs(m_error) > DVD_MSEC_TO_TIME(5)) ++ m_integral += m_error / DVD_TIME_BASE / INTEGRAL; ++ ++ double proportional = 0.0; ++ ++ //on big errors use more proportional ++ if (fabs(m_error / DVD_TIME_BASE) > 0.0) ++ { ++ double proportionaldiv = PROPORTIONAL * (PROPREF / fabs(m_error / DVD_TIME_BASE)); ++ if (proportionaldiv < PROPDIVMIN) proportionaldiv = PROPDIVMIN; ++ else if (proportionaldiv > PROPDIVMAX) proportionaldiv = PROPDIVMAX; ++ ++ proportional = m_error / DVD_TIME_BASE / proportionaldiv; ++ } ++ m_plladjust = 1.0 / m_pClock->GetClockSpeed() + proportional + m_integral; ++ double new_adjust = g_RBP.AdjustHDMIClock(m_plladjust); ++ CLog::Log(LOGDEBUG, "CDVDPlayerAudio::%s pll:%.4f (%.4f) proportional:%.4f integral:%.4f", __FUNCTION__, m_plladjust, new_adjust, proportional, m_integral); ++ } + } + } + +@@ -735,6 +761,10 @@ bool CDVDPlayerAudio::OutputPacket(DVDAudioFrame &audioframe) + m_dvdAudio.SetResampleRatio(m_resampleratio); + m_dvdAudio.AddPackets(audioframe); + } ++ else if (m_synctype == SYNC_PLLADJUST) ++ { ++ m_dvdAudio.AddPackets(audioframe); ++ } + + return true; + } +diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.h b/xbmc/cores/dvdplayer/DVDPlayerAudio.h +index e8b2ab6..02c64a0 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerAudio.h ++++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.h +@@ -232,6 +232,7 @@ class CDVDPlayerAudio : public CThread, public IDVDStreamPlayerAudio + bool m_prevskipped; + double m_maxspeedadjust; + double m_resampleratio; //resample ratio when using SYNC_RESAMPLE, used for the codec info ++ double m_plladjust; // for display using SYNC_PLLADJUST + + struct SInfo + { +diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp +index 34e0108..3cd8e18 100644 +--- a/xbmc/linux/RBP.cpp ++++ b/xbmc/linux/RBP.cpp +@@ -230,4 +230,17 @@ void CRBP::ResumeVideoOutput() + CLog::Log(LOGDEBUG, "Raspberry PI resuming video output\n"); + } + ++double CRBP::AdjustHDMIClock(double adjust) ++{ ++ char response[80]; ++ vc_gencmd(response, sizeof response, "hdmi_adjust_clock %f", adjust); ++ float new_adjust = 1.0f; ++ char *p = strchr(response, '='); ++ if (p) ++ new_adjust = atof(p+1); ++ CLog::Log(LOGDEBUG, "CRBP::%s(%.4f) = %.4f", __func__, adjust, new_adjust); ++ return new_adjust; ++} ++ ++ + #endif +diff --git a/xbmc/linux/RBP.h b/xbmc/linux/RBP.h +index f947acc..606c24f 100644 +--- a/xbmc/linux/RBP.h ++++ b/xbmc/linux/RBP.h +@@ -58,6 +58,7 @@ class CRBP + unsigned char *CaptureDisplay(int width, int height, int *stride, bool swap_red_blue, bool video_only = true); + DllOMX *GetDllOMX() { return m_OMX ? m_OMX->GetDll() : NULL; } + void WaitVsync(); ++ double AdjustHDMIClock(double adjust); + + void SuspendVideoOutput(); + void ResumeVideoOutput(); + +From 750cc5eba141ad091b036a57682d67076cbefa90 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 21 Sep 2014 18:31:31 +0100 +Subject: [PATCH 82/82] hack: revert squash: don't update originaldts when + marked as invalid + +--- + xbmc/cores/dvdplayer/DVDPlayer.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index 6547880..32374d4 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -2106,6 +2106,7 @@ void CDVDPlayer::CheckContinuity(CCurrentStream& current, DemuxPacket* pPacket) + // not sure yet - flags the packets as unknown until we get confirmation on another audio/video packet + pPacket->dts = DVD_NOPTS_VALUE; + pPacket->pts = DVD_NOPTS_VALUE; ++ current.originaldts = pPacket->dts; + } + } + else