[meta-freescale] [chromium-imx][PATCH] Update patches for meta-browser master
Tom Hochstein
tom.hochstein at nxp.com
Tue Jun 13 16:26:24 PDT 2017
This builds but unfortunately does not enable the VPU.
Offering the patch in case someone else can look at it.
Signed-off-by: Tom Hochstein <tom.hochstein at nxp.com>
---
README.md | 4 +-
...video-decode-accelerator-to-Chromium-GPU-.patch | 171 ----
...-video-decode-accelerator-to-Chromium-v53.patch | 187 ++++
...-video-decode-accelerator-to-Chromium-v54.patch | 172 ++++
.../common/gpu/media/imx_gl_viv_direct_texture.cc | 38 -
.../common/gpu/media/imx_gl_viv_direct_texture.h | 55 -
.../gpu/media/imxvpu_video_decode_accelerator.cc | 746 --------------
.../gpu/media/imxvpu_video_decode_accelerator.h | 107 --
src/content/common/gpu/media/imxvpucodec.h | 418 --------
.../common/gpu/media/imxvpucodec_fslwrapper.c | 1055 --------------------
.../common/gpu/media/imxvpucodec_platform.h | 35 -
.../gpu/media/imxvpucodec_platform_chromium.cc | 40 -
.../gpu/media/imxvpucodec_platform_chromium.h | 71 --
src/media/gpu/imx_gl_viv_direct_texture.cc | 38 +
src/media/gpu/imx_gl_viv_direct_texture.h | 55 +
src/media/gpu/imxvpu_video_decode_accelerator.cc | 767 ++++++++++++++
src/media/gpu/imxvpu_video_decode_accelerator.h | 112 +++
src/media/gpu/imxvpucodec.h | 418 ++++++++
src/media/gpu/imxvpucodec_fslwrapper.c | 1055 ++++++++++++++++++++
src/media/gpu/imxvpucodec_platform.h | 35 +
src/media/gpu/imxvpucodec_platform_chromium.cc | 40 +
src/media/gpu/imxvpucodec_platform_chromium.h | 71 ++
22 files changed, 2952 insertions(+), 2738 deletions(-)
delete mode 100644 patches/common/0002-Add-VPU-video-decode-accelerator-to-Chromium-GPU-.patch
create mode 100644 patches/common/0002-Add-VPU-video-decode-accelerator-to-Chromium-v53.patch
create mode 100644 patches/common/0002-Add-VPU-video-decode-accelerator-to-Chromium-v54.patch
delete mode 100644 src/content/common/gpu/media/imx_gl_viv_direct_texture.cc
delete mode 100644 src/content/common/gpu/media/imx_gl_viv_direct_texture.h
delete mode 100644 src/content/common/gpu/media/imxvpu_video_decode_accelerator.cc
delete mode 100644 src/content/common/gpu/media/imxvpu_video_decode_accelerator.h
delete mode 100644 src/content/common/gpu/media/imxvpucodec.h
delete mode 100644 src/content/common/gpu/media/imxvpucodec_fslwrapper.c
delete mode 100644 src/content/common/gpu/media/imxvpucodec_platform.h
delete mode 100644 src/content/common/gpu/media/imxvpucodec_platform_chromium.cc
delete mode 100644 src/content/common/gpu/media/imxvpucodec_platform_chromium.h
create mode 100644 src/media/gpu/imx_gl_viv_direct_texture.cc
create mode 100644 src/media/gpu/imx_gl_viv_direct_texture.h
create mode 100644 src/media/gpu/imxvpu_video_decode_accelerator.cc
create mode 100644 src/media/gpu/imxvpu_video_decode_accelerator.h
create mode 100644 src/media/gpu/imxvpucodec.h
create mode 100644 src/media/gpu/imxvpucodec_fslwrapper.c
create mode 100644 src/media/gpu/imxvpucodec_platform.h
create mode 100644 src/media/gpu/imxvpucodec_platform_chromium.cc
create mode 100644 src/media/gpu/imxvpucodec_platform_chromium.h
diff --git a/README.md b/README.md
index 10af946..4babe8a 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ This repository contains sources which add hardware video decoding support to Ch
using the Freescale i.MX VPU. They are placed under the BSD 3-clause license. See the
LICENSE file for details.
-These sources are written against Chromium 48.0.2548.0.
+These sources are written against Chromium 53.0.2785.143 and 54.0.2810.2.
Prerequisites
@@ -17,7 +17,7 @@ of decoded frames.
Also, Freescale's libfslvpuwrap library is required. Use at least version 1.0.45.
-Furthermore, Chromium must be ran with its EGL backend enabled. Use the --use-gl=egl option for this.
+Furthermore, Chromium must be run with its EGL backend enabled. Use the --use-gl=egl option for this.
Patching Chromium
diff --git a/patches/common/0002-Add-VPU-video-decode-accelerator-to-Chromium-GPU-.patch b/patches/common/0002-Add-VPU-video-decode-accelerator-to-Chromium-GPU-.patch
deleted file mode 100644
index 87368fc..0000000
--- a/patches/common/0002-Add-VPU-video-decode-accelerator-to-Chromium-GPU-.patch
+++ /dev/null
@@ -1,171 +0,0 @@
-From b80573b80dd42a5aa00c4d2f463e5fede1edfef0 Mon Sep 17 00:00:00 2001
-From: Carlos Rafael Giani <dv at pseudoterminal.org>
-Date: Thu, 25 Sep 2014 22:54:28 +0200
-Subject: [PATCH] Add VPU video decode accelerator to Chromium GPU media
- stack
-
-Upstream-Status: Inappropriate [other]
-Upstream currently does not accept patches for video acceleration in Linux
-
-Signed-off-by: Carlos Rafael Giani <dv at pseudoterminal.org>
----
- build/common.gypi | 3 ++
- .../gpu/media/gpu_video_decode_accelerator.cc | 7 +++++
- content/content_common.gypi | 34 ++++++++++++++++++++++
- gpu/config/software_rendering_list_json.cc | 5 ++--
- ui/gl/gl_implementation.h | 4 +--
- 5 files changed, 49 insertions(+), 4 deletions(-)
-
---- a/build/common.gypi
-+++ b/build/common.gypi
-@@ -1271,6 +1271,9 @@
- # Use system ICU instead of bundled one.
- 'use_system_icu%' : 0,
-
-+ # Whether or not the target platform is based on the i.MX SoC
-+ 'imx_platform%': 1,
-+
- # Default to enabled PIE; this is important for ASLR but we may need to be
- # able to turn it off for various reasons.
- 'linux_disable_pie%': 0,
---- a/content/common/gpu/media/gpu_video_decode_accelerator.h
-+++ b/content/common/gpu/media/gpu_video_decode_accelerator.h
-@@ -77,6 +77,7 @@
- class MessageFilter;
-
- scoped_ptr<media::VideoDecodeAccelerator> CreateDXVAVDA();
-+ scoped_ptr<media::VideoDecodeAccelerator> CreateImxVpuVDA();
- scoped_ptr<media::VideoDecodeAccelerator> CreateV4L2VDA();
- scoped_ptr<media::VideoDecodeAccelerator> CreateV4L2SliceVDA();
- scoped_ptr<media::VideoDecodeAccelerator> CreateVaapiVDA();
---- a/content/common/gpu/media/gpu_video_decode_accelerator.cc
-+++ b/content/common/gpu/media/gpu_video_decode_accelerator.cc
-@@ -31,6 +31,8 @@
- #if defined(OS_WIN)
- #include "base/win/windows_version.h"
- #include "content/common/gpu/media/dxva_video_decode_accelerator.h"
-+#elif defined(IMX_PLATFORM)
-+#include "content/common/gpu/media/imxvpu_video_decode_accelerator.h"
- #elif defined(OS_MACOSX)
- #include "content/common/gpu/media/vt_video_decode_accelerator.h"
- #elif defined(OS_CHROMEOS)
-@@ -258,6 +260,7 @@
- // same as the order of querying supported profiles of VDAs.
- const GpuVideoDecodeAccelerator::CreateVDAFp create_vda_fps[] = {
- &GpuVideoDecodeAccelerator::CreateDXVAVDA,
-+ &GpuVideoDecodeAccelerator::CreateImxVpuVDA,
- &GpuVideoDecodeAccelerator::CreateV4L2VDA,
- &GpuVideoDecodeAccelerator::CreateV4L2SliceVDA,
- &GpuVideoDecodeAccelerator::CreateVaapiVDA,
-@@ -298,6 +301,18 @@
- return decoder.Pass();
- }
-
-+scoped_ptr<media::VideoDecodeAccelerator>
-+GpuVideoDecodeAccelerator::CreateImxVpuVDA() {
-+ scoped_ptr<media::VideoDecodeAccelerator> decoder;
-+#if defined(IMX_PLATFORM)
-+ DVLOG(0) << "Using the i.MX6 VPU decode accelerator";
-+ decoder.reset(new ImxVpuVideoDecodeAccelerator(
-+ stub_->decoder()->AsWeakPtr(),
-+ make_context_current_));
-+#endif
-+ return decoder.Pass();
-+}
-+
- scoped_ptr<media::VideoDecodeAccelerator>
- GpuVideoDecodeAccelerator::CreateV4L2VDA() {
- scoped_ptr<media::VideoDecodeAccelerator> decoder;
-@@ -426,6 +426,8 @@
- profiles = VTVideoDecodeAccelerator::GetSupportedProfiles();
- #elif defined(OS_ANDROID)
- profiles = AndroidVideoDecodeAccelerator::GetSupportedProfiles();
-+#elif defined(IMX_PLATFORM)
-+ profiles = ImxVpuVideoDecodeAccelerator::GetSupportedProfiles();
- #endif
- return GpuVideoAcceleratorUtil::ConvertMediaToGpuDecodeProfiles(profiles);
- }
---- a/content/content_common.gypi
-+++ b/content/content_common.gypi
-@@ -802,6 +802,40 @@
- 'common/gpu/media/avda_state_provider.h',
- ],
- }],
-+ ['target_arch == "arm" and imx_platform == 1', {
-+ 'dependencies': [
-+ '../ui/gl/gl.gyp:gl',
-+ ],
-+ 'variables': {
-+ 'conditions': [
-+ ['sysroot!=""', {
-+ 'pkg-config': '../build/linux/pkg-config-wrapper "<(sysroot)" "<(target_arch)"',
-+ }, {
-+ 'pkg-config': 'pkg-config'
-+ }],
-+ ],
-+ },
-+ 'sources': [
-+ 'common/gpu/media/imx_gl_viv_direct_texture.cc',
-+ 'common/gpu/media/imx_gl_viv_direct_texture.h',
-+ 'common/gpu/media/imxvpucodec_fslwrapper.c',
-+ 'common/gpu/media/imxvpucodec.h',
-+ 'common/gpu/media/imxvpucodec_platform_chromium.cc',
-+ 'common/gpu/media/imxvpucodec_platform_chromium.h',
-+ 'common/gpu/media/imxvpucodec_platform.h',
-+ 'common/gpu/media/imxvpu_video_decode_accelerator.cc',
-+ 'common/gpu/media/imxvpu_video_decode_accelerator.h',
-+ ],
-+ 'defines': ['IMX_PLATFORM'],
-+ 'cflags': [
-+ '<!@(<(pkg-config) --cflags libfslvpuwrap)',
-+ ],
-+ 'link_settings': {
-+ 'libraries': [
-+ '<!@(<(pkg-config) --libs libfslvpuwrap)',
-+ ],
-+ },
-+ }],
- ['OS=="android" and enable_webrtc==1', {
- 'dependencies': [
- '../third_party/libyuv/libyuv.gyp:libyuv',
---- a/gpu/config/software_rendering_list_json.cc
-+++ b/gpu/config/software_rendering_list_json.cc
-@@ -464,7 +464,8 @@
- "all"
- ]
- },
-- {
-+ // 48 disabled for i.MX6 integration
-+/* {
- "id": 48,
- "description": "Accelerated video decode is unavailable on Linux",
- "cr_bugs": [137247],
-@@ -474,7 +475,7 @@
- "features": [
- "accelerated_video_decode"
- ]
-- },
-+ },*/
- {
- "id": 49,
- "description": "NVidia GeForce GT 650M can cause the system to hang with flash 3D",
---- a/ui/gl/gl_implementation.h
-+++ b/ui/gl/gl_implementation.h
-@@ -97,7 +97,7 @@
- GLImplementation GetNamedGLImplementation(const std::string& name);
-
- // Get the name of a GL implementation.
--const char* GetGLImplementationName(GLImplementation implementation);
-+GL_EXPORT const char* GetGLImplementationName(GLImplementation implementation);
-
- // Add a native library to those searched for GL entry points.
- void AddGLNativeLibrary(base::NativeLibrary library);
-@@ -116,7 +116,7 @@
- // and when querying functions from the EGL library supplied by Android, it may
- // return a function that prints a log message about the function being
- // unsupported.
--void* GetGLProcAddress(const char* name);
-+GL_EXPORT void* GetGLProcAddress(const char* name);
-
- // Return information about the GL window system binding implementation (e.g.,
- // EGL, GLX, WGL). Returns true if the information was retrieved successfully.
diff --git a/patches/common/0002-Add-VPU-video-decode-accelerator-to-Chromium-v53.patch b/patches/common/0002-Add-VPU-video-decode-accelerator-to-Chromium-v53.patch
new file mode 100644
index 0000000..97dec57
--- /dev/null
+++ b/patches/common/0002-Add-VPU-video-decode-accelerator-to-Chromium-v53.patch
@@ -0,0 +1,187 @@
+From b80573b80dd42a5aa00c4d2f463e5fede1edfef0 Mon Sep 17 00:00:00 2001
+From: Carlos Rafael Giani <dv at pseudoterminal.org>
+Date: Thu, 25 Sep 2014 22:54:28 +0200
+Subject: [PATCH] Add VPU video decode accelerator to Chromium GPU media
+ stack
+
+Upstream-Status: Inappropriate [other]
+Upstream currently does not accept patches for video acceleration in Linux
+
+Signed-off-by: Carlos Rafael Giani <dv at pseudoterminal.org>
+---
+ build/common.gypi | 3 ++
+ gpu/config/software_rendering_list_json.cc | 5 ++--
+ .../gpu_video_decode_accelerator_factory_impl.cc | 22 ++++++++++++++
+ .../gpu_video_decode_accelerator_factory_impl.h | 5 ++++
+ media/media_gpu.gypi | 34 ++++++++++++++++++++++
+ ui/gl/gl_implementation.h | 2 +-
+ 6 files changed, 68 insertions(+), 3 deletions(-)
+
+diff --git a/build/common.gypi b/build/common.gypi
+index f5d107d..3275219 100644
+--- a/build/common.gypi
++++ b/build/common.gypi
+@@ -1279,6 +1279,9 @@
+ # Use system ICU instead of bundled one.
+ 'use_system_icu%' : 0,
+
++ # Whether or not the target platform is based on the i.MX SoC
++ 'imx_platform%': 1,
++
+ # Default to enabled PIE; this is important for ASLR but we may need to be
+ # able to turn it off for various reasons.
+ 'linux_disable_pie%': 0,
+diff --git a/gpu/config/software_rendering_list_json.cc b/gpu/config/software_rendering_list_json.cc
+index b10e52a..6c3441d 100644
+--- a/gpu/config/software_rendering_list_json.cc
++++ b/gpu/config/software_rendering_list_json.cc
+@@ -430,7 +430,8 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST(
+ "all"
+ ]
+ },
+- {
++ // 48 disabled for i.MX6 integration
++/* {
+ "id": 48,
+ "description": "Accelerated video decode is unavailable on Linux",
+ "cr_bugs": [137247],
+@@ -440,7 +441,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST(
+ "features": [
+ "accelerated_video_decode"
+ ]
+- },
++ },*/
+ {
+ "id": 50,
+ "description": "Disable VMware software renderer on older Mesa",
+diff --git a/media/gpu/gpu_video_decode_accelerator_factory_impl.cc b/media/gpu/gpu_video_decode_accelerator_factory_impl.cc
+index 0c5e76e..d6620fa 100644
+--- a/media/gpu/gpu_video_decode_accelerator_factory_impl.cc
++++ b/media/gpu/gpu_video_decode_accelerator_factory_impl.cc
+@@ -12,6 +12,8 @@
+ #if defined(OS_WIN)
+ #include "base/win/windows_version.h"
+ #include "media/gpu/dxva_video_decode_accelerator_win.h"
++#elif defined(IMX_PLATFORM)
++#include "media/gpu/imxvpu_video_decode_accelerator.h"
+ #elif defined(OS_MACOSX)
+ #include "media/gpu/vt_video_decode_accelerator_mac.h"
+ #elif defined(OS_CHROMEOS)
+@@ -79,6 +81,9 @@ GpuVideoDecodeAcceleratorFactoryImpl::GetDecoderCapabilities(
+ #if defined(OS_WIN)
+ capabilities.supported_profiles =
+ DXVAVideoDecodeAccelerator::GetSupportedProfiles();
++#elif defined(IMX_PLATFORM)
++ capabilities.supported_profiles =
++ ImxVpuVideoDecodeAccelerator::GetSupportedProfiles();
+ #elif defined(OS_CHROMEOS)
+ VideoDecodeAccelerator::SupportedProfiles vda_profiles;
+ #if defined(USE_V4L2_CODEC)
+@@ -127,6 +132,9 @@ GpuVideoDecodeAcceleratorFactoryImpl::CreateVDA(
+ #if defined(OS_WIN)
+ &GpuVideoDecodeAcceleratorFactoryImpl::CreateDXVAVDA,
+ #endif
++#if defined(IMX_PLATFORM)
++ &GpuVideoDecodeAcceleratorFactoryImpl::CreateImxVpuVDA,
++#endif
+ #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
+ &GpuVideoDecodeAcceleratorFactoryImpl::CreateV4L2VDA,
+ &GpuVideoDecodeAcceleratorFactoryImpl::CreateV4L2SVDA,
+@@ -169,6 +177,20 @@ GpuVideoDecodeAcceleratorFactoryImpl::CreateDXVAVDA(
+ }
+ #endif
+
++#if defined(IMX_PLATFORM)
++std::unique_ptr<VideoDecodeAccelerator>
++GpuVideoDecodeAcceleratorFactoryImpl::CreateImxVpuVDA(
++ const gpu::GpuDriverBugWorkarounds& workarounds,
++ const gpu::GpuPreferences& gpu_preferences) const {
++ std::unique_ptr<VideoDecodeAccelerator> decoder;
++ DVLOG(0) << "Using the i.MX6 VPU decode accelerator";
++ decoder.reset(new ImxVpuVideoDecodeAccelerator(
++ make_context_current_cb_,
++ get_gles2_decoder_cb_));
++ return decoder;
++}
++#endif
++
+ #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
+ std::unique_ptr<VideoDecodeAccelerator>
+ GpuVideoDecodeAcceleratorFactoryImpl::CreateV4L2VDA(
+diff --git a/media/gpu/gpu_video_decode_accelerator_factory_impl.h b/media/gpu/gpu_video_decode_accelerator_factory_impl.h
+index faa01d3..ec514df 100644
+--- a/media/gpu/gpu_video_decode_accelerator_factory_impl.h
++++ b/media/gpu/gpu_video_decode_accelerator_factory_impl.h
+@@ -93,6 +93,11 @@ class MEDIA_GPU_EXPORT GpuVideoDecodeAcceleratorFactoryImpl {
+ const gpu::GpuDriverBugWorkarounds& workarounds,
+ const gpu::GpuPreferences& gpu_preferences) const;
+ #endif
++#if defined(IMX_PLATFORM)
++ std::unique_ptr<VideoDecodeAccelerator> CreateImxVpuVDA(
++ const gpu::GpuDriverBugWorkarounds& workarounds,
++ const gpu::GpuPreferences& gpu_preferences) const;
++#endif
+ #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
+ std::unique_ptr<VideoDecodeAccelerator> CreateV4L2VDA(
+ const gpu::GpuDriverBugWorkarounds& workarounds,
+diff --git a/media/media_gpu.gypi b/media/media_gpu.gypi
+index 8bea3e2..921ad63 100644
+--- a/media/media_gpu.gypi
++++ b/media/media_gpu.gypi
+@@ -95,6 +95,40 @@
+ },
+ ],
+ }],
++ ['target_arch == "arm" and imx_platform == 1', {
++ 'dependencies': [
++ '../ui/gl/gl.gyp:gl',
++ ],
++ 'variables': {
++ 'conditions': [
++ ['sysroot!=""', {
++ 'pkg-config': '../build/linux/pkg-config-wrapper "<(sysroot)" "<(target_arch)"',
++ }, {
++ 'pkg-config': 'pkg-config'
++ }],
++ ],
++ },
++ 'sources': [
++ 'gpu/imx_gl_viv_direct_texture.cc',
++ 'gpu/imx_gl_viv_direct_texture.h',
++ 'gpu/imxvpucodec_fslwrapper.c',
++ 'gpu/imxvpucodec.h',
++ 'gpu/imxvpucodec_platform_chromium.cc',
++ 'gpu/imxvpucodec_platform_chromium.h',
++ 'gpu/imxvpucodec_platform.h',
++ 'gpu/imxvpu_video_decode_accelerator.cc',
++ 'gpu/imxvpu_video_decode_accelerator.h',
++ ],
++ 'defines': ['IMX_PLATFORM'],
++ 'cflags': [
++ '<!@(<(pkg-config) --cflags libfslvpuwrap)',
++ ],
++ 'link_settings': {
++ 'libraries': [
++ '<!@(<(pkg-config) --libs libfslvpuwrap)',
++ ],
++ },
++ }],
+ ['OS=="android"', {
+ 'dependencies': [
+ '../media/media.gyp:media',
+diff --git a/ui/gl/gl_implementation.h b/ui/gl/gl_implementation.h
+index 7b41771..7321280 100644
+--- a/ui/gl/gl_implementation.h
++++ b/ui/gl/gl_implementation.h
+@@ -117,7 +117,7 @@ GL_EXPORT void SetGLGetProcAddressProc(GLGetProcAddressProc proc);
+ // and when querying functions from the EGL library supplied by Android, it may
+ // return a function that prints a log message about the function being
+ // unsupported.
+-void* GetGLProcAddress(const char* name);
++GL_EXPORT void* GetGLProcAddress(const char* name);
+
+ // Return information about the GL window system binding implementation (e.g.,
+ // EGL, GLX, WGL). Returns true if the information was retrieved successfully.
+--
+1.9.1
+
diff --git a/patches/common/0002-Add-VPU-video-decode-accelerator-to-Chromium-v54.patch b/patches/common/0002-Add-VPU-video-decode-accelerator-to-Chromium-v54.patch
new file mode 100644
index 0000000..0e1e5a0
--- /dev/null
+++ b/patches/common/0002-Add-VPU-video-decode-accelerator-to-Chromium-v54.patch
@@ -0,0 +1,172 @@
+From b4ff8c098ced8ab0f48abeb0579e82b4b5f402cc Mon Sep 17 00:00:00 2001
+From: Carlos Rafael Giani <dv at pseudoterminal.org>
+Date: Thu, 25 Sep 2014 22:54:28 +0200
+Subject: [PATCH] Add VPU video decode accelerator to Chromium GPU media stack
+
+Upstream-Status: Inappropriate [other]
+Upstream currently does not accept patches for video acceleration in Linux
+
+Signed-off-by: Carlos Rafael Giani <dv at pseudoterminal.org>
+---
+ build/common.gypi | 3 ++
+ gpu/config/software_rendering_list_json.cc | 5 ++--
+ media/gpu/gpu_video_decode_accelerator_factory.cc | 22 +++++++++++++++
+ media/gpu/gpu_video_decode_accelerator_factory.h | 5 ++++
+ media/media_gpu.gypi | 34 +++++++++++++++++++++++
+ 5 files changed, 67 insertions(+), 2 deletions(-)
+
+diff --git a/build/common.gypi b/build/common.gypi
+index f84d9f6..86fc8dd 100644
+--- a/build/common.gypi
++++ b/build/common.gypi
+@@ -1283,6 +1283,9 @@
+ # Use system ICU instead of bundled one.
+ 'use_system_icu%' : 0,
+
++ # Whether or not the target platform is based on the i.MX SoC
++ 'imx_platform%': 1,
++
+ # Default to enabled PIE; this is important for ASLR but we may need to be
+ # able to turn it off for various reasons.
+ 'linux_disable_pie%': 0,
+diff --git a/gpu/config/software_rendering_list_json.cc b/gpu/config/software_rendering_list_json.cc
+index 440fd81..24b19886 100644
+--- a/gpu/config/software_rendering_list_json.cc
++++ b/gpu/config/software_rendering_list_json.cc
+@@ -434,7 +434,8 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST(
+ "all"
+ ]
+ },
+- {
++ // 48 disabled for i.MX6 integration
++/* {
+ "id": 48,
+ "description": "Accelerated video decode is unavailable on Linux",
+ "cr_bugs": [137247],
+@@ -444,7 +445,7 @@ const char kSoftwareRenderingListJson[] = LONG_STRING_CONST(
+ "features": [
+ "accelerated_video_decode"
+ ]
+- },
++ },*/
+ {
+ "id": 50,
+ "description": "Disable VMware software renderer on older Mesa",
+diff --git a/media/gpu/gpu_video_decode_accelerator_factory.cc b/media/gpu/gpu_video_decode_accelerator_factory.cc
+index a78c554..40ceca9 100644
+--- a/media/gpu/gpu_video_decode_accelerator_factory.cc
++++ b/media/gpu/gpu_video_decode_accelerator_factory.cc
+@@ -12,6 +12,8 @@
+ #if defined(OS_WIN)
+ #include "base/win/windows_version.h"
+ #include "media/gpu/dxva_video_decode_accelerator_win.h"
++#elif defined(IMX_PLATFORM)
++#include "media/gpu/imxvpu_video_decode_accelerator.h"
+ #elif defined(OS_MACOSX)
+ #include "media/gpu/vt_video_decode_accelerator_mac.h"
+ #elif defined(OS_CHROMEOS)
+@@ -79,6 +81,9 @@ GpuVideoDecodeAcceleratorFactory::GetDecoderCapabilities(
+ #if defined(OS_WIN)
+ capabilities.supported_profiles =
+ DXVAVideoDecodeAccelerator::GetSupportedProfiles(gpu_preferences);
++#elif defined(IMX_PLATFORM)
++ capabilities.supported_profiles =
++ ImxVpuVideoDecodeAccelerator::GetSupportedProfiles();
+ #elif defined(OS_CHROMEOS)
+ VideoDecodeAccelerator::SupportedProfiles vda_profiles;
+ #if defined(USE_V4L2_CODEC)
+@@ -127,6 +132,9 @@ GpuVideoDecodeAcceleratorFactory::CreateVDA(
+ #if defined(OS_WIN)
+ &GpuVideoDecodeAcceleratorFactory::CreateDXVAVDA,
+ #endif
++#if defined(IMX_PLATFORM)
++ &GpuVideoDecodeAcceleratorFactory::CreateImxVpuVDA,
++#endif
+ #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
+ &GpuVideoDecodeAcceleratorFactory::CreateV4L2VDA,
+ &GpuVideoDecodeAcceleratorFactory::CreateV4L2SVDA,
+@@ -169,6 +177,20 @@ GpuVideoDecodeAcceleratorFactory::CreateDXVAVDA(
+ }
+ #endif
+
++#if defined(IMX_PLATFORM)
++std::unique_ptr<VideoDecodeAccelerator>
++GpuVideoDecodeAcceleratorFactory::CreateImxVpuVDA(
++ const gpu::GpuDriverBugWorkarounds& workarounds,
++ const gpu::GpuPreferences& gpu_preferences) const {
++ std::unique_ptr<VideoDecodeAccelerator> decoder;
++ DVLOG(0) << "Using the i.MX6 VPU decode accelerator";
++ decoder.reset(new ImxVpuVideoDecodeAccelerator(
++ make_context_current_cb_,
++ get_gles2_decoder_cb_));
++ return decoder;
++}
++#endif
++
+ #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
+ std::unique_ptr<VideoDecodeAccelerator>
+ GpuVideoDecodeAcceleratorFactory::CreateV4L2VDA(
+diff --git a/media/gpu/gpu_video_decode_accelerator_factory.h b/media/gpu/gpu_video_decode_accelerator_factory.h
+index 29d1d7a..239acd2 100644
+--- a/media/gpu/gpu_video_decode_accelerator_factory.h
++++ b/media/gpu/gpu_video_decode_accelerator_factory.h
+@@ -90,6 +90,11 @@ class MEDIA_GPU_EXPORT GpuVideoDecodeAcceleratorFactory {
+ const gpu::GpuDriverBugWorkarounds& workarounds,
+ const gpu::GpuPreferences& gpu_preferences) const;
+ #endif
++#if defined(IMX_PLATFORM)
++ std::unique_ptr<VideoDecodeAccelerator> CreateImxVpuVDA(
++ const gpu::GpuDriverBugWorkarounds& workarounds,
++ const gpu::GpuPreferences& gpu_preferences) const;
++#endif
+ #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
+ std::unique_ptr<VideoDecodeAccelerator> CreateV4L2VDA(
+ const gpu::GpuDriverBugWorkarounds& workarounds,
+diff --git a/media/media_gpu.gypi b/media/media_gpu.gypi
+index 3485d68..d4375281 100644
+--- a/media/media_gpu.gypi
++++ b/media/media_gpu.gypi
+@@ -96,6 +96,40 @@
+ },
+ ],
+ }],
++ ['target_arch == "arm" and imx_platform == 1', {
++ 'dependencies': [
++ '../ui/gl/gl.gyp:gl',
++ ],
++ 'variables': {
++ 'conditions': [
++ ['sysroot!=""', {
++ 'pkg-config': '../build/linux/pkg-config-wrapper "<(sysroot)" "<(target_arch)"',
++ }, {
++ 'pkg-config': 'pkg-config'
++ }],
++ ],
++ },
++ 'sources': [
++ 'gpu/imx_gl_viv_direct_texture.cc',
++ 'gpu/imx_gl_viv_direct_texture.h',
++ 'gpu/imxvpucodec_fslwrapper.c',
++ 'gpu/imxvpucodec.h',
++ 'gpu/imxvpucodec_platform_chromium.cc',
++ 'gpu/imxvpucodec_platform_chromium.h',
++ 'gpu/imxvpucodec_platform.h',
++ 'gpu/imxvpu_video_decode_accelerator.cc',
++ 'gpu/imxvpu_video_decode_accelerator.h',
++ ],
++ 'defines': ['IMX_PLATFORM'],
++ 'cflags': [
++ '<!@(<(pkg-config) --cflags libfslvpuwrap)',
++ ],
++ 'link_settings': {
++ 'libraries': [
++ '<!@(<(pkg-config) --libs libfslvpuwrap)',
++ ],
++ },
++ }],
+ ['OS=="android"', {
+ 'dependencies': [
+ '../media/media.gyp:media',
+--
+1.9.1
+
diff --git a/src/content/common/gpu/media/imx_gl_viv_direct_texture.cc b/src/content/common/gpu/media/imx_gl_viv_direct_texture.cc
deleted file mode 100644
index 3d208bb..0000000
--- a/src/content/common/gpu/media/imx_gl_viv_direct_texture.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "ui/gl/gl_implementation.h"
-#include "imx_gl_viv_direct_texture.h"
-
-
-bool init_viv_direct_texture(gfx::GLContext &context, GLESVIVDirectTextureProcs &procs)
-{
- VLOG(1) << "Initializing Vivante direct texture GLES extension";
-
- gfx::GLImplementation glimpl = gfx::GetGLImplementation();
- if (glimpl != gfx::kGLImplementationEGLGLES2)
- {
- LOG(INFO) << "Cannot initialize direct textures - GL implementation is "
- << gfx::GetGLImplementationName(glimpl)
- << ", expected " <<
- gfx::GetGLImplementationName(gfx::kGLImplementationEGLGLES2);
- return false;
- }
-
- // Newer Vivante drivers call the extension GL_VIV_tex_direct instead of GL_VIV_direct_texture,
- // even though it is the same extension
- if (context.HasExtension("GL_VIV_direct_texture"))
- VLOG(1) << "GL_VIV_direct_texture supported";
- else if (context.HasExtension("GL_VIV_tex_direct"))
- VLOG(1) << "GL_VIV_tex_direct supported";
- else
- {
- VLOG(1) << "Neither GL_VIV_direct_texture nor GL_VIV_tex_direct supported";
- return false;
- }
-
- procs.TexDirectVIV = reinterpret_cast < PFNGLTEXDIRECTVIVPROC > (gfx::GetGLProcAddress("glTexDirectVIV"));
- procs.TexDirectVIVMap = reinterpret_cast < PFNGLTEXDIRECTVIVMAPPROC > (gfx::GetGLProcAddress("glTexDirectVIVMap"));
- procs.TexDirectTiledMapVIV = reinterpret_cast < PFNGLTEXDIRECTTILEDMAPVIVPROC > (gfx::GetGLProcAddress("glTexDirectTiledMapVIV"));
- procs.TexDirectInvalidateVIV = reinterpret_cast < PFNGLTEXDIRECTINVALIDATEVIVPROC > (gfx::GetGLProcAddress("glTexDirectInvalidateVIV"));
-
- return true;
-}
-
diff --git a/src/content/common/gpu/media/imx_gl_viv_direct_texture.h b/src/content/common/gpu/media/imx_gl_viv_direct_texture.h
deleted file mode 100644
index ab56905..0000000
--- a/src/content/common/gpu/media/imx_gl_viv_direct_texture.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef IMX_GL_VIV_DIRECT_TEXTURE_H
-#define IMX_GL_VIV_DIRECT_TEXTURE_H
-
-#include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
-
-
-/* GL_VIV_direct_texture */
-#ifndef GL_VIV_direct_texture
-#define GL_VIV_YV12 0x8FC0
-#define GL_VIV_NV12 0x8FC1
-#define GL_VIV_YUY2 0x8FC2
-#define GL_VIV_UYVY 0x8FC3
-#define GL_VIV_NV21 0x8FC4
-#define GL_VIV_I420 0x8FC5
-#endif
-
-
-#ifndef GL_APICALL
-#define GL_APICALL KHRONOS_APICALL
-#endif
-
-#ifndef GL_APIENTRY
-#define GL_APIENTRY KHRONOS_APIENTRY
-#endif
-
-#ifndef GL_APIENTRYP
-#define GL_APIENTRYP GL_APIENTRY*
-#endif
-
-
-/* GL_VIV_direct_texture */
-#ifndef GL_VIV_direct_texture
-#define GL_VIV_direct_texture 1
-
-typedef void (GL_APIENTRYP PFNGLTEXDIRECTVIVPROC) (GLenum Target, GLsizei Width, GLsizei Height, GLenum Format, GLvoid ** Pixels);
-typedef void (GL_APIENTRYP PFNGLTEXDIRECTVIVMAPPROC) (GLenum Target, GLsizei Width, GLsizei Height, GLenum Format, GLvoid ** Logical, const GLuint * Physical);
-typedef void (GL_APIENTRYP PFNGLTEXDIRECTTILEDMAPVIVPROC) (GLenum Target, GLsizei Width, GLsizei Height, GLenum Format, GLvoid ** Logical, const GLuint * Physical);
-typedef void (GL_APIENTRYP PFNGLTEXDIRECTINVALIDATEVIVPROC) (GLenum Target);
-
-#endif
-
-struct GLESVIVDirectTextureProcs
-{
- PFNGLTEXDIRECTVIVPROC TexDirectVIV;
- PFNGLTEXDIRECTVIVMAPPROC TexDirectVIVMap;
- PFNGLTEXDIRECTTILEDMAPVIVPROC TexDirectTiledMapVIV;
- PFNGLTEXDIRECTINVALIDATEVIVPROC TexDirectInvalidateVIV;
-};
-
-
-bool init_viv_direct_texture(gfx::GLContext &context, GLESVIVDirectTextureProcs &procs);
-
-
-#endif
diff --git a/src/content/common/gpu/media/imxvpu_video_decode_accelerator.cc b/src/content/common/gpu/media/imxvpu_video_decode_accelerator.cc
deleted file mode 100644
index f96145c..0000000
--- a/src/content/common/gpu/media/imxvpu_video_decode_accelerator.cc
+++ /dev/null
@@ -1,746 +0,0 @@
-#include <iomanip>
-#include "media/base/limits.h"
-#include "base/bind.h"
-#include "base/memory/singleton.h"
-#include "content/common/gpu/media/imxvpu_video_decode_accelerator.h"
-#include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_implementation.h"
-
-
-namespace content
-{
-
-
-namespace
-{
-
-
-class ImxVpuLoadSingleton
-{
-public:
- static ImxVpuLoadSingleton* GetInstance()
- {
- return base::Singleton < ImxVpuLoadSingleton > ::get();
- }
-
- bool Load()
- {
- base::AutoLock auto_lock(lock_);
-
- ImxVpuDecReturnCodes ret;
-
- if ((ret = imx_vpu_dec_load()) != IMX_VPU_DEC_RETURN_CODE_OK)
- {
- LOG(ERROR) << "Could not load VPU: " << imx_vpu_dec_error_string(ret);
- return false;
- }
- else
- return true;
- }
-
- bool Unload()
- {
- base::AutoLock auto_lock(lock_);
-
- ImxVpuDecReturnCodes ret;
-
- if ((ret = imx_vpu_dec_unload()) != IMX_VPU_DEC_RETURN_CODE_OK)
- {
- LOG(ERROR) << "Could not unload VPU: " << imx_vpu_dec_error_string(ret);
- return false;
- }
- else
- return true;
- }
-
-private:
- ImxVpuLoadSingleton()
- {
- }
-
- friend struct base::DefaultSingletonTraits < ImxVpuLoadSingleton >;
-
- DISALLOW_COPY_AND_ASSIGN(ImxVpuLoadSingleton);
-
- base::Lock lock_;
-};
-
-
-} // unnamed namespace end
-
-static const media::VideoCodecProfile kSupportedProfiles[] = {
- media::H264PROFILE_BASELINE,
- media::H264PROFILE_MAIN,
- media::H264PROFILE_HIGH,
- media::H264PROFILE_MAX,
- media::VP8PROFILE_ANY,
-};
-
-
-ImxVpuVideoDecodeAccelerator::ImxVpuVideoDecodeAccelerator(base::WeakPtr < gpu::gles2::GLES2Decoder > const gles2_decoder, base::Callback < bool(void) > const &make_context_current)
- : gles2_decoder_(gles2_decoder)
- , make_context_current_(make_context_current)
- , vpu_decoder_(NULL)
- , initial_info_received_(false)
- , message_loop_(base::MessageLoop::current())
-{
- vpu_bitstream_buffer_block_.virtual_address = NULL;
-}
-
-
-ImxVpuVideoDecodeAccelerator::~ImxVpuVideoDecodeAccelerator()
-{
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
-}
-
-
-bool ImxVpuVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile, Client *client)
-{
- gfx::GLContext *context;
-
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
-
- client_ptr_factory_.reset(new base::WeakPtrFactory < Client > (client));
- client_ = client_ptr_factory_->GetWeakPtr();
-
- base::AutoLock auto_lock(lock_);
-
- LOG(INFO) << "Initializing i.MX VPU decoder";
-
- if (!make_context_current_.Run())
- {
- LOG(ERROR) << "Failed to make this decoder's GL context current.";
- return false;
- }
-
- if ((context = gles2_decoder_->GetGLContext()) == NULL)
- {
- LOG(ERROR) << "GLES2 context is NULL";
- return false;
- }
-
- if (!init_viv_direct_texture(*context, direct_texture_procs_))
- {
- LOG(ERROR) << "Initializing the direct texture extension failed";
- return false;
- }
-
- if ((profile >= media::H264PROFILE_MIN) && (profile <= media::H264PROFILE_MAX))
- {
- codec_format_ = IMX_VPU_CODEC_FORMAT_H264;
- VLOG(1) << "Setting h.264 as codec format";
- }
- else if ((profile >= media::VP8PROFILE_MIN) && (profile <= media::VP8PROFILE_MAX))
- {
- codec_format_ = IMX_VPU_CODEC_FORMAT_VP8;
- VLOG(1) << "Setting VP8 as codec format";
- }
- else
- {
- VLOG(1) << "Unsupported profile";
- return false;
- }
-
- VLOG(1) << "Loading VPU";
- if (!(ImxVpuLoadSingleton::GetInstance()->Load()))
- return false;
-
- if (!AllocateVpuBitstreamBuffer())
- {
- ImxVpuLoadSingleton::GetInstance()->Unload();
- return false;
- }
-
- VLOG(1) << "Opening decoder";
- if (!OpenDecoder())
- {
- ImxVpuLoadSingleton::GetInstance()->Unload();
- return false;
- }
-
- VLOG(1) << "Initialization done";
-
- return true;
-}
-
-
-void ImxVpuVideoDecodeAccelerator::Decode(media::BitstreamBuffer const &bitstream_buffer)
-{
- VLOG(3) << "Decoding bitstream buffer";
-
- base::AutoLock auto_lock(lock_);
-
- input_queue_.push(bitstream_buffer);
- ProcessQueuedInput();
-}
-
-
-void ImxVpuVideoDecodeAccelerator::AssignPictureBuffers(std::vector < media::PictureBuffer > const &buffers)
-{
- DCHECK(output_picture_buffers_.empty());
- DCHECK(buffers.size() == vpu_framebuffers_.size());
-
- base::AutoLock auto_lock(lock_);
-
- VLOG(1) << buffers.size() << " picture buffers are being provided by the client";
-
-
- // without this call, the GL calls below would not use the correct context
- make_context_current_.Run();
-
- for (size_t i = 0; i < buffers.size(); ++i)
- {
- int32 id = buffers[i].id();
-
- output_picture_buffers_.insert(std::make_pair(id, buffers[i]));
-
- ImxVpuFramebuffer &framebuffer = vpu_framebuffers_[i];
- framebuffer.user_data = reinterpret_cast < void* > (id);
-
- // associate VIV direct textures with VPU framebuffers (one texture per framebuffer)
- // by mapping the framebuffer to the direct texture
- // only needs to be done once, since this mapping doesn't change
- GLuint picture_buffer_texture_id = buffers[i].texture_id();
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, picture_buffer_texture_id);
-
- GLvoid *virt_addr = framebuffer.virtual_address;
- GLuint phys_addr = reinterpret_cast < GLuint > (framebuffer.physical_address);
-
- direct_texture_procs_.TexDirectVIVMap(
- GL_TEXTURE_2D,
- aligned_width_, aligned_height_,
- GL_VIV_I420,
- &virt_addr, &phys_addr
- );
-
- VLOG(1)
- << "Associating picture buffer " << i << "/" << buffers.size() << " ID " << id << " with framebuffer #" << i << std::hex
- << " virtual address " << std::setfill('0') << std::setw(8) << reinterpret_cast < void* > (virt_addr)
- << " physical address " << std::setfill('0') << std::setw(8) << reinterpret_cast < void* > (phys_addr)
- << std::dec;
- }
-
-
- ProcessQueuedInput();
-}
-
-
-void ImxVpuVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id)
-{
- base::AutoLock auto_lock(lock_);
-
- VLOG(3) << "Reusing picture buffer with ID " << picture_buffer_id;
-
- for (size_t i = 0; i < vpu_framebuffers_.size(); ++i)
- {
- ImxVpuFramebuffer &framebuffer = vpu_framebuffers_[i];
- int32 id = reinterpret_cast < int32 > (framebuffer.user_data);
- if (id == picture_buffer_id)
- {
- ImxVpuDecReturnCodes ret;
-
- if ((ret = imx_vpu_dec_mark_framebuffer_as_displayed(vpu_decoder_, &framebuffer)) != IMX_VPU_DEC_RETURN_CODE_OK)
- {
- LOG(ERROR) << "Marking framebuffer for picture buffer with ID " << picture_buffer_id << "as displayed failed : " << imx_vpu_dec_error_string(ret);
- }
- else
- ProcessQueuedInput();
-
- return;
- }
- }
-
- LOG(WARNING) << "Picture buffer ID " << picture_buffer_id << " could not be associated with a framebuffer";
-}
-
-
-void ImxVpuVideoDecodeAccelerator::Flush()
-{
- base::AutoLock auto_lock(lock_);
-
- VLOG(2) << "Flush: processing all currently queued input bitstream buffers";
- ProcessQueuedInput();
-
- VLOG(2) << "Flush: draining VPU decoder";
- imx_vpu_dec_set_drain_mode(vpu_decoder_, 1);
- while (true)
- {
- ProcessRetval pretval = ProcessInput(NULL);
- if (pretval != ProcessOK)
- break;
- // TODO: handle ProcessFail (ProcessEOS should just cause the loop to terminate)
- }
- imx_vpu_dec_set_drain_mode(vpu_decoder_, 0);
-
- VLOG(2) << "Flush: done";
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(
- &Client::NotifyFlushDone,
- client_
- )
- );
-
-}
-
-
-void ImxVpuVideoDecodeAccelerator::Reset()
-{
- base::AutoLock auto_lock(lock_);
-
- VLOG(2) << "Reset: flushing decoder";
- imx_vpu_dec_flush(vpu_decoder_);
-
- VLOG(2) << "Reset: ending all queued bitstream buffers";
- while (!input_queue_.empty())
- {
- int32 bitstream_buffer_id = input_queue_.front().id();
- input_queue_.pop();
-
- if (bitstream_buffer_id != -1)
- {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(
- &Client::NotifyEndOfBitstreamBuffer,
- client_, bitstream_buffer_id
- )
- );
- }
- }
-
- BitstreamBufferQueue empty_queue;
- std::swap(input_queue_, empty_queue);
-
- VLOG(2) << "Reset: done";
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(
- &Client::NotifyResetDone,
- client_
- )
- );
-}
-
-
-void ImxVpuVideoDecodeAccelerator::Destroy()
-{
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
- Cleanup();
- delete this;
-}
-
-
-// static
-media::VideoDecodeAccelerator::SupportedProfiles
-ImxVpuVideoDecodeAccelerator::GetSupportedProfiles()
-{
- SupportedProfiles profiles;
- for (const auto& supported_profile : kSupportedProfiles) {
- SupportedProfile profile;
- profile.profile = supported_profile;
- profile.min_resolution.SetSize(64, 64);
- profile.max_resolution.SetSize(1920, 1088);
- profiles.push_back(profile);
- }
- return profiles;
-}
-
-
-bool ImxVpuVideoDecodeAccelerator::CanDecodeOnIOThread()
-{
- return false;
-}
-
-
-void ImxVpuVideoDecodeAccelerator::Cleanup()
-{
- DCHECK_EQ(message_loop_, base::MessageLoop::current());
-
- base::AutoLock auto_lock(lock_);
- client_ptr_factory_.reset();
-
- CloseDecoder();
-
- DeallocateVpuBitstreamBuffer();
-
- ImxVpuLoadSingleton::GetInstance()->Unload();
-}
-
-
-bool ImxVpuVideoDecodeAccelerator::OpenDecoder()
-{
- lock_.AssertAcquired();
-
- ImxVpuDecOpenParams open_params;
-
- open_params.codec_format = codec_format_;
-
- open_params.enable_frame_reordering = (codec_format_ == IMX_VPU_CODEC_FORMAT_H264) ? 1 : 0;
-
- // frame width & height are read from the bitstream
- open_params.frame_width = 0;
- open_params.frame_height = 0;
-
- if (imx_vpu_dec_open(&(vpu_decoder_), &open_params, vpu_bitstream_buffer_block_.virtual_address, vpu_bitstream_buffer_block_.physical_address) != IMX_VPU_DEC_RETURN_CODE_OK)
- return false;
-
- return true;
-}
-
-
-void ImxVpuVideoDecodeAccelerator::CloseDecoder()
-{
- lock_.AssertAcquired();
-
- if (vpu_decoder_ == NULL)
- return;
-
- imx_vpu_dec_close(vpu_decoder_);
- DeallocateVpuFramebuffers();
-
- vpu_decoder_ = NULL;
-}
-
-
-bool ImxVpuVideoDecodeAccelerator::AllocateVpuBitstreamBuffer()
-{
- lock_.AssertAcquired();
-
- ImxVpuDecReturnCodes ret;
-
- imx_vpu_dec_get_bitstream_buffer_info(&(vpu_bitstream_buffer_block_.alignment), &(vpu_bitstream_buffer_block_.size));
- if ((ret = imx_vpu_dec_allocate_memory(&vpu_bitstream_buffer_block_)) != IMX_VPU_DEC_RETURN_CODE_OK)
- {
- LOG(ERROR) << "Allocating VPU bitstream buffer failed: " << imx_vpu_dec_error_string(ret);
- return false;
- }
- else
- return true;
-}
-
-
-bool ImxVpuVideoDecodeAccelerator::DeallocateVpuBitstreamBuffer()
-{
- lock_.AssertAcquired();
-
- ImxVpuDecReturnCodes ret;
-
- if (vpu_bitstream_buffer_block_.virtual_address == NULL)
- return true;
-
- if ((ret = imx_vpu_dec_deallocate_memory(&vpu_bitstream_buffer_block_)) != IMX_VPU_DEC_RETURN_CODE_OK)
- {
- LOG(ERROR) << "Deallocating VPU bitstream buffer failed: " << imx_vpu_dec_error_string(ret);
- return false;
- }
- else
- return true;
-}
-
-
-bool ImxVpuVideoDecodeAccelerator::AllocateAndRegisterVPUFramebuffers()
-{
- lock_.AssertAcquired();
-
- ImxVpuDecReturnCodes ret;
- unsigned int y_stride, cbcr_stride, y_size, cbcr_size, mvcol_size, total_size;
-
- aligned_width_ = vpu_dec_initial_info_.frame_width;
- aligned_height_ = vpu_dec_initial_info_.frame_height;
-
- imx_vpu_dec_calc_framebuffer_sizes(
- &vpu_dec_initial_info_,
- &aligned_width_, &aligned_height_,
- &y_stride, &cbcr_stride,
- &y_size, &cbcr_size,
- &mvcol_size,
- &total_size
- );
-
- vpu_framebuffers_.resize(vpu_dec_initial_info_.min_num_required_framebuffers + media::limits::kMaxVideoFrames);
- vpu_framebuffer_mem_blocks_.resize(vpu_framebuffers_.size());
- memset(&(vpu_framebuffers_[0]), 0, sizeof(ImxVpuFramebuffer) * vpu_framebuffers_.size());
- memset(&(vpu_framebuffer_mem_blocks_[0]), 0, sizeof(ImxVpuMemBlock) * vpu_framebuffers_.size());
-
- for (unsigned int i = 0; i < vpu_framebuffers_.size(); ++i)
- {
- ImxVpuFramebuffer &framebuffer = vpu_framebuffers_[i];
- ImxVpuMemBlock &memblock = vpu_framebuffer_mem_blocks_[i];
-
- memblock.size = total_size;
- memblock.alignment = vpu_dec_initial_info_.framebuffer_alignment;
- if (imx_vpu_dec_allocate_memory(&memblock) != IMX_VPU_DEC_RETURN_CODE_OK)
- {
- LOG(ERROR) << "Could not allocate framebuffer memory for framebuffer " << i << "/" << vpu_framebuffers_.size();
- memblock.physical_address = 0;
- return false;
- }
-
- framebuffer.y_stride = y_stride;
- framebuffer.cbcr_stride = cbcr_stride;
- framebuffer.virtual_address = memblock.virtual_address;
- framebuffer.physical_address = memblock.physical_address;
- framebuffer.y_offset = 0;
- framebuffer.cb_offset = y_size;
- framebuffer.cr_offset = y_size + cbcr_size;
- framebuffer.mvcol_offset = y_size + cbcr_size * 2;
- }
-
- if ((ret = imx_vpu_dec_register_framebuffers(vpu_decoder_, &(vpu_framebuffers_[0]), vpu_framebuffers_.size())) != IMX_VPU_DEC_RETURN_CODE_OK)
- {
- LOG(ERROR) << "Registering framebuffers failed: " << imx_vpu_dec_error_string(ret);
- return false;
- }
- else
- return true;
-}
-
-
-bool ImxVpuVideoDecodeAccelerator::DeallocateVpuFramebuffers()
-{
- lock_.AssertAcquired();
-
- for (unsigned int i = 0; i < vpu_framebuffer_mem_blocks_.size(); ++i)
- {
- ImxVpuMemBlock &memblock = vpu_framebuffer_mem_blocks_[i];
- if (memblock.physical_address != 0)
- {
- if (imx_vpu_dec_deallocate_memory(&memblock) != IMX_VPU_DEC_RETURN_CODE_OK)
- {
- LOG(ERROR) << "Deallocating memory block of framebuffer " << i << "/" << vpu_framebuffer_mem_blocks_.size() << " failed";
- }
- }
- }
- vpu_framebuffer_mem_blocks_.clear();
-
- return true;
-}
-
-
-void ImxVpuVideoDecodeAccelerator::ProcessQueuedInput()
-{
- lock_.AssertAcquired();
-
- VLOG(1) << "Input queue size: " << input_queue_.size();
-
- {
- if (input_queue_.empty())
- {
- VLOG(1) << "Input queue empty - nothing to process";
- return;
- }
-
- if (initial_info_received_ && output_picture_buffers_.empty())
- {
- VLOG(1) << "No picture buffers have been provided yet - will try again later";
- return;
- }
-
- if (initial_info_received_ && (imx_vpu_dec_get_num_free_framebuffers(vpu_decoder_) < imx_vpu_dec_get_min_num_free_required(vpu_decoder_)))
- {
- VLOG(1) << "Not enough free framebuffers available - will try again later";
- return;
- }
-
- media::BitstreamBuffer const &queued_bitstream_buffer = input_queue_.front();
- ProcessRetval ret = ProcessInput(&queued_bitstream_buffer);
- input_queue_.pop();
-
- if (ret != ProcessOK)
- return;
- }
-}
-
-
-ImxVpuVideoDecodeAccelerator::ProcessRetval ImxVpuVideoDecodeAccelerator::ProcessInput(media::BitstreamBuffer const *input_bitstream_buffer)
-{
- ImxVpuDecReturnCodes ret;
-
- lock_.AssertAcquired();
-
-
- ImxVpuEncodedFrame encoded_frame;
- scoped_ptr < base::SharedMemory > shm;
-
- // bitstream_buffer is NULL while draining
- if (input_bitstream_buffer != NULL)
- {
- VLOG(3) << "Processing input bitstream buffer with ID " << input_bitstream_buffer->id();
-
- shm.reset(new base::SharedMemory(input_bitstream_buffer->handle(), true));
- // The shared memory block is automatically unmapped by the destructor
- shm->Map(input_bitstream_buffer->size());
-
- // The stored bitstream IDs are incremented to make debug output clearer
- // (otherwise, the imxvpucodec debug printout will print (nil) for the ID 0,
- // 0x1 for the ID 1 etc.)
- encoded_frame.virtual_address = shm->memory();
- encoded_frame.data_size = input_bitstream_buffer->size();
- encoded_frame.user_data = reinterpret_cast < void* > (input_bitstream_buffer->id() + 1);
-
- VLOG(3) << "Creating encoded frame (data address " << encoded_frame.virtual_address << " size " << encoded_frame.data_size << " id " << input_bitstream_buffer->id();
- }
- else
- {
- VLOG(2) << "Setting input data to NULL";
-
- encoded_frame.virtual_address = NULL;
- encoded_frame.data_size = 0;
- encoded_frame.user_data = NULL;
- }
-
- encoded_frame.codec_data = NULL;
- encoded_frame.codec_data_size = 0;
-
-
- unsigned int output_code;
- if ((ret = imx_vpu_dec_decode_frame(vpu_decoder_, &encoded_frame, &output_code)) != IMX_VPU_DEC_RETURN_CODE_OK)
- {
- LOG(ERROR) << "Decoding frame failed: " << imx_vpu_dec_error_string(ret);
- return ProcessFailed;
- }
-
- VLOG(1) << "Output code of decoded frame: 0x" << std::hex << output_code;
-
- if (input_bitstream_buffer != NULL)
- {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(
- &Client::NotifyEndOfBitstreamBuffer,
- client_,
- input_bitstream_buffer->id()
- )
- );
- }
-
- if (output_code & (IMX_VPU_DEC_OUTPUT_CODE_INITIAL_INFO_AVAILABLE | IMX_VPU_DEC_OUTPUT_CODE_RESOLUTION_CHANGED))
- {
- VLOG(1) << "Initial information is available - retrieving";
-
- if ((ret = imx_vpu_dec_get_initial_info(vpu_decoder_, &vpu_dec_initial_info_)) != IMX_VPU_DEC_RETURN_CODE_OK)
- {
- LOG(ERROR) << "Retrieving initial info failed: " << imx_vpu_dec_error_string(ret);
- return ProcessFailed;
- }
-
- VLOG(1) << "Initial info: frame size " << vpu_dec_initial_info_.frame_width << "x" << vpu_dec_initial_info_.frame_height << " min num required framebuffers: " << vpu_dec_initial_info_.min_num_required_framebuffers;
-
- if (
- !DeallocateVpuFramebuffers() ||
- !AllocateAndRegisterVPUFramebuffers()
- )
- return ProcessFailed;
-
- initial_info_received_ = true;
-
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(
- &Client::ProvidePictureBuffers,
- client_,
- vpu_framebuffers_.size(),
- gfx::Size(aligned_width_, aligned_height_),
- GL_TEXTURE_2D
- )
- );
- }
-
- ProcessRetval pretval = (output_code & IMX_VPU_DEC_OUTPUT_CODE_EOS) ? ProcessEOS : ProcessOK;
-
- int32 bitstream_buffer_id = 0;
- if (output_code & IMX_VPU_DEC_OUTPUT_CODE_FRAME_OUTPUT)
- {
- ImxVpuDecodedFrame decoded_frame;
- if ((ret = imx_vpu_dec_get_decoded_frame(vpu_decoder_, &decoded_frame)) != IMX_VPU_DEC_RETURN_CODE_OK)
- {
- LOG(ERROR) << "Retrieving decoded frame failed: " << imx_vpu_dec_error_string(ret);
- return ProcessFailed;
- }
-
- bitstream_buffer_id = reinterpret_cast < int32 > (decoded_frame.user_data) - 1;
-
- VLOG(3) << "Decoded frame was retrieved, bitstream buffer id " << bitstream_buffer_id;
-
- if (decoded_frame.framebuffer == NULL)
- {
- LOG(ERROR) << "Framebuffer of decoded frame is NULL";
- pretval = ProcessFailed;
- }
- else
- {
- if (!ProcessOutput(*(decoded_frame.framebuffer), bitstream_buffer_id))
- {
- // if ProcessOutput returns false, then no picture buffer has
- // been sent to the client, so the decoded frame must be returned
- // to the VPU pool here
- VLOG(1) << "ProcessOutput failed -> returning decoded frame to internal VPU pool";
- imx_vpu_dec_mark_framebuffer_as_displayed(vpu_decoder_, decoded_frame.framebuffer);
- pretval = ProcessFailed;
- }
-
- // if processing the output was successful, the framebuffer is
- // _not_ marked as displayed here; this is done in ReusePictureBuffer(),
- // because only then it is certain that the client is done with that frame
- }
- }
- else if (output_code & IMX_VPU_DEC_OUTPUT_CODE_DROPPED)
- {
- void *user_data = imx_vpu_dec_get_dropped_frame_user_data(vpu_decoder_);
- bitstream_buffer_id = reinterpret_cast < int32 > (user_data) - 1;
- VLOG(2) << "Frame was dropped, bitstream buffer id " << bitstream_buffer_id;
- }
-
- return pretval;
-}
-
-
-bool ImxVpuVideoDecodeAccelerator::ProcessOutput(ImxVpuFramebuffer const &output_framebuffer, int32 input_bitstream_buffer_id)
-{
- lock_.AssertAcquired();
-
- int32 picture_buffer_id = reinterpret_cast < int32 > (output_framebuffer.user_data);
- OutputBufferMap::const_iterator iter = output_picture_buffers_.find(picture_buffer_id);
- if (iter == output_picture_buffers_.end())
- {
- LOG(ERROR) << "No picture buffer with ID " << picture_buffer_id << " found";
- return false;
- }
- GLuint picture_buffer_texture_id = iter->second.texture_id();
-
- make_context_current_.Run();
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, picture_buffer_texture_id);
-
- direct_texture_procs_.TexDirectInvalidateVIV(GL_TEXTURE_2D);
-
- gles2_decoder_->RestoreTextureUnitBindings(0);
- gles2_decoder_->RestoreActiveTexture();
-
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(
- &Client::PictureReady,
- client_,
- media::Picture(
- picture_buffer_id,
- input_bitstream_buffer_id,
- gfx::Rect(
- 0,
- 0,
- vpu_dec_initial_info_.frame_width,
- vpu_dec_initial_info_.frame_height
- ),
- false
- )
- )
- );
-
- return true;
-}
-
-
-} // namespace content
diff --git a/src/content/common/gpu/media/imxvpu_video_decode_accelerator.h b/src/content/common/gpu/media/imxvpu_video_decode_accelerator.h
deleted file mode 100644
index 2447379..0000000
--- a/src/content/common/gpu/media/imxvpu_video_decode_accelerator.h
+++ /dev/null
@@ -1,107 +0,0 @@
-#ifndef CONTENT_COMMON_GPU_MEDIA_IMXVPU_VIDEO_DECODE_ACCELERATOR_H_
-#define CONTENT_COMMON_GPU_MEDIA_IMXVPU_VIDEO_DECODE_ACCELERATOR_H_
-
-#include <list>
-#include <map>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/memory/linked_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/compiler_specific.h"
-#include "base/synchronization/lock.h"
-#include "content/common/content_export.h"
-#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
-#include "media/base/bitstream_buffer.h"
-#include "media/video/picture.h"
-#include "media/video/video_decode_accelerator.h"
-
-#include "imxvpucodec.h"
-#include "imx_gl_viv_direct_texture.h"
-
-
-namespace content
-{
-
-
-class CONTENT_EXPORT ImxVpuVideoDecodeAccelerator
- : public media::VideoDecodeAccelerator
-{
-public:
- explicit ImxVpuVideoDecodeAccelerator(base::WeakPtr < gpu::gles2::GLES2Decoder > const gles2_decoder, base::Callback < bool(void) > const &make_context_current);
- virtual ~ImxVpuVideoDecodeAccelerator();
-
- virtual bool Initialize(media::VideoCodecProfile profile, Client *client) override;
- virtual void Decode(media::BitstreamBuffer const &bitstream_buffer) override;
- virtual void AssignPictureBuffers(std::vector < media::PictureBuffer > const &buffers) override;
- virtual void ReusePictureBuffer(int32 picture_buffer_id) override;
- virtual void Flush() override;
- virtual void Reset() override;
- virtual void Destroy() override;
- virtual bool CanDecodeOnIOThread() override;
-
- static media::VideoDecodeAccelerator::SupportedProfiles GetSupportedProfiles();
-
-private:
- enum ProcessRetval
- {
- ProcessOK,
- ProcessEOS,
- ProcessFailed
- };
-
- void Cleanup();
-
- // VPU specifics
- bool OpenDecoder();
- void CloseDecoder();
- bool AllocateVpuBitstreamBuffer();
- bool DeallocateVpuBitstreamBuffer();
- bool AllocateAndRegisterVPUFramebuffers();
- bool DeallocateVpuFramebuffers();
-
- // Bitstream buffer and framebuffer processing
- void ProcessQueuedInput();
- ProcessRetval ProcessInput(media::BitstreamBuffer const *input_bitstream_buffer);
- bool ProcessOutput(ImxVpuFramebuffer const &output_framebuffer, int32 input_bitstream_buffer_id);
-
-
- scoped_ptr < base::WeakPtrFactory < Client > > client_ptr_factory_;
- base::WeakPtr < Client > client_;
-
- base::WeakPtr < gpu::gles2::GLES2Decoder > const gles2_decoder_;
- base::Callback < bool(void) > make_context_current_;
-
- typedef std::vector < ImxVpuFramebuffer > ImxVpuFramebuffers;
- typedef std::vector < ImxVpuMemBlock > ImxVpuMemBlocks;
- ImxVpuDecoder *vpu_decoder_;
- ImxVpuCodecFormats codec_format_;
- ImxVpuMemBlock vpu_bitstream_buffer_block_;
- ImxVpuDecInitialInfo vpu_dec_initial_info_;
- ImxVpuFramebuffers vpu_framebuffers_;
- ImxVpuMemBlocks vpu_framebuffer_mem_blocks_;
- unsigned int aligned_width_, aligned_height_;
- bool initial_info_received_;
-
- GLESVIVDirectTextureProcs direct_texture_procs_;
-
- base::Lock lock_;
-
- typedef std::queue < media::BitstreamBuffer > BitstreamBufferQueue;
- BitstreamBufferQueue input_queue_;
-
- typedef std::map < int32, media::PictureBuffer > OutputBufferMap;
- OutputBufferMap output_picture_buffers_;
-
- // ChildThread's message loop
- base::MessageLoop* message_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(ImxVpuVideoDecodeAccelerator);
-};
-
-
-} // namespace content end
-
-
-#endif // CONTENT_COMMON_GPU_MEDIA_IMXVPU_VIDEO_DECODE_ACCELERATOR_H_
diff --git a/src/content/common/gpu/media/imxvpucodec.h b/src/content/common/gpu/media/imxvpucodec.h
deleted file mode 100644
index 4fb63b3..0000000
--- a/src/content/common/gpu/media/imxvpucodec.h
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * imxvpucodec - i.MX6 VPU hardware codec engine API library
- * Copyright (c) 2014 Carlos Rafael Giani
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any
- * damages arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute
- * it freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must
- * not claim that you wrote the original software. If you use this
- * software in a product, an acknowledgment in the product
- * documentation would be appreciated but is not required.
- *
- * 2. Altered source versions must be plainly marked as such, and must
- * not be misrepresented as being the original software.
- *
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-
-#ifndef IMXVPUCODEC_H
-#define IMXVPUCODEC_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-
-/* This library provides a high-level interface for controlling the Freescale
- * i.MX VPU en/decoder.
- * Other libraries do not provide a way of associating frames with user defined
- * information, and lack calls to check the number of currently free framebuffers
- * (when decoding). The former is required by many media frameworks such as
- * GStreamer, FFmpeg/libav, the Chromium media codebase etc. The latter is
- * necessary when framebuffer display and decoding can happen in different
- * threads (the counter makes it possible to use synchronization primitives
- * like thread condition variables to wait until enough frames are free).
- *
- * Note that the functions are _not_ thread safe. If they may be called from
- * different threads, you must make sure they are surrounded by a mutex lock.
- * It is recommended to use one global mutex for the imx_vpu_*_load()/unload()
- * functions, and another de/encoder instance specific mutex for all of the other
- * calls.
- *
- * How to use the decoder (error handling omitted for clarity):
- * 1. Call imx_vpu_dec_load()
- * 2. Call imx_vpu_dec_get_bitstream_buffer_info(), and allocate a DMA buffer
- * with the given size and alignment.
- * 3. Fill an instance of ImxVpuDecOpenParams with the values specific to the
- * input data. In most cases, one wants to set enable_frame_reordering to 1
- * with h.264 data here.
- * 4. Call imx_vpu_dec_open(), passing in a pointer to the filled ImxVpuDecOpenParams
- * instance, and the virtual and physical addresses of the bitstream DMA buffer
- * which was allocated in step 2.
- * 5. Call imx_vpu_dec_decode_frame() with the first encoded frame.
- * If the output_code bitmask contains IMX_VPU_DEC_OUTPUT_CODE_INITIAL_INFO_AVAILABLE,
- * proceed, otherwise continue feeding in data.
- * 6. Once IMX_VPU_DEC_OUTPUT_CODE_INITIAL_INFO_AVAILABLE has been set in the output code,
- * call imx_vpu_dec_get_initial_info() with a pointer to an ImxVpuDecInitialInfo
- * instance.
- * 7. (Optional) Perform the necessary size and alignment calculations by calling
- * imx_vpu_dec_calc_framebuffer_sizes().
- * 8. Create an array of at least as many ImxVpuFramebuffer instances as specified in
- * min_num_required_framebuffers. Each instance must point to a DMA buffer that is big
- * enough to hold a frame. If step 7 was performed, allocating as many bytes as indicated
- * by total_size is enough. Make sure the Y,Cb,Cr,MvCol offsets in each ImxVpuFramebuffer
- * instance are valid.
- * 9. Call imx_vpu_dec_register_framebuffers() and pass in the ImxVpuFramebuffer array
- * and the number of ImxVpuFramebuffer instances.
- * 10. Continue calling imx_vpu_dec_decode_frame(). The virtual address in encoded_frame
- * must not be NULL.
- * If the IMX_VPU_DEC_OUTPUT_CODE_FRAME_OUTPUT flag is set in the output code,
- * call imx_vpu_dec_get_decoded_frame() with a pointer to an ImxVpuDecodedFrame instance
- * which gets filled with information about the decoded frame. Once the decoded frame
- * has been processed by the user, imx_vpu_dec_mark_framebuffer_as_displayed() must be
- * called to let the decoder know that the framebuffer is available for storing new
- * decoded frames again.
- * If IMX_VPU_DEC_OUTPUT_CODE_DROPPED is set, you can call
- * imx_vpu_dec_get_dropped_frame_user_data() to retrieve the user_data field
- * of the dropped frame. If IMX_VPU_DEC_OUTPUT_CODE_EOS is set, stop playback and close
- * the decoder.
- * 11. In case a flush/reset is desired (typically after seeking), call imx_vpu_dec_flush().
- * Note that any internal user_data pointers from the en/decoded frames will be
- * set to NULL after this call (this is the only exception where the library modifies
- * the user_data fields).
- * 12. When there is no more incoming data, and pending decoded frames need to be retrieved
- * from the decoder, call imx_vpu_dec_set_drain_mode(). This is typically necessary when
- * the data source reached its end, playback is finishing, and there is a delay
- * of N frames at the beginning.
- * After this call, continue calling imx_vpu_dec_decode_frame() to retrieve the pending
- * decoded frames, but the virtual address of encoded_frame must be NULL.
- * As in step 10, if IMX_VPU_DEC_OUTPUT_CODE_EOS is set, stop playback, close the decoder.
- * 13. After playback is finished, close the decoder with imx_vpu_dec_close().
- * 14. Deallocate framebuffer memory blocks and the bitstream buffer memory block.
- * 15. Call imx_vpu_dec_unload().
- *
- * Step 15 should only be called if no more playback sessions will occur.
- *
- * As mentioned before, in situations where decoding and display of decoded frames happen in
- * different thread, it is necessary to let the decoder wait until enough framebuffers
- * are free (= available for the VPU to decode into). This is typically done by such a check
- * (in pseudo code):
- *
- * mutex_lock(&mutex);
- *
- * while (imx_vpu_dec_get_num_free_framebuffers(decoder) < imx_vpu_dec_get_min_num_free_required(decoder))
- * condition_wait(&condition_variable, &mutex);
- *
- * imx_vpu_dec_decode_frame(decoder, encoded_frame, &output_code);
- * ...
- *
- * mutex_unlock(&mutex);
- */
-
-
-
-/***********************************************/
-/******* COMMON STRUCTURES AND FUNCTIONS *******/
-/***********************************************/
-
-
-#define IMX_VPU_ALIGN_VAL_TO(LENGTH, ALIGN_SIZE) ( ((uintptr_t)(((uint8_t*)(LENGTH)) + (ALIGN_SIZE) - 1) / (ALIGN_SIZE)) * (ALIGN_SIZE) )
-
-
-typedef uint32_t imx_vpu_phys_addr_t;
-typedef uint32_t imx_vpu_cpu_addr_t; /* used only in allocators so far */
-
-
-typedef enum
-{
- IMX_VPU_PIC_TYPE_UNKNOWN = 0,
- IMX_VPU_PIC_TYPE_I,
- IMX_VPU_PIC_TYPE_P,
- IMX_VPU_PIC_TYPE_B,
- IMX_VPU_PIC_TYPE_IDR,
- IMX_VPU_PIC_TYPE_BI,
- IMX_VPU_PIC_TYPE_SKIP
-}
-ImxVpuPicType;
-
-
-typedef enum
-{
- IMX_VPU_CODEC_FORMAT_MPEG2 = 0, /* includes MPEG1 */
- IMX_VPU_CODEC_FORMAT_MPEG4,
- IMX_VPU_CODEC_FORMAT_H263,
- IMX_VPU_CODEC_FORMAT_H264,
- IMX_VPU_CODEC_FORMAT_H264_MVC,
- IMX_VPU_CODEC_FORMAT_WMV3,
- IMX_VPU_CODEC_FORMAT_WVC1,
- IMX_VPU_CODEC_FORMAT_MJPEG,
- IMX_VPU_CODEC_FORMAT_VP8
- /* XXX others will be added when the firmware supports them */
-}
-ImxVpuCodecFormats;
-
-
-typedef enum
-{
- IMX_VPU_MJPEG_FORMAT_YUV420 = 0, /* also known as I420 */
- IMX_VPU_MJPEG_FORMAT_YUV422_HORIZONTAL = 1,
- IMX_VPU_MJPEG_FORMAT_YUV422_VERTICAL = 2, /* 4:2:2 vertical, actually 2:2:4 (according to the VPU docs) */
- IMX_VPU_MJPEG_FORMAT_YUV444 = 3,
- IMX_VPU_MJPEG_FORMAT_YUV400 = 4 /* 8-bit grayscale */
-}
-ImxVpuMJpegFormat;
-
-
-typedef struct
-{
- /* Stride of the Y and of the Cb&Cr components.
- * Specified in bytes. */
- unsigned int y_stride, cbcr_stride;
-
- /* The virtual address of is actually not used by the VPU,
- * and only of interest to the user. It can be NULL for cases
- * where only a physical address exists or where a virtual
- * address is not necessary. */
- void *virtual_address;
- /* The physical address must always be valid. */
- imx_vpu_phys_addr_t physical_address;
-
- /* These define the starting offsets of each component
- * relative to the start of the buffer. Specified in bytes.
- *
- * mvcol is the "co-located motion vector" data. */
- size_t
- y_offset,
- cb_offset,
- cr_offset,
- mvcol_offset;
-
- /* User-defined pointer. The library does not touch this value.
- * This can be used to identify framebuffers for example.
- * Not to be confused with the user_data fields of ImxVpuEncodedFrame
- * and ImxVpuDecodedFrame. */
- void *user_data;
-
- /* Internal, implementation-defined data. Do not modify. */
- void *internal;
-}
-ImxVpuFramebuffer;
-
-
-typedef struct
-{
- /* Virtual and physical addresses pointing to the encoded data.
- * The virtual address must always be valid. The physical address
- * is only required for encoding. */
- void *virtual_address;
- imx_vpu_phys_addr_t physical_address;
-
- /* Size of the encoded data, in bytes. */
- unsigned int data_size;
-
- /* Pointer to out-of-band codec/header data. If such data exists,
- * specify the pointer to the memory block containing the data,
- * as well as the size of the memory block (in bytes).
- * Set pointer and size for every encoded frame when decoding.
- * If no such data exists or is required, set pointer to NULL and
- * size to 0. */
- void *codec_data;
- unsigned int codec_data_size;
-
- /* User-defined pointer. The library does not touch this value.
- * This pointer and the one from the corresponding
- * decoded frame will have the same value. The library will
- * pass then through.
- * It can be used to identify frames and associated corresponding
- * en- and decoded frames for example. */
- void *user_data;
-}
-ImxVpuEncodedFrame;
-
-
-typedef struct
-{
- /* When decoding: pointer to the framebuffer containing the decoded frame.
- * When encoding: pointer to the framebuffer containing the frame to be encoded.
- * Must always be valid. */
- ImxVpuFramebuffer *framebuffer;
-
- /* picture type (I, P, B, ..) */
- ImxVpuPicType pic_type;
-
- /* User-defined pointer. The library does not touch this value.
- * This pointer and the one from the corresponding
- * encoded frame will have the same value. The library will
- * pass then through.
- * It can be used to identify frames and associated corresponding
- * en- and decoded frames for example. */
- void *user_data;
-}
-ImxVpuDecodedFrame;
-
-
-/* This structure is only used by the allocate/deallocate calls below,
- * which in turn are convenience calls that wrap VPU-provided DMA buffer
- * allocators. If a different DMA buffer allocator is used (like ION),
- * this structure does not have to be used. */
-typedef struct
-{
- size_t size;
- unsigned int alignment;
-
- void* virtual_address;
- imx_vpu_phys_addr_t physical_address;
- imx_vpu_cpu_addr_t cpu_address;
-
- void* virtual_address_unaligned;
- imx_vpu_phys_addr_t physical_address_unaligned;
-}
-ImxVpuMemBlock;
-
-
-
-
-/************************************************/
-/******* DECODER STRUCTURES AND FUNCTIONS *******/
-/************************************************/
-
-
-typedef struct _ImxVpuDecoder ImxVpuDecoder;
-
-
-typedef enum
-{
- IMX_VPU_DEC_RETURN_CODE_OK = 0,
- IMX_VPU_DEC_RETURN_CODE_ERROR,
- IMX_VPU_DEC_RETURN_CODE_INVALID_PARAMS,
- IMX_VPU_DEC_RETURN_CODE_INVALID_HANDLE,
- IMX_VPU_DEC_RETURN_CODE_INVALID_FRAMEBUFFER,
- IMX_VPU_DEC_RETURN_CODE_INSUFFICIENT_FRAMEBUFFERS,
- IMX_VPU_DEC_RETURN_CODE_INVALID_STRIDE,
- IMX_VPU_DEC_RETURN_CODE_WRONG_CALL_SEQUENCE,
- IMX_VPU_DEC_RETURN_CODE_TIMEOUT
-}
-ImxVpuDecReturnCodes;
-
-
-typedef enum
-{
- IMX_VPU_DEC_OUTPUT_CODE_INPUT_USED = (1UL << 0),
- IMX_VPU_DEC_OUTPUT_CODE_EOS = (1UL << 1),
- IMX_VPU_DEC_OUTPUT_CODE_FRAME_OUTPUT = (1UL << 2),
- IMX_VPU_DEC_OUTPUT_CODE_NO_FRAME_OUTPUT = (1UL << 3),
- IMX_VPU_DEC_OUTPUT_CODE_DROPPED = (1UL << 4),
- IMX_VPU_DEC_OUTPUT_CODE_NOT_ENOUGH_OUTPUT_FRAMES = (1UL << 5),
- IMX_VPU_DEC_OUTPUT_CODE_NOT_ENOUGH_INPUT_DATA = (1UL << 6),
- IMX_VPU_DEC_OUTPUT_CODE_INITIAL_INFO_AVAILABLE = (1UL << 7),
- IMX_VPU_DEC_OUTPUT_CODE_RESOLUTION_CHANGED = (1UL << 8),
- IMX_VPU_DEC_OUTPUT_CODE_DECODE_ONLY = (1UL << 9),
- IMX_VPU_DEC_OUTPUT_CODE_INTERNAL_RESET = (1UL << 10)
-}
-ImxVpuDecOutputCodes;
-
-
-typedef struct
-{
- ImxVpuCodecFormats codec_format;
-
- int enable_frame_reordering;
- unsigned int frame_width, frame_height;
-}
-ImxVpuDecOpenParams;
-
-
-typedef struct
-{
- /* Width of height of frames, in pixels. */
- unsigned int frame_width, frame_height;
- /* Frame rate ratio. */
- unsigned int frame_rate_numerator, frame_rate_denominator;
-
- /* Caller must register at least this many framebuffers
- * with the decoder. */
- unsigned int min_num_required_framebuffers;
-
- /* Pixel format of the decoded frames. For codec formats
- * other than motion JPEG, this value will always be
- * IMX_VPU_MJPEG_FORMAT_YUV420. */
- ImxVpuMJpegFormat mjpeg_source_format;
-
- /* 0 = no interlacing, 1 = interlacing. */
- int interlacing;
-
- /* Fixed point, shifted by 16.
- * Example: 1.0 -> floor(1.0*(1<<16)) = 0x10000
- * 0.5 -> floor(0.5*(1<<16)) = 0x8000 */
- unsigned int width_height_ratio;
-
- /* Physical framebuffer addresses must be aligned to this value. */
- unsigned int framebuffer_alignment;
-}
-ImxVpuDecInitialInfo;
-
-
-/* Returns a human-readable description of the error code.
- * Useful for logging. */
-char const * imx_vpu_dec_error_string(ImxVpuDecReturnCodes code);
-
-/* These two functions load/unload the decoder. Thanks to an internal reference
- * counter, it is safe to call these functions more than once. However, the
- * number of unload() calls must match the number of load() calls.
- *
- * The decoder must be loaded before doing anything else with the decoder.
- * Similarly, the decoder must not be unloaded before all decoder activities
- * have been finished. This includes opening/decoding decoder instances. */
-ImxVpuDecReturnCodes imx_vpu_dec_load(void);
-ImxVpuDecReturnCodes imx_vpu_dec_unload(void);
-
-/* Convenience allocator for allocating DMA buffers. */
-ImxVpuDecReturnCodes imx_vpu_dec_allocate_memory(ImxVpuMemBlock *mem_block);
-ImxVpuDecReturnCodes imx_vpu_dec_deallocate_memory(ImxVpuMemBlock *mem_block);
-
-/* Called before imx_vpu_dec_open(), it returns the alignment and size for the
- * physical memory block necessary for the decoder's bitstream buffer. The user
- * must allocate a DMA buffer of at least this size, and its physical address
- * must be aligned according to the alignment value. */
-void imx_vpu_dec_get_bitstream_buffer_info(unsigned int *alignment, size_t *size);
-
-ImxVpuDecReturnCodes imx_vpu_dec_open(ImxVpuDecoder **decoder, ImxVpuDecOpenParams const *open_params, void *bitstream_buffer_virtual_address, imx_vpu_phys_addr_t bitstream_buffer_physical_address);
-ImxVpuDecReturnCodes imx_vpu_dec_close(ImxVpuDecoder *decoder);
-
-ImxVpuDecReturnCodes imx_vpu_dec_set_drain_mode(ImxVpuDecoder *decoder, int enabled);
-ImxVpuDecReturnCodes imx_vpu_dec_flush(ImxVpuDecoder *decoder);
-
-ImxVpuDecReturnCodes imx_vpu_dec_register_framebuffers(ImxVpuDecoder *decoder, ImxVpuFramebuffer *framebuffers, unsigned int num_framebuffers);
-void imx_vpu_dec_calc_framebuffer_sizes(ImxVpuDecInitialInfo const *initial_info, unsigned int *frame_width, unsigned int *frame_height, unsigned int *y_stride, unsigned int *cbcr_stride, unsigned int *y_size, unsigned int *cbcr_size, unsigned int *mvcol_size, unsigned int *total_size);
-
-ImxVpuDecReturnCodes imx_vpu_dec_get_initial_info(ImxVpuDecoder *decoder, ImxVpuDecInitialInfo *info);
-
-ImxVpuDecReturnCodes imx_vpu_dec_decode_frame(ImxVpuDecoder *decoder, ImxVpuEncodedFrame const *encoded_frame, unsigned int *output_code);
-ImxVpuDecReturnCodes imx_vpu_dec_get_decoded_frame(ImxVpuDecoder *decoder, ImxVpuDecodedFrame *decoded_frame);
-void* imx_vpu_dec_get_dropped_frame_user_data(ImxVpuDecoder *decoder);
-int imx_vpu_dec_get_num_free_framebuffers(ImxVpuDecoder *decoder);
-int imx_vpu_dec_get_min_num_free_required(ImxVpuDecoder *decoder);
-ImxVpuDecReturnCodes imx_vpu_dec_mark_framebuffer_as_displayed(ImxVpuDecoder *decoder, ImxVpuFramebuffer const *framebuffer);
-
-
-
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif
-
diff --git a/src/content/common/gpu/media/imxvpucodec_fslwrapper.c b/src/content/common/gpu/media/imxvpucodec_fslwrapper.c
deleted file mode 100644
index e425060..0000000
--- a/src/content/common/gpu/media/imxvpucodec_fslwrapper.c
+++ /dev/null
@@ -1,1055 +0,0 @@
-/*
- * imxvpucodec - i.MX6 VPU hardware codec engine API library
- * Copyright (c) 2014 Carlos Rafael Giani
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any
- * damages arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute
- * it freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must
- * not claim that you wrote the original software. If you use this
- * software in a product, an acknowledgment in the product
- * documentation would be appreciated but is not required.
- *
- * 2. Altered source versions must be plainly marked as such, and must
- * not be misrepresented as being the original software.
- *
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <vpu_wrapper.h>
-#include "imxvpucodec.h"
-#include "imxvpucodec_platform.h"
-
-
-
-
-/***********************************************/
-/******* COMMON STRUCTURES AND FUNCTIONS *******/
-/***********************************************/
-
-
-#ifndef NULL
-#define NULL ((void*)0)
-#endif
-
-
-#ifndef TRUE
-#define TRUE (1)
-#endif
-
-
-#ifndef FALSE
-#define FALSE (0)
-#endif
-
-
-#ifndef BOOL
-#define BOOL int
-#endif
-
-
-static ImxVpuMJpegFormat convert_from_wrapper_mjpg_format(int format)
-{
- return (ImxVpuMJpegFormat)format;
-}
-
-
-static ImxVpuPicType convert_from_wrapper_pic_type(VpuPicType type)
-{
- switch (type)
- {
- case VPU_I_PIC: return IMX_VPU_PIC_TYPE_I;
- case VPU_P_PIC: return IMX_VPU_PIC_TYPE_P;
- case VPU_B_PIC: return IMX_VPU_PIC_TYPE_B;
- case VPU_IDR_PIC: return IMX_VPU_PIC_TYPE_IDR;
- case VPU_BI_PIC: return IMX_VPU_PIC_TYPE_BI;
- case VPU_SKIP_PIC: return IMX_VPU_PIC_TYPE_SKIP;
- default: return IMX_VPU_PIC_TYPE_UNKNOWN;
- }
-}
-
-
-static VpuCodStd convert_to_wrapper_codec_std(ImxVpuCodecFormats format)
-{
- switch (format)
- {
- case IMX_VPU_CODEC_FORMAT_MPEG4: return VPU_V_MPEG4;
- case IMX_VPU_CODEC_FORMAT_H263: return VPU_V_H263;
- case IMX_VPU_CODEC_FORMAT_H264: return VPU_V_AVC;
- case IMX_VPU_CODEC_FORMAT_H264_MVC: return VPU_V_AVC_MVC;
- case IMX_VPU_CODEC_FORMAT_WMV3: return VPU_V_VC1;
- case IMX_VPU_CODEC_FORMAT_WVC1: return VPU_V_VC1_AP;
- case IMX_VPU_CODEC_FORMAT_MPEG2: return VPU_V_MPEG2;
- case IMX_VPU_CODEC_FORMAT_MJPEG: return VPU_V_MJPG;
- case IMX_VPU_CODEC_FORMAT_VP8: return VPU_V_VP8;
- default: assert(FALSE);
- }
-
- return VPU_V_MPEG2; /* should never be reached */
-}
-
-
-static void convert_from_wrapper_mem_desc(VpuMemDesc *mem_desc, ImxVpuMemBlock *mem_block)
-{
- mem_block->size = mem_desc->nSize;
- mem_block->virtual_address_unaligned = (void*)(mem_desc->nVirtAddr);
- mem_block->physical_address_unaligned = mem_desc->nPhyAddr;
- mem_block->cpu_address = mem_desc->nCpuAddr;
-}
-
-
-static void convert_to_wrapper_mem_desc(ImxVpuMemBlock *mem_block, VpuMemDesc *mem_desc)
-{
- mem_desc->nSize = mem_block->size;
- mem_desc->nVirtAddr = (unsigned long)(mem_block->virtual_address_unaligned);
- mem_desc->nPhyAddr = mem_block->physical_address_unaligned;
- mem_desc->nCpuAddr = mem_block->cpu_address;
-}
-
-
-static void convert_to_wrapper_framebuffer(ImxVpuFramebuffer *fb, VpuFrameBuffer *wrapper_fb)
-{
- memset(wrapper_fb, 0, sizeof(VpuFrameBuffer));
-
- wrapper_fb->nStrideY = fb->y_stride;
- wrapper_fb->nStrideC = fb->cbcr_stride;
-
- wrapper_fb->pbufY = (unsigned char*)(fb->physical_address + fb->y_offset);
- wrapper_fb->pbufCb = (unsigned char*)(fb->physical_address + fb->cb_offset);
- wrapper_fb->pbufCr = (unsigned char*)(fb->physical_address + fb->cr_offset);
- wrapper_fb->pbufMvCol = (unsigned char*)(fb->physical_address + fb->mvcol_offset);
-}
-
-
-
-
-/************************************************/
-/******* DECODER STRUCTURES AND FUNCTIONS *******/
-/************************************************/
-
-
-#define MIN_NUM_FREE_FB_REQUIRED 6
-#define FRAME_ALIGN 16
-
-
-struct _ImxVpuDecoder
-{
- VpuDecHandle handle;
-
- void *virt_mem_sub_block;
- size_t virt_mem_sub_block_size;
-
- ImxVpuCodecFormats codec_format;
-
- unsigned int num_framebuffers;
- VpuFrameBuffer **wrapper_framebuffers;
- ImxVpuFramebuffer *framebuffers;
- void **user_data_for_frames;
- void *pending_user_data;
- void *dropped_frame_user_data;
- int num_user_data;
- BOOL delay_pending_user_data;
- void *last_pending_user_data;
-
- BOOL consumption_info_available;
- BOOL flush_vpu_upon_reset;
-
- BOOL recalculate_num_avail_framebuffers;
- int num_available_framebuffers;
- int num_times_counter_decremented;
- int num_framebuffers_in_use;
-};
-
-
-static ImxVpuDecReturnCodes dec_convert_retcode(VpuDecRetCode code)
-{
- switch (code)
- {
- case VPU_DEC_RET_SUCCESS: return IMX_VPU_DEC_RETURN_CODE_OK;
- case VPU_DEC_RET_FAILURE: return IMX_VPU_DEC_RETURN_CODE_ERROR;
- case VPU_DEC_RET_INVALID_PARAM: return IMX_VPU_DEC_RETURN_CODE_INVALID_PARAMS;
- case VPU_DEC_RET_INVALID_HANDLE: return IMX_VPU_DEC_RETURN_CODE_INVALID_HANDLE;
- case VPU_DEC_RET_INVALID_FRAME_BUFFER: return IMX_VPU_DEC_RETURN_CODE_INVALID_FRAMEBUFFER;
- case VPU_DEC_RET_INSUFFICIENT_FRAME_BUFFERS: return IMX_VPU_DEC_RETURN_CODE_INSUFFICIENT_FRAMEBUFFERS;
- case VPU_DEC_RET_INVALID_STRIDE: return IMX_VPU_DEC_RETURN_CODE_INVALID_STRIDE;
- case VPU_DEC_RET_WRONG_CALL_SEQUENCE: return IMX_VPU_DEC_RETURN_CODE_WRONG_CALL_SEQUENCE;
- case VPU_DEC_RET_FAILURE_TIMEOUT: return IMX_VPU_DEC_RETURN_CODE_TIMEOUT;
-
- default: return IMX_VPU_DEC_RETURN_CODE_ERROR;
- }
-}
-
-
-static unsigned int dec_convert_outcode(VpuDecBufRetCode code)
-{
- /* TODO: REPEAT? SKIP? */
- unsigned int out = 0;
- if (code & VPU_DEC_INPUT_USED) out |= IMX_VPU_DEC_OUTPUT_CODE_INPUT_USED;
- if (code & VPU_DEC_OUTPUT_EOS) out |= IMX_VPU_DEC_OUTPUT_CODE_EOS;
- if (code & VPU_DEC_OUTPUT_DIS) out |= IMX_VPU_DEC_OUTPUT_CODE_FRAME_OUTPUT;
- if (code & VPU_DEC_OUTPUT_NODIS) out |= IMX_VPU_DEC_OUTPUT_CODE_NO_FRAME_OUTPUT;
- if (code & VPU_DEC_OUTPUT_DROPPED) out |= IMX_VPU_DEC_OUTPUT_CODE_DROPPED;
- if (code & VPU_DEC_OUTPUT_MOSAIC_DIS) out |= IMX_VPU_DEC_OUTPUT_CODE_DROPPED; /* mosaic frames are dropped */
- if (code & VPU_DEC_NO_ENOUGH_BUF) out |= IMX_VPU_DEC_OUTPUT_CODE_NOT_ENOUGH_OUTPUT_FRAMES;
- if (code & VPU_DEC_NO_ENOUGH_INBUF) out |= IMX_VPU_DEC_OUTPUT_CODE_NOT_ENOUGH_INPUT_DATA;
- if (code & VPU_DEC_INIT_OK) out |= IMX_VPU_DEC_OUTPUT_CODE_INITIAL_INFO_AVAILABLE;
- if (code & VPU_DEC_RESOLUTION_CHANGED) out |= IMX_VPU_DEC_OUTPUT_CODE_RESOLUTION_CHANGED;
- return out;
-}
-
-
-static void dec_convert_to_wrapper_open_param(ImxVpuDecOpenParams const *open_params, VpuDecOpenParam *wrapper_open_param)
-{
- memset(wrapper_open_param, 0, sizeof(VpuDecOpenParam));
-
- wrapper_open_param->CodecFormat = convert_to_wrapper_codec_std(open_params->codec_format);
- wrapper_open_param->nReorderEnable = open_params->enable_frame_reordering;
- wrapper_open_param->nPicWidth = open_params->frame_width;
- wrapper_open_param->nPicHeight = open_params->frame_height;
-}
-
-
-static void dec_convert_from_wrapper_initial_info(VpuDecInitInfo *wrapper_info, ImxVpuDecInitialInfo *info)
-{
- info->frame_width = wrapper_info->nPicWidth;
- info->frame_height = wrapper_info->nPicHeight;
- info->frame_rate_numerator = wrapper_info->nFrameRateRes;
- info->frame_rate_denominator = wrapper_info->nFrameRateDiv;
-
- info->min_num_required_framebuffers = wrapper_info->nMinFrameBufferCount + MIN_NUM_FREE_FB_REQUIRED;
- info->mjpeg_source_format = convert_from_wrapper_mjpg_format(wrapper_info->nMjpgSourceFormat);
-
- info->interlacing = wrapper_info->nInterlace;
-
- info->width_height_ratio = wrapper_info->nQ16ShiftWidthDivHeightRatio;
-
- info->framebuffer_alignment = wrapper_info->nAddressAlignment;
-}
-
-
-static int dec_get_wrapper_framebuffer_index(ImxVpuDecoder *decoder, VpuFrameBuffer *wrapper_fb)
-{
- unsigned int i;
-
- // TODO: do something faster, like a hash table
- for (i = 0; i < decoder->num_framebuffers; ++i)
- {
- if (wrapper_fb == decoder->wrapper_framebuffers[i])
- return (int)i;
- }
- return -1;
-}
-
-
-char const * imx_vpu_dec_error_string(ImxVpuDecReturnCodes code)
-{
- switch (code)
- {
- case IMX_VPU_DEC_RETURN_CODE_OK: return "ok";
- case IMX_VPU_DEC_RETURN_CODE_ERROR: return "unspecified error";
- case IMX_VPU_DEC_RETURN_CODE_INVALID_PARAMS: return "invalid params";
- case IMX_VPU_DEC_RETURN_CODE_INVALID_HANDLE: return "invalid handle";
- case IMX_VPU_DEC_RETURN_CODE_INVALID_FRAMEBUFFER: return "invalid framebuffer";
- case IMX_VPU_DEC_RETURN_CODE_INSUFFICIENT_FRAMEBUFFERS: return "insufficient_framebuffers";
- case IMX_VPU_DEC_RETURN_CODE_INVALID_STRIDE: return "invalid stride";
- case IMX_VPU_DEC_RETURN_CODE_WRONG_CALL_SEQUENCE: return "wrong call sequence";
- case IMX_VPU_DEC_RETURN_CODE_TIMEOUT: return "timeout";
- default: return "<unknown>";
- }
-}
-
-
-static unsigned long vpu_load_inst_counter = 0;
-
-
-ImxVpuDecReturnCodes imx_vpu_dec_load(void)
-{
- IMX_VPU_TRACE("VPU load instance counter: %lu", vpu_load_inst_counter);
- if (vpu_load_inst_counter == 0)
- {
- ImxVpuDecReturnCodes ret = dec_convert_retcode(VPU_DecLoad());
- if (ret != IMX_VPU_DEC_RETURN_CODE_OK)
- {
- IMX_VPU_ERROR("loading decoder failed: %s", imx_vpu_dec_error_string(ret));
- return ret;
- }
- else
- IMX_VPU_TRACE("loaded decoder");
- }
-
- ++vpu_load_inst_counter;
-
- return IMX_VPU_DEC_RETURN_CODE_OK;
-}
-
-
-ImxVpuDecReturnCodes imx_vpu_dec_unload(void)
-{
- IMX_VPU_TRACE("VPU load instance counter: %lu", vpu_load_inst_counter);
- if (vpu_load_inst_counter == 1)
- {
- ImxVpuDecReturnCodes ret = dec_convert_retcode(VPU_DecUnLoad());
- if (ret != IMX_VPU_DEC_RETURN_CODE_OK)
- {
- IMX_VPU_ERROR("unloading decoder failed: %s", imx_vpu_dec_error_string(ret));
- return ret;
- }
- else
- IMX_VPU_TRACE("unloaded decoder");
- }
-
- if (vpu_load_inst_counter > 0)
- --vpu_load_inst_counter;
-
- return IMX_VPU_DEC_RETURN_CODE_OK;
-}
-
-
-ImxVpuDecReturnCodes imx_vpu_dec_allocate_memory(ImxVpuMemBlock *mem_block)
-{
- VpuDecRetCode ret;
- VpuMemDesc mem_desc;
-
- if (mem_block->alignment == 0)
- mem_block->alignment = 1;
-
- mem_desc.nSize = mem_block->size + mem_block->alignment;
-
- if ((ret = VPU_DecGetMem(&mem_desc)) != VPU_DEC_RET_SUCCESS)
- {
- IMX_VPU_ERROR("allocating %d bytes of physical memory failed: %s", mem_block->size, imx_vpu_dec_error_string(dec_convert_retcode(ret)));
- return dec_convert_retcode(ret);
- }
- else
- IMX_VPU_TRACE("allocated %d bytes of physical memory", mem_block->size);
-
- convert_from_wrapper_mem_desc(&mem_desc, mem_block);
-
- mem_block->virtual_address = (void *)IMX_VPU_ALIGN_VAL_TO(mem_block->virtual_address_unaligned, mem_block->alignment);
- mem_block->physical_address = (imx_vpu_phys_addr_t)IMX_VPU_ALIGN_VAL_TO(mem_block->physical_address_unaligned, mem_block->alignment);
-
- return IMX_VPU_DEC_RETURN_CODE_OK;
-}
-
-
-ImxVpuDecReturnCodes imx_vpu_dec_deallocate_memory(ImxVpuMemBlock *mem_block)
-{
- ImxVpuDecReturnCodes ret;
- VpuMemDesc mem_desc;
-
- convert_to_wrapper_mem_desc(mem_block, &mem_desc);
-
- ret = dec_convert_retcode(VPU_DecFreeMem(&mem_desc));
- if (ret != IMX_VPU_DEC_RETURN_CODE_OK)
- IMX_VPU_ERROR("deallocating %d bytes of physical memory failed: %s", mem_block->size, imx_vpu_dec_error_string(ret));
- else
- IMX_VPU_TRACE("deallocated %d bytes of physical memory", mem_block->size);
-
- return ret;
-}
-
-
-void imx_vpu_dec_get_bitstream_buffer_info(unsigned int *alignment, size_t *size)
-{
- int i;
- VpuMemInfo mem_info;
-
- VPU_DecQueryMem(&mem_info);
-
- /* only two sub blocks are ever present - get the VPU_MEM_PHY one */
-
- for (i = 0; i < mem_info.nSubBlockNum; ++i)
- {
- if (mem_info.MemSubBlock[i].MemType == VPU_MEM_PHY)
- {
- *alignment = mem_info.MemSubBlock[i].nAlignment;
- *size = mem_info.MemSubBlock[i].nSize;
- IMX_VPU_TRACE("determined alignment %d and size %d for the physical memory for the bitstream buffer", *alignment, *size);
- break;
- }
- }
-
- /* virtual memory block is allocated internally inside imx_vpu_dec_open() */
-}
-
-
-ImxVpuDecReturnCodes imx_vpu_dec_open(ImxVpuDecoder **decoder, ImxVpuDecOpenParams const *open_params, void *bitstream_buffer_virtual_address, imx_vpu_phys_addr_t bitstream_buffer_physical_addres)
-{
- int config_param;
- VpuDecRetCode ret;
- VpuMemInfo mem_info;
- VpuDecOpenParam open_param;
-
- *decoder = IMX_VPU_ALLOC(sizeof(ImxVpuDecoder));
- if ((*decoder) == NULL)
- {
- IMX_VPU_ERROR("allocating memory for decoder object failed");
- return IMX_VPU_DEC_RETURN_CODE_ERROR;
- }
-
- memset(*decoder, 0, sizeof(ImxVpuDecoder));
-
- {
- int i;
-
- VPU_DecQueryMem(&mem_info);
-
- IMX_VPU_INFO("about to allocate %d memory sub blocks", mem_info.nSubBlockNum);
- for (i = 0; i < mem_info.nSubBlockNum; ++i)
- {
- char const *type_str = "<unknown>";
- VpuMemSubBlockInfo *sub_block = &(mem_info.MemSubBlock[i]);
-
- switch (sub_block->MemType)
- {
- case VPU_MEM_VIRT:
- type_str = "virtual";
-
- (*decoder)->virt_mem_sub_block_size = sub_block->nSize + sub_block->nAlignment;
- (*decoder)->virt_mem_sub_block = IMX_VPU_ALLOC((*decoder)->virt_mem_sub_block_size);
- if ((*decoder)->virt_mem_sub_block == NULL)
- {
- IMX_VPU_ERROR("allocating memory for sub block failed");
- return IMX_VPU_DEC_RETURN_CODE_ERROR;
- }
-
- sub_block->pVirtAddr = (unsigned char *)IMX_VPU_ALIGN_VAL_TO((*decoder)->virt_mem_sub_block, sub_block->nAlignment);
- sub_block->pPhyAddr = 0;
- break;
-
- case VPU_MEM_PHY:
- type_str = "physical";
-
- sub_block->pVirtAddr = (unsigned char *)(bitstream_buffer_virtual_address);
- sub_block->pPhyAddr = (unsigned char *)(bitstream_buffer_physical_addres);
- break;
- default:
- break;
- }
-
- IMX_VPU_INFO("allocated memory sub block #%d: type: %s size: %d alignment: %d virtual address: %p physical address: %p", i, type_str, sub_block->nSize, sub_block->nAlignment, sub_block->pVirtAddr, sub_block->pPhyAddr);
- }
- }
-
- dec_convert_to_wrapper_open_param(open_params, &open_param);
-
- IMX_VPU_TRACE("opening decoder");
-
- switch (open_params->codec_format)
- {
- case IMX_VPU_CODEC_FORMAT_H264:
- case IMX_VPU_CODEC_FORMAT_H264_MVC:
- case IMX_VPU_CODEC_FORMAT_MPEG2:
- case IMX_VPU_CODEC_FORMAT_MPEG4:
- (*decoder)->consumption_info_available = TRUE;
- (*decoder)->flush_vpu_upon_reset = TRUE;
- break;
- case IMX_VPU_CODEC_FORMAT_H263:
- case IMX_VPU_CODEC_FORMAT_WMV3:
- case IMX_VPU_CODEC_FORMAT_WVC1:
- (*decoder)->consumption_info_available = FALSE;
- (*decoder)->flush_vpu_upon_reset = FALSE;
- break;
- case IMX_VPU_CODEC_FORMAT_MJPEG:
- case IMX_VPU_CODEC_FORMAT_VP8:
- (*decoder)->consumption_info_available = FALSE;
- (*decoder)->flush_vpu_upon_reset = TRUE;
- break;
- default:
- break;
- }
-
- ret = VPU_DecOpen(&((*decoder)->handle), &open_param, &mem_info);
- if (ret != VPU_DEC_RET_SUCCESS)
- {
- IMX_VPU_ERROR("opening decoder failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
- goto cleanup;
- }
-
- IMX_VPU_TRACE("setting configuration");
-
- config_param = VPU_DEC_SKIPNONE;
- ret = VPU_DecConfig((*decoder)->handle, VPU_DEC_CONF_SKIPMODE, &config_param);
- if (ret != VPU_DEC_RET_SUCCESS)
- {
- IMX_VPU_ERROR("setting skipmode to NONE failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
- goto cleanup;
- }
-
- config_param = 0;
- ret = VPU_DecConfig((*decoder)->handle, VPU_DEC_CONF_BUFDELAY, &config_param);
- if (ret != VPU_DEC_RET_SUCCESS)
- {
- IMX_VPU_ERROR("setting bufdelay to 0 failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
- goto cleanup;
- }
-
- config_param = VPU_DEC_IN_NORMAL;
- ret = VPU_DecConfig((*decoder)->handle, VPU_DEC_CONF_INPUTTYPE, &config_param);
- if (ret != VPU_DEC_RET_SUCCESS)
- {
- IMX_VPU_ERROR("setting input type to \"normal\" failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
- goto cleanup;
- }
-
- (*decoder)->codec_format = open_params->codec_format;
-
-finish:
- if (ret == VPU_DEC_RET_SUCCESS)
- IMX_VPU_TRACE("successfully opened decoder");
-
- return dec_convert_retcode(ret);
-
-cleanup:
- if ((*decoder)->virt_mem_sub_block != NULL)
- IMX_VPU_FREE((*decoder)->virt_mem_sub_block, (*decoder)->virt_mem_sub_block_size);
- IMX_VPU_FREE(*decoder, sizeof(ImxVpuDecoder));
- *decoder = NULL;
-
- goto finish;
-}
-
-
-ImxVpuDecReturnCodes imx_vpu_dec_close(ImxVpuDecoder *decoder)
-{
- VpuDecRetCode ret;
-
- IMX_VPU_TRACE("closing decoder");
-
- ret = VPU_DecFlushAll(decoder->handle);
- if (ret == VPU_DEC_RET_FAILURE_TIMEOUT)
- {
- IMX_VPU_WARNING("resetting decoder after a timeout occurred");
- ret = VPU_DecReset(decoder->handle);
- if (ret != VPU_DEC_RET_SUCCESS)
- IMX_VPU_ERROR("resetting decoder failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
- }
- else if (ret != VPU_DEC_RET_SUCCESS)
- IMX_VPU_ERROR("flushing decoder failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
-
- ret = VPU_DecClose(decoder->handle);
- if (ret != VPU_DEC_RET_SUCCESS)
- IMX_VPU_ERROR("closing decoder failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
-
- if (decoder->user_data_for_frames != NULL)
- IMX_VPU_FREE(decoder->user_data_for_frames, sizeof(void*) * decoder->num_framebuffers);
- if (decoder->wrapper_framebuffers != NULL)
- IMX_VPU_FREE(decoder->wrapper_framebuffers, sizeof(VpuFrameBuffer*) * decoder->num_framebuffers);
- if (decoder->virt_mem_sub_block != NULL)
- IMX_VPU_FREE(decoder->virt_mem_sub_block, decoder->virt_mem_sub_block_size);
- IMX_VPU_FREE(decoder, sizeof(ImxVpuDecoder));
-
- IMX_VPU_TRACE("closed decoder");
-
- return dec_convert_retcode(ret);
-}
-
-
-ImxVpuDecReturnCodes imx_vpu_dec_set_drain_mode(ImxVpuDecoder *decoder, int enabled)
-{
- int config_param;
- VpuDecRetCode ret;
-
- config_param = enabled ? VPU_DEC_IN_DRAIN : VPU_DEC_IN_NORMAL;
- ret = VPU_DecConfig(decoder->handle, VPU_DEC_CONF_INPUTTYPE, &config_param);
-
- if (ret != VPU_DEC_RET_SUCCESS)
- IMX_VPU_ERROR("setting decoder drain mode failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
- else
- IMX_VPU_INFO("set decoder drain mode to %d", enabled);
-
- return dec_convert_retcode(ret);
-}
-
-
-ImxVpuDecReturnCodes imx_vpu_dec_flush(ImxVpuDecoder *decoder)
-{
- VpuDecRetCode ret = VPU_DEC_RET_SUCCESS;
-
- decoder->delay_pending_user_data = FALSE;
-
- if (decoder->flush_vpu_upon_reset)
- {
- ret = VPU_DecFlushAll(decoder->handle);
- if (ret == VPU_DEC_RET_FAILURE_TIMEOUT)
- {
- IMX_VPU_WARNING("resetting decoder after a timeout occurred");
- ret = VPU_DecReset(decoder->handle);
- if (ret != VPU_DEC_RET_SUCCESS)
- IMX_VPU_ERROR("resetting decoder failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
- }
- else if (ret != VPU_DEC_RET_SUCCESS)
- IMX_VPU_ERROR("flushing decoder failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
- else
- IMX_VPU_INFO("flushed decoder");
-
- decoder->recalculate_num_avail_framebuffers = TRUE;
- }
- else
- IMX_VPU_INFO("decoder not flushed, because it is unnecessary for this codec format");
-
- if (decoder->user_data_for_frames != NULL)
- memset(decoder->user_data_for_frames, 0, sizeof(void*) * decoder->num_framebuffers);
- decoder->num_user_data = 0;
-
- return dec_convert_retcode(ret);
-}
-
-
-ImxVpuDecReturnCodes imx_vpu_dec_register_framebuffers(ImxVpuDecoder *decoder, ImxVpuFramebuffer *framebuffers, unsigned int num_framebuffers)
-{
- unsigned int i;
- VpuDecRetCode ret;
- VpuFrameBuffer *temp_fbs;
-
- IMX_VPU_TRACE("attempting to register %u framebuffers", num_framebuffers);
-
- decoder->wrapper_framebuffers = NULL;
-
- temp_fbs = IMX_VPU_ALLOC(sizeof(VpuFrameBuffer) * num_framebuffers);
- if (temp_fbs == NULL)
- {
- IMX_VPU_ERROR("allocating memory for framebuffers failed");
- return IMX_VPU_DEC_RETURN_CODE_ERROR;
- }
-
- for (i = 0; i < num_framebuffers; ++i)
- convert_to_wrapper_framebuffer(&framebuffers[i], &(temp_fbs[i]));
-
- ret = VPU_DecRegisterFrameBuffer(decoder->handle, temp_fbs, num_framebuffers);
-
- IMX_VPU_FREE(temp_fbs, sizeof(VpuFrameBuffer) * num_framebuffers);
-
- if (ret != VPU_DEC_RET_SUCCESS)
- {
- ImxVpuDecReturnCodes imxret = dec_convert_retcode(ret);
- IMX_VPU_ERROR("registering framebuffers failed: %s", imx_vpu_dec_error_string(imxret));
- return ret;
- }
-
- decoder->wrapper_framebuffers = IMX_VPU_ALLOC(sizeof(VpuFrameBuffer*) * num_framebuffers);
- {
- int out_num;
- VPU_DecAllRegFrameInfo(decoder->handle, decoder->wrapper_framebuffers, &out_num);
- IMX_VPU_LOG("out_num: %d num_framebuffers: %u", out_num, num_framebuffers);
- }
-
- decoder->framebuffers = framebuffers;
- decoder->num_framebuffers = num_framebuffers;
- decoder->num_available_framebuffers = num_framebuffers;
-
- decoder->user_data_for_frames = IMX_VPU_ALLOC(sizeof(void*) * num_framebuffers);
- if (decoder->user_data_for_frames == NULL)
- {
- IMX_VPU_ERROR("allocating memory for user data failed");
- IMX_VPU_FREE(decoder->wrapper_framebuffers, sizeof(VpuFrameBuffer*) * num_framebuffers);
- decoder->wrapper_framebuffers = NULL;
- return IMX_VPU_DEC_RETURN_CODE_ERROR;
- }
-
- memset(decoder->user_data_for_frames, 0, sizeof(void*) * num_framebuffers);
- decoder->num_user_data = 0;
-
- return IMX_VPU_DEC_RETURN_CODE_OK;
-}
-
-
-void imx_vpu_dec_calc_framebuffer_sizes(ImxVpuDecInitialInfo const *initial_info, unsigned int *frame_width, unsigned int *frame_height, unsigned int *y_stride, unsigned int *uv_stride, unsigned int *y_size, unsigned int *uv_size, unsigned int *mvcol_size, unsigned int *total_size)
-{
- int alignment;
-
- *frame_width = IMX_VPU_ALIGN_VAL_TO(*frame_width, FRAME_ALIGN);
- if (initial_info->interlacing)
- *frame_height = IMX_VPU_ALIGN_VAL_TO(*frame_height, (2 * FRAME_ALIGN));
- else
- *frame_height = IMX_VPU_ALIGN_VAL_TO(*frame_height, FRAME_ALIGN);
-
- *y_stride = *frame_width;
- *y_size = (*y_stride) * (*frame_height);
-
- switch (initial_info->mjpeg_source_format)
- {
- case IMX_VPU_MJPEG_FORMAT_YUV420:
- *uv_stride = *y_stride / 2;
- *uv_size = *mvcol_size = *y_size / 4;
- break;
- case IMX_VPU_MJPEG_FORMAT_YUV422_HORIZONTAL:
- *uv_stride = *y_stride / 2;
- *uv_size = *mvcol_size = *y_size / 2;
- break;
- case IMX_VPU_MJPEG_FORMAT_YUV444:
- *uv_stride = *y_stride;
- *uv_size = *mvcol_size = *y_size;
- break;
- case IMX_VPU_MJPEG_FORMAT_YUV400:
- /* TODO: check if this is OK */
- *uv_stride = 0;
- *uv_size = *mvcol_size = 0;
- break;
- default:
- assert(FALSE);
- }
-
- alignment = initial_info->framebuffer_alignment;
- if (alignment > 1)
- {
- *y_size = IMX_VPU_ALIGN_VAL_TO(*y_size, alignment);
- *uv_size = IMX_VPU_ALIGN_VAL_TO(*uv_size, alignment);
- *mvcol_size = IMX_VPU_ALIGN_VAL_TO(*mvcol_size, alignment);
- }
-
- *total_size = *y_size + *uv_size + *uv_size + *mvcol_size + alignment;
-}
-
-
-ImxVpuDecReturnCodes imx_vpu_dec_get_initial_info(ImxVpuDecoder *decoder, ImxVpuDecInitialInfo *info)
-{
- VpuDecRetCode ret;
- VpuDecInitInfo init_info;
-
- ret = VPU_DecGetInitialInfo(decoder->handle, &init_info);
- IMX_VPU_LOG("VPU_DecGetInitialInfo: min num framebuffers required: %d", init_info.nMinFrameBufferCount);
- dec_convert_from_wrapper_initial_info(&init_info, info);
- return dec_convert_retcode(ret);
-}
-
-
-ImxVpuDecReturnCodes imx_vpu_dec_decode_frame(ImxVpuDecoder *decoder, ImxVpuEncodedFrame const *encoded_frame, unsigned int *output_code)
-{
- VpuDecRetCode ret;
- VpuBufferNode node;
- int buf_ret_code;
-
- node.pVirAddr = encoded_frame->virtual_address;
- node.pPhyAddr = 0; /* encoded data is always read from a regular memory block, not a DMA buffer */
- node.nSize = encoded_frame->data_size;
-
- node.sCodecData.pData = encoded_frame->codec_data;
- node.sCodecData.nSize = encoded_frame->codec_data_size;
-
- decoder->pending_user_data = encoded_frame->user_data;
-
- ret = VPU_DecDecodeBuf(decoder->handle, &node, &buf_ret_code);
- IMX_VPU_LOG("VPU_DecDecodeBuf buf ret code: 0x%x", buf_ret_code);
-
- *output_code = dec_convert_outcode(buf_ret_code);
-
- if (ret != VPU_DEC_RET_SUCCESS)
- {
- IMX_VPU_ERROR("decoding frame failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
- return dec_convert_retcode(ret);
- }
-
- if (decoder->recalculate_num_avail_framebuffers)
- {
- decoder->num_available_framebuffers = decoder->num_framebuffers - decoder->num_framebuffers_in_use;
- IMX_VPU_LOG("recalculated number of available framebuffers to %d", decoder->num_available_framebuffers);
- decoder->recalculate_num_avail_framebuffers = FALSE;
- }
-
- if (buf_ret_code & VPU_DEC_INIT_OK)
- {
- decoder->delay_pending_user_data = TRUE;
- decoder->last_pending_user_data = decoder->pending_user_data;
- }
-
- if (buf_ret_code & VPU_DEC_FLUSH)
- {
- IMX_VPU_INFO("VPU requested a decoder flush");
- ret = VPU_DecFlushAll(decoder->handle);
- if (ret == VPU_DEC_RET_FAILURE_TIMEOUT)
- {
- IMX_VPU_WARNING("timeout detected, resetting decoder");
-
- ret = VPU_DecReset(decoder->handle);
- if (ret != VPU_DEC_RET_SUCCESS)
- {
- ImxVpuDecReturnCodes imxret = dec_convert_retcode(ret);
- IMX_VPU_ERROR("resetting decoder failed: %s", imx_vpu_dec_error_string(imxret));
- return imxret;
- }
- else
- *output_code |= IMX_VPU_DEC_OUTPUT_CODE_INTERNAL_RESET;
- }
- else if (ret != VPU_DEC_RET_SUCCESS)
- {
- ImxVpuDecReturnCodes imxret = dec_convert_retcode(ret);
- IMX_VPU_ERROR("flushing decoder failed: %s", imx_vpu_dec_error_string(imxret));
- return imxret;
- }
- else
- IMX_VPU_INFO("flushed decoder");
- }
-
- if (buf_ret_code & VPU_DEC_RESOLUTION_CHANGED)
- {
- IMX_VPU_INFO("resolution changed - resetting internal states");
-
- *output_code |= IMX_VPU_DEC_OUTPUT_CODE_INITIAL_INFO_AVAILABLE;
-
- decoder->delay_pending_user_data = TRUE;
- decoder->recalculate_num_avail_framebuffers = FALSE;
-
- decoder->num_user_data = 0;
-
- if (decoder->user_data_for_frames != NULL)
- IMX_VPU_FREE(decoder->user_data_for_frames, sizeof(void*) * decoder->num_framebuffers);
- if (decoder->wrapper_framebuffers != NULL)
- IMX_VPU_FREE(decoder->wrapper_framebuffers, sizeof(VpuFrameBuffer*) * decoder->num_framebuffers);
-
- decoder->user_data_for_frames = NULL;
- decoder->wrapper_framebuffers = NULL;
- }
-
- if (buf_ret_code & VPU_DEC_NO_ENOUGH_INBUF)
- {
- /* Not dropping frame here on purpose; the next input frame may
- * complete the input */
- }
-
- {
- void *user_data = decoder->delay_pending_user_data ? decoder->last_pending_user_data : decoder->pending_user_data;
-
- /* The first time this location is reached, VPU_DEC_INIT_OK will be set in the output_code.
- * This implies that the framebuffers have not been allocated and registered yet,
- * so no user data can be stored yet.
- * With codec formats that produce consumption info, this is not a problem, because
- * VPU_DEC_ONE_FRM_CONSUMED will be returned only when framebuffers are present.
- * But with other formats, an explicit decoder->framebuffers != NULL check is necessary
- * (see below). The user_data pointer does not get lost; it is stored in last_pending_user_data. */
- if ((buf_ret_code & VPU_DEC_ONE_FRM_CONSUMED) && !(buf_ret_code & VPU_DEC_OUTPUT_DROPPED))
- {
- int fb_index;
-
- VpuDecFrameLengthInfo consumed_frame_info;
- ret = VPU_DecGetConsumedFrameInfo(decoder->handle, &consumed_frame_info);
- if (ret != VPU_DEC_RET_SUCCESS)
- {
- ImxVpuDecReturnCodes imxret = dec_convert_retcode(ret);
- IMX_VPU_ERROR("getting consumed frame info failed: %s", imx_vpu_dec_error_string(imxret));
- return imxret;
- }
-
- fb_index = dec_get_wrapper_framebuffer_index(decoder, consumed_frame_info.pFrame);
-
- if (consumed_frame_info.pFrame != NULL)
- {
- if ((fb_index >= 0) && (fb_index < (int)(decoder->num_framebuffers)))
- {
- IMX_VPU_LOG("framebuffer index %d for framebuffer %p user data %p", fb_index, (void *)(consumed_frame_info.pFrame), user_data);
- decoder->user_data_for_frames[fb_index] = user_data;
- }
- else
- IMX_VPU_ERROR("framebuffer index %d for framebuffer %p user data %p out of bounds", fb_index, (void *)(consumed_frame_info.pFrame), user_data);
- }
- else
- IMX_VPU_WARNING("consumed frame info contains a NULL frame");
- }
- else if (!(decoder->consumption_info_available) && (decoder->framebuffers != NULL))
- {
- if (decoder->num_user_data < (int)(decoder->num_framebuffers))
- {
- decoder->user_data_for_frames[decoder->num_user_data] = user_data;
- decoder->num_user_data++;
-
- IMX_VPU_LOG("user data %p stored as newest", user_data);
-
- IMX_VPU_TRACE("incremented number of userdata pointers to %d", decoder->num_user_data);
- }
- else
- IMX_VPU_WARNING("too many user data pointers in memory - cannot store current one");
- }
-
- decoder->last_pending_user_data = decoder->pending_user_data;
- decoder->pending_user_data = NULL;
- }
-
- if ((buf_ret_code & VPU_DEC_ONE_FRM_CONSUMED) && !(buf_ret_code & VPU_DEC_OUTPUT_DROPPED))
- {
- decoder->num_available_framebuffers--;
- decoder->num_times_counter_decremented++;
- IMX_VPU_LOG("decremented number of available framebuffers to %d (with consumed frame info); number of times decremented is now %d", decoder->num_available_framebuffers, decoder->num_times_counter_decremented);
- }
-
- if (buf_ret_code & VPU_DEC_OUTPUT_NODIS)
- {
- if ((encoded_frame->virtual_address != NULL) && (decoder->codec_format == IMX_VPU_CODEC_FORMAT_VP8))
- *output_code |= IMX_VPU_DEC_OUTPUT_CODE_DECODE_ONLY;
- }
-
- /* VPU_DEC_NO_ENOUGH_BUF handled by caller - should be treated as an error */
-
- if ((buf_ret_code & VPU_DEC_OUTPUT_DIS) && !(decoder->consumption_info_available))
- {
- decoder->num_available_framebuffers--;
- decoder->num_times_counter_decremented++;
- IMX_VPU_LOG("decremented number of available framebuffers to %d (no consumed frame info); number of times decremented is now %d", decoder->num_available_framebuffers, decoder->num_times_counter_decremented);
- }
- else if (buf_ret_code & VPU_DEC_OUTPUT_MOSAIC_DIS)
- {
- IMX_VPU_TRACE("dropping mosaic frame");
-
- /* mosaic frames do not seem to be useful for anything, so they are just dropped here */
-
- ImxVpuDecReturnCodes imxret;
- ImxVpuDecodedFrame decoded_frame;
-
- if ((imxret = imx_vpu_dec_get_decoded_frame(decoder, &decoded_frame)) != IMX_VPU_DEC_RETURN_CODE_OK)
- {
- IMX_VPU_ERROR("error getting output mosaic frame: %s", imx_vpu_dec_error_string(imxret));
- return imxret;
- }
-
- if ((imxret = imx_vpu_dec_mark_framebuffer_as_displayed(decoder, decoded_frame.framebuffer)) != IMX_VPU_DEC_RETURN_CODE_OK)
- {
- IMX_VPU_ERROR("error marking mosaic frame as displayed: %s", imx_vpu_dec_error_string(imxret));
- return imxret;
- }
-
- decoder->dropped_frame_user_data = decoded_frame.user_data;
-
- *output_code |= IMX_VPU_DEC_OUTPUT_CODE_DROPPED;
- }
- else if (buf_ret_code & VPU_DEC_OUTPUT_DROPPED)
- {
- // TODO make this work for formats with consumption info
- if (decoder->num_user_data > 0)
- {
- decoder->dropped_frame_user_data = decoder->user_data_for_frames[0];
- decoder->user_data_for_frames[0] = NULL;
- memmove(decoder->user_data_for_frames, decoder->user_data_for_frames + 1, sizeof(void*) * (decoder->num_user_data - 1));
- decoder->num_user_data--;
- }
- else
- decoder->dropped_frame_user_data = NULL;
- }
-
- /* In case the VPU didn't use the input and no consumed frame info is available,
- * drop the input frame to make sure timestamps are okay
- * (If consumed frame info is present it is still possible it might be used for input-output frame
- * associations; unlikely to occur thought) */
- if ((encoded_frame->virtual_address != NULL) && !(buf_ret_code & (VPU_DEC_ONE_FRM_CONSUMED | VPU_DEC_INPUT_USED | VPU_DEC_RESOLUTION_CHANGED)))
- {
- decoder->dropped_frame_user_data = encoded_frame->user_data;
- *output_code |= IMX_VPU_DEC_OUTPUT_CODE_DROPPED;
- }
-
- return IMX_VPU_DEC_RETURN_CODE_OK;
-}
-
-
-ImxVpuDecReturnCodes imx_vpu_dec_get_decoded_frame(ImxVpuDecoder *decoder, ImxVpuDecodedFrame *decoded_frame)
-{
- VpuDecRetCode ret;
- VpuDecOutFrameInfo out_frame_info;
- int fb_index;
- void *user_data;
-
- ret = VPU_DecGetOutputFrame(decoder->handle, &out_frame_info);
- if (ret != VPU_DEC_RET_SUCCESS)
- {
- ImxVpuDecReturnCodes imxret = dec_convert_retcode(ret);
- IMX_VPU_ERROR("error getting decoded output frame: %s", imx_vpu_dec_error_string(imxret));
- return imxret;
- }
-
- fb_index = dec_get_wrapper_framebuffer_index(decoder, out_frame_info.pDisplayFrameBuf);
-
- user_data = NULL;
- if (decoder->consumption_info_available)
- {
- if ((fb_index >= 0) && (fb_index < (int)(decoder->num_framebuffers)))
- {
- user_data = decoder->user_data_for_frames[fb_index];
- IMX_VPU_LOG("framebuffer index %d for framebuffer %p and user data %p", fb_index, (void *)(out_frame_info.pDisplayFrameBuf), user_data);
- decoder->user_data_for_frames[fb_index] = NULL;
- }
- else
- IMX_VPU_ERROR("framebuffer index %d for framebuffer %p and user data %p out of bounds", fb_index, (void *)(out_frame_info.pDisplayFrameBuf), user_data);
- }
- else
- {
- if (decoder->num_user_data > 0)
- {
- user_data = decoder->user_data_for_frames[0];
- decoder->user_data_for_frames[0] = NULL;
- IMX_VPU_LOG("framebuffer index %d user data %p retrieved as oldest", fb_index, user_data);
- memmove(decoder->user_data_for_frames, decoder->user_data_for_frames + 1, sizeof(void*) * (decoder->num_user_data - 1));
- decoder->num_user_data--;
- }
- }
-
- decoded_frame->pic_type = convert_from_wrapper_pic_type(out_frame_info.ePicType);
- decoded_frame->user_data = user_data;
-
- /* XXX
- * This association assumes that the order of internal framebuffer entries
- * inside the VPU wrapper is the same as the order of the framebuffers here.
- * So, decoder->framebuffers[1] equals internal framebuffer entry with index 1 etc.
- */
- decoded_frame->framebuffer = &(decoder->framebuffers[fb_index]);
- /* This is used in imx_vpu_dec_mark_framebuffer_as_displayed() to be able
- * to mark the vpuwrapper framebuffer as displayed */
- decoded_frame->framebuffer->internal = out_frame_info.pDisplayFrameBuf;
-
- decoder->num_framebuffers_in_use++;
-
- return IMX_VPU_DEC_RETURN_CODE_OK;
-}
-
-
-void* imx_vpu_dec_get_dropped_frame_user_data(ImxVpuDecoder *decoder)
-{
- return decoder->dropped_frame_user_data;
-}
-
-
-int imx_vpu_dec_get_num_free_framebuffers(ImxVpuDecoder *decoder)
-{
- return decoder->num_available_framebuffers;
-}
-
-
-int imx_vpu_dec_get_min_num_free_required(ImxVpuDecoder *decoder)
-{
- IMXVPUCODEC_UNUSED_PARAM(decoder);
- return MIN_NUM_FREE_FB_REQUIRED;
-}
-
-
-ImxVpuDecReturnCodes imx_vpu_dec_mark_framebuffer_as_displayed(ImxVpuDecoder *decoder, ImxVpuFramebuffer const *framebuffer)
-{
- VpuDecRetCode ret;
- VpuFrameBuffer *wrapper_fb = (VpuFrameBuffer *)(framebuffer->internal);
-
- ret = VPU_DecOutFrameDisplayed(decoder->handle, wrapper_fb);
- if (ret != VPU_DEC_RET_SUCCESS)
- {
- ImxVpuDecReturnCodes imxret = dec_convert_retcode(ret);
- IMX_VPU_ERROR("error marking output frame as displayed: %s", imx_vpu_dec_error_string(imxret));
- return imxret;
- }
-
- IMX_VPU_LOG("marked framebuffer %p with physical address 0x%x as displayed", (void *)framebuffer, framebuffer->physical_address);
-
- if (decoder->num_times_counter_decremented > 0)
- {
- decoder->num_available_framebuffers++;
- decoder->num_times_counter_decremented--;
- decoder->num_framebuffers_in_use--;
-
- IMX_VPU_LOG("num_available_framebuffers %d num_times_counter_decremented %d num_framebuffers_in_use %d", decoder->num_available_framebuffers, decoder->num_times_counter_decremented, decoder->num_framebuffers_in_use);
- }
-
- return IMX_VPU_DEC_RETURN_CODE_OK;
-}
-
diff --git a/src/content/common/gpu/media/imxvpucodec_platform.h b/src/content/common/gpu/media/imxvpucodec_platform.h
deleted file mode 100644
index 83fe05a..0000000
--- a/src/content/common/gpu/media/imxvpucodec_platform.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * imxvpucodec - i.MX6 VPU hardware codec engine API library
- * Copyright (c) 2014 Carlos Rafael Giani
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any
- * damages arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute
- * it freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must
- * not claim that you wrote the original software. If you use this
- * software in a product, an acknowledgment in the product
- * documentation would be appreciated but is not required.
- *
- * 2. Altered source versions must be plainly marked as such, and must
- * not be misrepresented as being the original software.
- *
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-
-#ifndef IMXVPUCODEC_PLATFORM_H
-#define IMXVPUCODEC_PLATFORM_H
-
-
-#define IMXVPUCODEC_UNUSED_PARAM(x) ((void)(x))
-
-
-#include "imxvpucodec_platform_chromium.h"
-
-
-#endif
diff --git a/src/content/common/gpu/media/imxvpucodec_platform_chromium.cc b/src/content/common/gpu/media/imxvpucodec_platform_chromium.cc
deleted file mode 100644
index b5e861d..0000000
--- a/src/content/common/gpu/media/imxvpucodec_platform_chromium.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "imxvpucodec_platform_chromium.h"
-#include "base/logging.h"
-
-#include <stdio.h>
-#include <stdarg.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-void imx_vpu_log(ImxVpuLogLevel level, char const *file, int const line, char const *fn, const char * format, ...)
-{
- va_list args;
- char buf[500];
-
- va_start(args, format);
- vsnprintf(buf, sizeof(buf), format, args);
- va_end(args);
-
- #define DO_LOG(severity) do { LOG(severity) << file << ":" << line << " (" << fn << ") " << buf; } while(0)
- #define DO_VLOG(severity) do { VLOG(severity) << file << ":" << line << " (" << fn << ") " << buf; } while(0)
-
- switch (level)
- {
- case IMX_VPU_LOG_LEVEL_ERROR: DO_LOG(ERROR); break;
- case IMX_VPU_LOG_LEVEL_WARNING: DO_LOG(WARNING); break;
- case IMX_VPU_LOG_LEVEL_INFO: DO_LOG(INFO); break;
- case IMX_VPU_LOG_LEVEL_DEBUG: DO_VLOG(0); break;
- case IMX_VPU_LOG_LEVEL_LOG: DO_VLOG(1); break;
- case IMX_VPU_LOG_LEVEL_TRACE: DO_VLOG(2); break;
- default: break;
- }
-}
-
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/src/content/common/gpu/media/imxvpucodec_platform_chromium.h b/src/content/common/gpu/media/imxvpucodec_platform_chromium.h
deleted file mode 100644
index 8803d3a..0000000
--- a/src/content/common/gpu/media/imxvpucodec_platform_chromium.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * imxvpucodec - i.MX6 VPU hardware codec engine API library
- * Copyright (c) 2014 Carlos Rafael Giani
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any
- * damages arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute
- * it freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must
- * not claim that you wrote the original software. If you use this
- * software in a product, an acknowledgment in the product
- * documentation would be appreciated but is not required.
- *
- * 2. Altered source versions must be plainly marked as such, and must
- * not be misrepresented as being the original software.
- *
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-
-#ifndef IMXVPUCODEC_PLATFORM_CHROMIUM_H
-#define IMXVPUCODEC_PLATFORM_CHROMIUM_H
-
-
-#include <stdlib.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#define IMX_VPU_ALLOC(SIZE) malloc(SIZE)
-#define IMX_VPU_FREE(PTR, SIZE) free(PTR)
-
-
-#define IMX_VPU_ERROR(...) imx_vpu_log(IMX_VPU_LOG_LEVEL_ERROR, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
-#define IMX_VPU_WARNING(...) imx_vpu_log(IMX_VPU_LOG_LEVEL_WARNING, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
-#define IMX_VPU_INFO(...) imx_vpu_log(IMX_VPU_LOG_LEVEL_INFO, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
-#define IMX_VPU_DEBUG(...) imx_vpu_log(IMX_VPU_LOG_LEVEL_DEBUG, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
-#define IMX_VPU_LOG(...) imx_vpu_log(IMX_VPU_LOG_LEVEL_LOG, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
-#define IMX_VPU_TRACE(...) imx_vpu_log(IMX_VPU_LOG_LEVEL_TRACE, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
-
-
-typedef enum
-{
- IMX_VPU_LOG_LEVEL_ERROR = 0,
- IMX_VPU_LOG_LEVEL_WARNING,
- IMX_VPU_LOG_LEVEL_INFO,
- IMX_VPU_LOG_LEVEL_DEBUG,
- IMX_VPU_LOG_LEVEL_LOG,
- IMX_VPU_LOG_LEVEL_TRACE
-}
-ImxVpuLogLevel;
-
-
-void imx_vpu_log(ImxVpuLogLevel level, char const *file, int const line, char const *fn, const char * format, ...);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif
-
-
diff --git a/src/media/gpu/imx_gl_viv_direct_texture.cc b/src/media/gpu/imx_gl_viv_direct_texture.cc
new file mode 100644
index 0000000..b5847b8
--- /dev/null
+++ b/src/media/gpu/imx_gl_viv_direct_texture.cc
@@ -0,0 +1,38 @@
+#include "ui/gl/gl_implementation.h"
+#include "imx_gl_viv_direct_texture.h"
+
+
+bool init_viv_direct_texture(gl::GLContext &context, GLESVIVDirectTextureProcs &procs)
+{
+ VLOG(1) << "Initializing Vivante direct texture GLES extension";
+
+ gl::GLImplementation glimpl = gl::GetGLImplementation();
+ if (glimpl != gl::kGLImplementationEGLGLES2)
+ {
+ LOG(INFO) << "Cannot initialize direct textures - GL implementation is "
+ << gl::GetGLImplementationName(glimpl)
+ << ", expected " <<
+ gl::GetGLImplementationName(gl::kGLImplementationEGLGLES2);
+ return false;
+ }
+
+ // Newer Vivante drivers call the extension GL_VIV_tex_direct instead of GL_VIV_direct_texture,
+ // even though it is the same extension
+ if (context.HasExtension("GL_VIV_direct_texture"))
+ VLOG(1) << "GL_VIV_direct_texture supported";
+ else if (context.HasExtension("GL_VIV_tex_direct"))
+ VLOG(1) << "GL_VIV_tex_direct supported";
+ else
+ {
+ VLOG(1) << "Neither GL_VIV_direct_texture nor GL_VIV_tex_direct supported";
+ return false;
+ }
+
+ procs.TexDirectVIV = reinterpret_cast < PFNGLTEXDIRECTVIVPROC > (gl::GetGLProcAddress("glTexDirectVIV"));
+ procs.TexDirectVIVMap = reinterpret_cast < PFNGLTEXDIRECTVIVMAPPROC > (gl::GetGLProcAddress("glTexDirectVIVMap"));
+ procs.TexDirectTiledMapVIV = reinterpret_cast < PFNGLTEXDIRECTTILEDMAPVIVPROC > (gl::GetGLProcAddress("glTexDirectTiledMapVIV"));
+ procs.TexDirectInvalidateVIV = reinterpret_cast < PFNGLTEXDIRECTINVALIDATEVIVPROC > (gl::GetGLProcAddress("glTexDirectInvalidateVIV"));
+
+ return true;
+}
+
diff --git a/src/media/gpu/imx_gl_viv_direct_texture.h b/src/media/gpu/imx_gl_viv_direct_texture.h
new file mode 100644
index 0000000..35e253a
--- /dev/null
+++ b/src/media/gpu/imx_gl_viv_direct_texture.h
@@ -0,0 +1,55 @@
+#ifndef IMX_GL_VIV_DIRECT_TEXTURE_H
+#define IMX_GL_VIV_DIRECT_TEXTURE_H
+
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+
+
+/* GL_VIV_direct_texture */
+#ifndef GL_VIV_direct_texture
+#define GL_VIV_YV12 0x8FC0
+#define GL_VIV_NV12 0x8FC1
+#define GL_VIV_YUY2 0x8FC2
+#define GL_VIV_UYVY 0x8FC3
+#define GL_VIV_NV21 0x8FC4
+#define GL_VIV_I420 0x8FC5
+#endif
+
+
+#ifndef GL_APICALL
+#define GL_APICALL KHRONOS_APICALL
+#endif
+
+#ifndef GL_APIENTRY
+#define GL_APIENTRY KHRONOS_APIENTRY
+#endif
+
+#ifndef GL_APIENTRYP
+#define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+
+/* GL_VIV_direct_texture */
+#ifndef GL_VIV_direct_texture
+#define GL_VIV_direct_texture 1
+
+typedef void (GL_APIENTRYP PFNGLTEXDIRECTVIVPROC) (GLenum Target, GLsizei Width, GLsizei Height, GLenum Format, GLvoid ** Pixels);
+typedef void (GL_APIENTRYP PFNGLTEXDIRECTVIVMAPPROC) (GLenum Target, GLsizei Width, GLsizei Height, GLenum Format, GLvoid ** Logical, const GLuint * Physical);
+typedef void (GL_APIENTRYP PFNGLTEXDIRECTTILEDMAPVIVPROC) (GLenum Target, GLsizei Width, GLsizei Height, GLenum Format, GLvoid ** Logical, const GLuint * Physical);
+typedef void (GL_APIENTRYP PFNGLTEXDIRECTINVALIDATEVIVPROC) (GLenum Target);
+
+#endif
+
+struct GLESVIVDirectTextureProcs
+{
+ PFNGLTEXDIRECTVIVPROC TexDirectVIV;
+ PFNGLTEXDIRECTVIVMAPPROC TexDirectVIVMap;
+ PFNGLTEXDIRECTTILEDMAPVIVPROC TexDirectTiledMapVIV;
+ PFNGLTEXDIRECTINVALIDATEVIVPROC TexDirectInvalidateVIV;
+};
+
+
+bool init_viv_direct_texture(gl::GLContext &context, GLESVIVDirectTextureProcs &procs);
+
+
+#endif
diff --git a/src/media/gpu/imxvpu_video_decode_accelerator.cc b/src/media/gpu/imxvpu_video_decode_accelerator.cc
new file mode 100644
index 0000000..f666f31
--- /dev/null
+++ b/src/media/gpu/imxvpu_video_decode_accelerator.cc
@@ -0,0 +1,767 @@
+#include <iomanip>
+#include "media/base/limits.h"
+#include "base/bind.h"
+#include "base/memory/singleton.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "media/gpu/imxvpu_video_decode_accelerator.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_implementation.h"
+
+
+namespace media
+{
+
+
+namespace
+{
+
+
+class ImxVpuLoadSingleton
+{
+public:
+ static ImxVpuLoadSingleton* GetInstance()
+ {
+ return base::Singleton < ImxVpuLoadSingleton > ::get();
+ }
+
+ bool Load()
+ {
+ base::AutoLock auto_lock(lock_);
+
+ ImxVpuDecReturnCodes ret;
+
+ if ((ret = imx_vpu_dec_load()) != IMX_VPU_DEC_RETURN_CODE_OK)
+ {
+ LOG(ERROR) << "Could not load VPU: " << imx_vpu_dec_error_string(ret);
+ return false;
+ }
+ else
+ return true;
+ }
+
+ bool Unload()
+ {
+ base::AutoLock auto_lock(lock_);
+
+ ImxVpuDecReturnCodes ret;
+
+ if ((ret = imx_vpu_dec_unload()) != IMX_VPU_DEC_RETURN_CODE_OK)
+ {
+ LOG(ERROR) << "Could not unload VPU: " << imx_vpu_dec_error_string(ret);
+ return false;
+ }
+ else
+ return true;
+ }
+
+private:
+ ImxVpuLoadSingleton()
+ {
+ }
+
+ friend struct base::DefaultSingletonTraits < ImxVpuLoadSingleton >;
+
+ DISALLOW_COPY_AND_ASSIGN(ImxVpuLoadSingleton);
+
+ base::Lock lock_;
+};
+
+
+} // unnamed namespace end
+
+static const media::VideoCodecProfile kSupportedProfiles[] = {
+ media::H264PROFILE_BASELINE,
+ media::H264PROFILE_MAIN,
+ media::H264PROFILE_HIGH,
+ media::H264PROFILE_MAX,
+ media::VP8PROFILE_ANY,
+};
+
+
+ImxVpuVideoDecodeAccelerator::ImxVpuVideoDecodeAccelerator(
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const GetGLES2DecoderCallback& get_gles2_decoder_cb)
+ : make_context_current_cb_(make_context_current_cb)
+ , get_gles2_decoder_cb_(get_gles2_decoder_cb)
+ , vpu_decoder_(NULL)
+ , initial_info_received_(false)
+{
+ vpu_bitstream_buffer_block_.virtual_address = NULL;
+}
+
+
+ImxVpuVideoDecodeAccelerator::~ImxVpuVideoDecodeAccelerator()
+{
+}
+
+
+bool ImxVpuVideoDecodeAccelerator::Initialize(const Config& config, Client *client)
+{
+ gl::GLContext *context;
+
+ if (config.is_encrypted)
+ {
+ NOTREACHED() << "Encrypted streams are not supported";
+ return false;
+ }
+
+ if (make_context_current_cb_.is_null() || get_gles2_decoder_cb_.is_null()) {
+ NOTREACHED() << "GL callbacks are required for this VDA";
+ return false;
+ }
+
+ client_ptr_factory_.reset(new base::WeakPtrFactory < Client > (client));
+ client_ = client_ptr_factory_->GetWeakPtr();
+
+ base::AutoLock auto_lock(lock_);
+
+ LOG(INFO) << "Initializing i.MX VPU decoder";
+
+ auto gles_decoder = get_gles2_decoder_cb_.Run();
+ if (!gles_decoder)
+ {
+ LOG(ERROR) << "Failed to get gles2 decoder instance.";
+ return false;
+ }
+
+ if (!make_context_current_cb_.Run()) {
+ LOG(ERROR) << "Failed to make this decoder's GL context current.";
+ return false;
+ }
+
+ if ((context = gles_decoder->GetGLContext()) == NULL)
+ {
+ LOG(ERROR) << "GLES2 context is NULL";
+ return false;
+ }
+
+ if (!init_viv_direct_texture(*context, direct_texture_procs_))
+ {
+ LOG(ERROR) << "Initializing the direct texture extension failed";
+ return false;
+ }
+
+ const VideoCodecProfile& profile = config.profile;
+ if ((profile >= media::H264PROFILE_MIN) && (profile <= media::H264PROFILE_MAX))
+ {
+ codec_format_ = IMX_VPU_CODEC_FORMAT_H264;
+ VLOG(1) << "Setting h.264 as codec format";
+ }
+ else if ((profile >= media::VP8PROFILE_MIN) && (profile <= media::VP8PROFILE_MAX))
+ {
+ codec_format_ = IMX_VPU_CODEC_FORMAT_VP8;
+ VLOG(1) << "Setting VP8 as codec format";
+ }
+ else
+ {
+ VLOG(1) << "Unsupported profile";
+ return false;
+ }
+
+ VLOG(1) << "Loading VPU";
+ if (!(ImxVpuLoadSingleton::GetInstance()->Load()))
+ return false;
+
+ if (!AllocateVpuBitstreamBuffer())
+ {
+ ImxVpuLoadSingleton::GetInstance()->Unload();
+ return false;
+ }
+
+ VLOG(1) << "Opening decoder";
+ if (!OpenDecoder())
+ {
+ ImxVpuLoadSingleton::GetInstance()->Unload();
+ return false;
+ }
+
+ VLOG(1) << "Initialization done";
+
+ return true;
+}
+
+
+void ImxVpuVideoDecodeAccelerator::Decode(media::BitstreamBuffer const &bitstream_buffer)
+{
+ VLOG(3) << "Decoding bitstream buffer";
+
+ base::AutoLock auto_lock(lock_);
+
+ input_queue_.push(bitstream_buffer);
+ ProcessQueuedInput();
+}
+
+
+void ImxVpuVideoDecodeAccelerator::AssignPictureBuffers(std::vector < media::PictureBuffer > const &buffers)
+{
+ DCHECK(output_picture_buffers_.empty());
+ DCHECK(buffers.size() == vpu_framebuffers_.size());
+
+ base::AutoLock auto_lock(lock_);
+
+ VLOG(1) << buffers.size() << " picture buffers are being provided by the client";
+
+ const bool have_context = make_context_current_cb_.Run();
+ LOG_IF(WARNING, !have_context)
+ << "Failed to make GL context current for Assign, continuing.";
+
+ for (size_t i = 0; i < buffers.size(); ++i)
+ {
+ int32_t id = buffers[i].id();
+
+ output_picture_buffers_.insert(std::make_pair(id, buffers[i]));
+
+ ImxVpuFramebuffer &framebuffer = vpu_framebuffers_[i];
+ framebuffer.user_data = reinterpret_cast < void* > (id);
+
+ // associate VIV direct textures with VPU framebuffers (one texture per framebuffer)
+ // by mapping the framebuffer to the direct texture
+ // only needs to be done once, since this mapping doesn't change
+ GLuint picture_buffer_texture_id = buffers[i].texture_ids()[0];
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, picture_buffer_texture_id);
+
+ GLvoid *virt_addr = framebuffer.virtual_address;
+ GLuint phys_addr = reinterpret_cast < GLuint > (framebuffer.physical_address);
+
+ direct_texture_procs_.TexDirectVIVMap(
+ GL_TEXTURE_2D,
+ aligned_width_, aligned_height_,
+ GL_VIV_I420,
+ &virt_addr, &phys_addr
+ );
+
+ VLOG(1)
+ << "Associating picture buffer " << i << "/" << buffers.size() << " ID " << id << " with framebuffer #" << i << std::hex
+ << " virtual address " << std::setfill('0') << std::setw(8) << reinterpret_cast < void* > (virt_addr)
+ << " physical address " << std::setfill('0') << std::setw(8) << reinterpret_cast < void* > (phys_addr)
+ << std::dec;
+ }
+
+
+ ProcessQueuedInput();
+}
+
+
+void ImxVpuVideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_buffer_id)
+{
+ base::AutoLock auto_lock(lock_);
+
+ VLOG(3) << "Reusing picture buffer with ID " << picture_buffer_id;
+
+ for (size_t i = 0; i < vpu_framebuffers_.size(); ++i)
+ {
+ ImxVpuFramebuffer &framebuffer = vpu_framebuffers_[i];
+ int32_t id = reinterpret_cast < int32_t > (framebuffer.user_data);
+ if (id == picture_buffer_id)
+ {
+ ImxVpuDecReturnCodes ret;
+
+ if ((ret = imx_vpu_dec_mark_framebuffer_as_displayed(vpu_decoder_, &framebuffer)) != IMX_VPU_DEC_RETURN_CODE_OK)
+ {
+ LOG(ERROR) << "Marking framebuffer for picture buffer with ID " << picture_buffer_id << "as displayed failed : " << imx_vpu_dec_error_string(ret);
+ }
+ else
+ ProcessQueuedInput();
+
+ return;
+ }
+ }
+
+ LOG(WARNING) << "Picture buffer ID " << picture_buffer_id << " could not be associated with a framebuffer";
+}
+
+
+void ImxVpuVideoDecodeAccelerator::Flush()
+{
+ base::AutoLock auto_lock(lock_);
+
+ VLOG(2) << "Flush: processing all currently queued input bitstream buffers";
+ ProcessQueuedInput();
+
+ VLOG(2) << "Flush: draining VPU decoder";
+ imx_vpu_dec_set_drain_mode(vpu_decoder_, 1);
+ while (true)
+ {
+ ProcessRetval pretval = ProcessInput(NULL);
+ if (pretval != ProcessOK)
+ break;
+ // TODO: handle ProcessFail (ProcessEOS should just cause the loop to terminate)
+ }
+ imx_vpu_dec_set_drain_mode(vpu_decoder_, 0);
+
+ VLOG(2) << "Flush: done";
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &Client::NotifyFlushDone,
+ client_
+ )
+ );
+
+}
+
+
+void ImxVpuVideoDecodeAccelerator::Reset()
+{
+ base::AutoLock auto_lock(lock_);
+
+ VLOG(2) << "Reset: flushing decoder";
+ imx_vpu_dec_flush(vpu_decoder_);
+
+ VLOG(2) << "Reset: ending all queued bitstream buffers";
+ while (!input_queue_.empty())
+ {
+ int32_t bitstream_buffer_id = input_queue_.front().id();
+ input_queue_.pop();
+
+ if (bitstream_buffer_id != -1)
+ {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &Client::NotifyEndOfBitstreamBuffer,
+ client_, bitstream_buffer_id
+ )
+ );
+ }
+ }
+
+ BitstreamBufferQueue empty_queue;
+ std::swap(input_queue_, empty_queue);
+
+ VLOG(2) << "Reset: done";
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &Client::NotifyResetDone,
+ client_
+ )
+ );
+}
+
+
+void ImxVpuVideoDecodeAccelerator::Destroy()
+{
+ Cleanup();
+ delete this;
+}
+
+
+// static
+media::VideoDecodeAccelerator::SupportedProfiles
+ImxVpuVideoDecodeAccelerator::GetSupportedProfiles()
+{
+ SupportedProfiles profiles;
+ for (const auto& supported_profile : kSupportedProfiles) {
+ SupportedProfile profile;
+ profile.profile = supported_profile;
+ profile.min_resolution.SetSize(64, 64);
+ profile.max_resolution.SetSize(1920, 1088);
+ profiles.push_back(profile);
+ }
+ return profiles;
+}
+
+
+bool ImxVpuVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
+ const base::WeakPtr<Client>& decode_client,
+ const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner)
+{
+ return false;
+}
+
+
+void ImxVpuVideoDecodeAccelerator::Cleanup()
+{
+ base::AutoLock auto_lock(lock_);
+ client_ptr_factory_.reset();
+
+ CloseDecoder();
+
+ DeallocateVpuBitstreamBuffer();
+
+ ImxVpuLoadSingleton::GetInstance()->Unload();
+}
+
+
+bool ImxVpuVideoDecodeAccelerator::OpenDecoder()
+{
+ lock_.AssertAcquired();
+
+ ImxVpuDecOpenParams open_params;
+
+ open_params.codec_format = codec_format_;
+
+ open_params.enable_frame_reordering = (codec_format_ == IMX_VPU_CODEC_FORMAT_H264) ? 1 : 0;
+
+ // frame width & height are read from the bitstream
+ open_params.frame_width = 0;
+ open_params.frame_height = 0;
+
+ if (imx_vpu_dec_open(&(vpu_decoder_), &open_params, vpu_bitstream_buffer_block_.virtual_address, vpu_bitstream_buffer_block_.physical_address) != IMX_VPU_DEC_RETURN_CODE_OK)
+ return false;
+
+ return true;
+}
+
+
+void ImxVpuVideoDecodeAccelerator::CloseDecoder()
+{
+ lock_.AssertAcquired();
+
+ if (vpu_decoder_ == NULL)
+ return;
+
+ imx_vpu_dec_close(vpu_decoder_);
+ DeallocateVpuFramebuffers();
+
+ vpu_decoder_ = NULL;
+}
+
+
+bool ImxVpuVideoDecodeAccelerator::AllocateVpuBitstreamBuffer()
+{
+ lock_.AssertAcquired();
+
+ ImxVpuDecReturnCodes ret;
+
+ imx_vpu_dec_get_bitstream_buffer_info(&(vpu_bitstream_buffer_block_.alignment), &(vpu_bitstream_buffer_block_.size));
+ if ((ret = imx_vpu_dec_allocate_memory(&vpu_bitstream_buffer_block_)) != IMX_VPU_DEC_RETURN_CODE_OK)
+ {
+ LOG(ERROR) << "Allocating VPU bitstream buffer failed: " << imx_vpu_dec_error_string(ret);
+ return false;
+ }
+ else
+ return true;
+}
+
+
+bool ImxVpuVideoDecodeAccelerator::DeallocateVpuBitstreamBuffer()
+{
+ lock_.AssertAcquired();
+
+ ImxVpuDecReturnCodes ret;
+
+ if (vpu_bitstream_buffer_block_.virtual_address == NULL)
+ return true;
+
+ if ((ret = imx_vpu_dec_deallocate_memory(&vpu_bitstream_buffer_block_)) != IMX_VPU_DEC_RETURN_CODE_OK)
+ {
+ LOG(ERROR) << "Deallocating VPU bitstream buffer failed: " << imx_vpu_dec_error_string(ret);
+ return false;
+ }
+ else
+ return true;
+}
+
+
+bool ImxVpuVideoDecodeAccelerator::AllocateAndRegisterVPUFramebuffers()
+{
+ lock_.AssertAcquired();
+
+ ImxVpuDecReturnCodes ret;
+ unsigned int y_stride, cbcr_stride, y_size, cbcr_size, mvcol_size, total_size;
+
+ aligned_width_ = vpu_dec_initial_info_.frame_width;
+ aligned_height_ = vpu_dec_initial_info_.frame_height;
+
+ imx_vpu_dec_calc_framebuffer_sizes(
+ &vpu_dec_initial_info_,
+ &aligned_width_, &aligned_height_,
+ &y_stride, &cbcr_stride,
+ &y_size, &cbcr_size,
+ &mvcol_size,
+ &total_size
+ );
+
+ vpu_framebuffers_.resize(vpu_dec_initial_info_.min_num_required_framebuffers + media::limits::kMaxVideoFrames);
+ vpu_framebuffer_mem_blocks_.resize(vpu_framebuffers_.size());
+ memset(&(vpu_framebuffers_[0]), 0, sizeof(ImxVpuFramebuffer) * vpu_framebuffers_.size());
+ memset(&(vpu_framebuffer_mem_blocks_[0]), 0, sizeof(ImxVpuMemBlock) * vpu_framebuffers_.size());
+
+ for (unsigned int i = 0; i < vpu_framebuffers_.size(); ++i)
+ {
+ ImxVpuFramebuffer &framebuffer = vpu_framebuffers_[i];
+ ImxVpuMemBlock &memblock = vpu_framebuffer_mem_blocks_[i];
+
+ memblock.size = total_size;
+ memblock.alignment = vpu_dec_initial_info_.framebuffer_alignment;
+ if (imx_vpu_dec_allocate_memory(&memblock) != IMX_VPU_DEC_RETURN_CODE_OK)
+ {
+ LOG(ERROR) << "Could not allocate framebuffer memory for framebuffer " << i << "/" << vpu_framebuffers_.size();
+ memblock.physical_address = 0;
+ return false;
+ }
+
+ framebuffer.y_stride = y_stride;
+ framebuffer.cbcr_stride = cbcr_stride;
+ framebuffer.virtual_address = memblock.virtual_address;
+ framebuffer.physical_address = memblock.physical_address;
+ framebuffer.y_offset = 0;
+ framebuffer.cb_offset = y_size;
+ framebuffer.cr_offset = y_size + cbcr_size;
+ framebuffer.mvcol_offset = y_size + cbcr_size * 2;
+ }
+
+ if ((ret = imx_vpu_dec_register_framebuffers(vpu_decoder_, &(vpu_framebuffers_[0]), vpu_framebuffers_.size())) != IMX_VPU_DEC_RETURN_CODE_OK)
+ {
+ LOG(ERROR) << "Registering framebuffers failed: " << imx_vpu_dec_error_string(ret);
+ return false;
+ }
+ else
+ return true;
+}
+
+
+bool ImxVpuVideoDecodeAccelerator::DeallocateVpuFramebuffers()
+{
+ lock_.AssertAcquired();
+
+ for (unsigned int i = 0; i < vpu_framebuffer_mem_blocks_.size(); ++i)
+ {
+ ImxVpuMemBlock &memblock = vpu_framebuffer_mem_blocks_[i];
+ if (memblock.physical_address != 0)
+ {
+ if (imx_vpu_dec_deallocate_memory(&memblock) != IMX_VPU_DEC_RETURN_CODE_OK)
+ {
+ LOG(ERROR) << "Deallocating memory block of framebuffer " << i << "/" << vpu_framebuffer_mem_blocks_.size() << " failed";
+ }
+ }
+ }
+ vpu_framebuffer_mem_blocks_.clear();
+
+ return true;
+}
+
+
+void ImxVpuVideoDecodeAccelerator::ProcessQueuedInput()
+{
+ lock_.AssertAcquired();
+
+ VLOG(1) << "Input queue size: " << input_queue_.size();
+
+ {
+ if (input_queue_.empty())
+ {
+ VLOG(1) << "Input queue empty - nothing to process";
+ return;
+ }
+
+ if (initial_info_received_ && output_picture_buffers_.empty())
+ {
+ VLOG(1) << "No picture buffers have been provided yet - will try again later";
+ return;
+ }
+
+ if (initial_info_received_ && (imx_vpu_dec_get_num_free_framebuffers(vpu_decoder_) < imx_vpu_dec_get_min_num_free_required(vpu_decoder_)))
+ {
+ VLOG(1) << "Not enough free framebuffers available - will try again later";
+ return;
+ }
+
+ media::BitstreamBuffer const &queued_bitstream_buffer = input_queue_.front();
+ ProcessRetval ret = ProcessInput(&queued_bitstream_buffer);
+ input_queue_.pop();
+
+ if (ret != ProcessOK)
+ return;
+ }
+}
+
+
+ImxVpuVideoDecodeAccelerator::ProcessRetval ImxVpuVideoDecodeAccelerator::ProcessInput(media::BitstreamBuffer const *input_bitstream_buffer)
+{
+ ImxVpuDecReturnCodes ret;
+
+ lock_.AssertAcquired();
+
+
+ ImxVpuEncodedFrame encoded_frame;
+ std::unique_ptr < base::SharedMemory > shm;
+
+ // bitstream_buffer is NULL while draining
+ if (input_bitstream_buffer != NULL)
+ {
+ VLOG(3) << "Processing input bitstream buffer with ID " << input_bitstream_buffer->id();
+
+ shm.reset(new base::SharedMemory(input_bitstream_buffer->handle(), true));
+ // The shared memory block is automatically unmapped by the destructor
+ shm->Map(input_bitstream_buffer->size());
+
+ // The stored bitstream IDs are incremented to make debug output clearer
+ // (otherwise, the imxvpucodec debug printout will print (nil) for the ID 0,
+ // 0x1 for the ID 1 etc.)
+ encoded_frame.virtual_address = shm->memory();
+ encoded_frame.data_size = input_bitstream_buffer->size();
+ encoded_frame.user_data = reinterpret_cast < void* > (input_bitstream_buffer->id() + 1);
+
+ VLOG(3) << "Creating encoded frame (data address " << encoded_frame.virtual_address << " size " << encoded_frame.data_size << " id " << input_bitstream_buffer->id();
+ }
+ else
+ {
+ VLOG(2) << "Setting input data to NULL";
+
+ encoded_frame.virtual_address = NULL;
+ encoded_frame.data_size = 0;
+ encoded_frame.user_data = NULL;
+ }
+
+ encoded_frame.codec_data = NULL;
+ encoded_frame.codec_data_size = 0;
+
+
+ unsigned int output_code;
+ if ((ret = imx_vpu_dec_decode_frame(vpu_decoder_, &encoded_frame, &output_code)) != IMX_VPU_DEC_RETURN_CODE_OK)
+ {
+ LOG(ERROR) << "Decoding frame failed: " << imx_vpu_dec_error_string(ret);
+ return ProcessFailed;
+ }
+
+ VLOG(1) << "Output code of decoded frame: 0x" << std::hex << output_code;
+
+ if (input_bitstream_buffer != NULL)
+ {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &Client::NotifyEndOfBitstreamBuffer,
+ client_,
+ input_bitstream_buffer->id()
+ )
+ );
+ }
+
+ if (output_code & (IMX_VPU_DEC_OUTPUT_CODE_INITIAL_INFO_AVAILABLE | IMX_VPU_DEC_OUTPUT_CODE_RESOLUTION_CHANGED))
+ {
+ VLOG(1) << "Initial information is available - retrieving";
+
+ if ((ret = imx_vpu_dec_get_initial_info(vpu_decoder_, &vpu_dec_initial_info_)) != IMX_VPU_DEC_RETURN_CODE_OK)
+ {
+ LOG(ERROR) << "Retrieving initial info failed: " << imx_vpu_dec_error_string(ret);
+ return ProcessFailed;
+ }
+
+ VLOG(1) << "Initial info: frame size " << vpu_dec_initial_info_.frame_width << "x" << vpu_dec_initial_info_.frame_height << " min num required framebuffers: " << vpu_dec_initial_info_.min_num_required_framebuffers;
+
+ if (
+ !DeallocateVpuFramebuffers() ||
+ !AllocateAndRegisterVPUFramebuffers()
+ )
+ return ProcessFailed;
+
+ initial_info_received_ = true;
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &Client::ProvidePictureBuffers,
+ client_,
+ vpu_framebuffers_.size(),
+ PIXEL_FORMAT_UNKNOWN,
+ 1,
+ gfx::Size(aligned_width_, aligned_height_),
+ GL_TEXTURE_2D
+ )
+ );
+ }
+
+ ProcessRetval pretval = (output_code & IMX_VPU_DEC_OUTPUT_CODE_EOS) ? ProcessEOS : ProcessOK;
+
+ int32_t bitstream_buffer_id = 0;
+ if (output_code & IMX_VPU_DEC_OUTPUT_CODE_FRAME_OUTPUT)
+ {
+ ImxVpuDecodedFrame decoded_frame;
+ if ((ret = imx_vpu_dec_get_decoded_frame(vpu_decoder_, &decoded_frame)) != IMX_VPU_DEC_RETURN_CODE_OK)
+ {
+ LOG(ERROR) << "Retrieving decoded frame failed: " << imx_vpu_dec_error_string(ret);
+ return ProcessFailed;
+ }
+
+ bitstream_buffer_id = reinterpret_cast < int32_t > (decoded_frame.user_data) - 1;
+
+ VLOG(3) << "Decoded frame was retrieved, bitstream buffer id " << bitstream_buffer_id;
+
+ if (decoded_frame.framebuffer == NULL)
+ {
+ LOG(ERROR) << "Framebuffer of decoded frame is NULL";
+ pretval = ProcessFailed;
+ }
+ else
+ {
+ if (!ProcessOutput(*(decoded_frame.framebuffer), bitstream_buffer_id))
+ {
+ // if ProcessOutput returns false, then no picture buffer has
+ // been sent to the client, so the decoded frame must be returned
+ // to the VPU pool here
+ VLOG(1) << "ProcessOutput failed -> returning decoded frame to internal VPU pool";
+ imx_vpu_dec_mark_framebuffer_as_displayed(vpu_decoder_, decoded_frame.framebuffer);
+ pretval = ProcessFailed;
+ }
+
+ // if processing the output was successful, the framebuffer is
+ // _not_ marked as displayed here; this is done in ReusePictureBuffer(),
+ // because only then it is certain that the client is done with that frame
+ }
+ }
+ else if (output_code & IMX_VPU_DEC_OUTPUT_CODE_DROPPED)
+ {
+ void *user_data = imx_vpu_dec_get_dropped_frame_user_data(vpu_decoder_);
+ bitstream_buffer_id = reinterpret_cast < int32_t > (user_data) - 1;
+ VLOG(2) << "Frame was dropped, bitstream buffer id " << bitstream_buffer_id;
+ }
+
+ return pretval;
+}
+
+
+bool ImxVpuVideoDecodeAccelerator::ProcessOutput(ImxVpuFramebuffer const &output_framebuffer, int32_t input_bitstream_buffer_id)
+{
+ lock_.AssertAcquired();
+
+ int32_t picture_buffer_id = reinterpret_cast < int32_t > (output_framebuffer.user_data);
+ OutputBufferMap::const_iterator iter = output_picture_buffers_.find(picture_buffer_id);
+ if (iter == output_picture_buffers_.end())
+ {
+ LOG(ERROR) << "No picture buffer with ID " << picture_buffer_id << " found";
+ return false;
+ }
+ GLuint picture_buffer_texture_id = iter->second.texture_ids()[0];
+
+ const bool have_context = make_context_current_cb_.Run();
+ LOG_IF(WARNING, !have_context)
+ << "Failed to make GL context current for Assign, continuing.";
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, picture_buffer_texture_id);
+
+ direct_texture_procs_.TexDirectInvalidateVIV(GL_TEXTURE_2D);
+
+ auto gles_decoder = get_gles2_decoder_cb_.Run();
+ gles_decoder->RestoreTextureUnitBindings(0);
+ gles_decoder->RestoreActiveTexture();
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &Client::PictureReady,
+ client_,
+ media::Picture(
+ picture_buffer_id,
+ input_bitstream_buffer_id,
+ gfx::Rect(
+ 0,
+ 0,
+ vpu_dec_initial_info_.frame_width,
+ vpu_dec_initial_info_.frame_height
+ ),
+ false
+ )
+ )
+ );
+
+ return true;
+}
+
+
+} // namespace media
diff --git a/src/media/gpu/imxvpu_video_decode_accelerator.h b/src/media/gpu/imxvpu_video_decode_accelerator.h
new file mode 100644
index 0000000..d12e57b
--- /dev/null
+++ b/src/media/gpu/imxvpu_video_decode_accelerator.h
@@ -0,0 +1,112 @@
+#ifndef MEDIA_GPU_IMXVPU_VIDEO_DECODE_ACCELERATOR_H_
+#define MEDIA_GPU_IMXVPU_VIDEO_DECODE_ACCELERATOR_H_
+
+#include <list>
+#include <map>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/memory/linked_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/compiler_specific.h"
+#include "base/synchronization/lock.h"
+#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
+#include "media/base/bitstream_buffer.h"
+#include "media/gpu/gpu_video_decode_accelerator_helpers.h"
+#include "media/gpu/media_gpu_export.h"
+#include "media/video/picture.h"
+#include "media/video/video_decode_accelerator.h"
+
+#include "imxvpucodec.h"
+#include "imx_gl_viv_direct_texture.h"
+
+
+namespace media
+{
+
+
+class MEDIA_GPU_EXPORT ImxVpuVideoDecodeAccelerator
+ : public media::VideoDecodeAccelerator
+{
+public:
+ explicit ImxVpuVideoDecodeAccelerator(
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const GetGLES2DecoderCallback& get_gles2_decoder_cb);
+ ~ImxVpuVideoDecodeAccelerator() override;
+
+ virtual bool Initialize(const Config& config, Client *client) override;
+ virtual void Decode(media::BitstreamBuffer const &bitstream_buffer) override;
+ virtual void AssignPictureBuffers(std::vector < media::PictureBuffer > const &buffers) override;
+ virtual void ReusePictureBuffer(int32_t picture_buffer_id) override;
+ virtual void Flush() override;
+ virtual void Reset() override;
+ virtual void Destroy() override;
+ bool TryToSetupDecodeOnSeparateThread(
+ const base::WeakPtr<Client>& decode_client,
+ const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) override;
+
+ static media::VideoDecodeAccelerator::SupportedProfiles GetSupportedProfiles();
+
+private:
+ enum ProcessRetval
+ {
+ ProcessOK,
+ ProcessEOS,
+ ProcessFailed
+ };
+
+ void Cleanup();
+
+ // VPU specifics
+ bool OpenDecoder();
+ void CloseDecoder();
+ bool AllocateVpuBitstreamBuffer();
+ bool DeallocateVpuBitstreamBuffer();
+ bool AllocateAndRegisterVPUFramebuffers();
+ bool DeallocateVpuFramebuffers();
+
+ // Bitstream buffer and framebuffer processing
+ void ProcessQueuedInput();
+ ProcessRetval ProcessInput(media::BitstreamBuffer const *input_bitstream_buffer);
+ void RequestPictureBuffers();
+ bool ProcessOutput(ImxVpuFramebuffer const &output_framebuffer, int32_t input_bitstream_buffer_id);
+
+
+ std::unique_ptr < base::WeakPtrFactory < Client > > client_ptr_factory_;
+ base::WeakPtr < Client > client_;
+
+ // Callback to set the correct gl context.
+ MakeGLContextCurrentCallback make_context_current_cb_;
+
+ // Callback to get the GLES2Decoder instance.
+ GetGLES2DecoderCallback get_gles2_decoder_cb_;
+
+ typedef std::vector < ImxVpuFramebuffer > ImxVpuFramebuffers;
+ typedef std::vector < ImxVpuMemBlock > ImxVpuMemBlocks;
+ ImxVpuDecoder *vpu_decoder_;
+ ImxVpuCodecFormats codec_format_;
+ ImxVpuMemBlock vpu_bitstream_buffer_block_;
+ ImxVpuDecInitialInfo vpu_dec_initial_info_;
+ ImxVpuFramebuffers vpu_framebuffers_;
+ ImxVpuMemBlocks vpu_framebuffer_mem_blocks_;
+ unsigned int aligned_width_, aligned_height_;
+ bool initial_info_received_;
+
+ GLESVIVDirectTextureProcs direct_texture_procs_;
+
+ base::Lock lock_;
+
+ typedef std::queue < media::BitstreamBuffer > BitstreamBufferQueue;
+ BitstreamBufferQueue input_queue_;
+
+ typedef std::map < int32_t, media::PictureBuffer > OutputBufferMap;
+ OutputBufferMap output_picture_buffers_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImxVpuVideoDecodeAccelerator);
+};
+
+
+} // namespace media
+
+
+#endif // MEDIA_GPU_IMXVPU_VIDEO_DECODE_ACCELERATOR_H_
diff --git a/src/media/gpu/imxvpucodec.h b/src/media/gpu/imxvpucodec.h
new file mode 100644
index 0000000..4fb63b3
--- /dev/null
+++ b/src/media/gpu/imxvpucodec.h
@@ -0,0 +1,418 @@
+/*
+ * imxvpucodec - i.MX6 VPU hardware codec engine API library
+ * Copyright (c) 2014 Carlos Rafael Giani
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any
+ * damages arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute
+ * it freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must
+ * not claim that you wrote the original software. If you use this
+ * software in a product, an acknowledgment in the product
+ * documentation would be appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must
+ * not be misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+
+#ifndef IMXVPUCODEC_H
+#define IMXVPUCODEC_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+/* This library provides a high-level interface for controlling the Freescale
+ * i.MX VPU en/decoder.
+ * Other libraries do not provide a way of associating frames with user defined
+ * information, and lack calls to check the number of currently free framebuffers
+ * (when decoding). The former is required by many media frameworks such as
+ * GStreamer, FFmpeg/libav, the Chromium media codebase etc. The latter is
+ * necessary when framebuffer display and decoding can happen in different
+ * threads (the counter makes it possible to use synchronization primitives
+ * like thread condition variables to wait until enough frames are free).
+ *
+ * Note that the functions are _not_ thread safe. If they may be called from
+ * different threads, you must make sure they are surrounded by a mutex lock.
+ * It is recommended to use one global mutex for the imx_vpu_*_load()/unload()
+ * functions, and another de/encoder instance specific mutex for all of the other
+ * calls.
+ *
+ * How to use the decoder (error handling omitted for clarity):
+ * 1. Call imx_vpu_dec_load()
+ * 2. Call imx_vpu_dec_get_bitstream_buffer_info(), and allocate a DMA buffer
+ * with the given size and alignment.
+ * 3. Fill an instance of ImxVpuDecOpenParams with the values specific to the
+ * input data. In most cases, one wants to set enable_frame_reordering to 1
+ * with h.264 data here.
+ * 4. Call imx_vpu_dec_open(), passing in a pointer to the filled ImxVpuDecOpenParams
+ * instance, and the virtual and physical addresses of the bitstream DMA buffer
+ * which was allocated in step 2.
+ * 5. Call imx_vpu_dec_decode_frame() with the first encoded frame.
+ * If the output_code bitmask contains IMX_VPU_DEC_OUTPUT_CODE_INITIAL_INFO_AVAILABLE,
+ * proceed, otherwise continue feeding in data.
+ * 6. Once IMX_VPU_DEC_OUTPUT_CODE_INITIAL_INFO_AVAILABLE has been set in the output code,
+ * call imx_vpu_dec_get_initial_info() with a pointer to an ImxVpuDecInitialInfo
+ * instance.
+ * 7. (Optional) Perform the necessary size and alignment calculations by calling
+ * imx_vpu_dec_calc_framebuffer_sizes().
+ * 8. Create an array of at least as many ImxVpuFramebuffer instances as specified in
+ * min_num_required_framebuffers. Each instance must point to a DMA buffer that is big
+ * enough to hold a frame. If step 7 was performed, allocating as many bytes as indicated
+ * by total_size is enough. Make sure the Y,Cb,Cr,MvCol offsets in each ImxVpuFramebuffer
+ * instance are valid.
+ * 9. Call imx_vpu_dec_register_framebuffers() and pass in the ImxVpuFramebuffer array
+ * and the number of ImxVpuFramebuffer instances.
+ * 10. Continue calling imx_vpu_dec_decode_frame(). The virtual address in encoded_frame
+ * must not be NULL.
+ * If the IMX_VPU_DEC_OUTPUT_CODE_FRAME_OUTPUT flag is set in the output code,
+ * call imx_vpu_dec_get_decoded_frame() with a pointer to an ImxVpuDecodedFrame instance
+ * which gets filled with information about the decoded frame. Once the decoded frame
+ * has been processed by the user, imx_vpu_dec_mark_framebuffer_as_displayed() must be
+ * called to let the decoder know that the framebuffer is available for storing new
+ * decoded frames again.
+ * If IMX_VPU_DEC_OUTPUT_CODE_DROPPED is set, you can call
+ * imx_vpu_dec_get_dropped_frame_user_data() to retrieve the user_data field
+ * of the dropped frame. If IMX_VPU_DEC_OUTPUT_CODE_EOS is set, stop playback and close
+ * the decoder.
+ * 11. In case a flush/reset is desired (typically after seeking), call imx_vpu_dec_flush().
+ * Note that any internal user_data pointers from the en/decoded frames will be
+ * set to NULL after this call (this is the only exception where the library modifies
+ * the user_data fields).
+ * 12. When there is no more incoming data, and pending decoded frames need to be retrieved
+ * from the decoder, call imx_vpu_dec_set_drain_mode(). This is typically necessary when
+ * the data source reached its end, playback is finishing, and there is a delay
+ * of N frames at the beginning.
+ * After this call, continue calling imx_vpu_dec_decode_frame() to retrieve the pending
+ * decoded frames, but the virtual address of encoded_frame must be NULL.
+ * As in step 10, if IMX_VPU_DEC_OUTPUT_CODE_EOS is set, stop playback, close the decoder.
+ * 13. After playback is finished, close the decoder with imx_vpu_dec_close().
+ * 14. Deallocate framebuffer memory blocks and the bitstream buffer memory block.
+ * 15. Call imx_vpu_dec_unload().
+ *
+ * Step 15 should only be called if no more playback sessions will occur.
+ *
+ * As mentioned before, in situations where decoding and display of decoded frames happen in
+ * different thread, it is necessary to let the decoder wait until enough framebuffers
+ * are free (= available for the VPU to decode into). This is typically done by such a check
+ * (in pseudo code):
+ *
+ * mutex_lock(&mutex);
+ *
+ * while (imx_vpu_dec_get_num_free_framebuffers(decoder) < imx_vpu_dec_get_min_num_free_required(decoder))
+ * condition_wait(&condition_variable, &mutex);
+ *
+ * imx_vpu_dec_decode_frame(decoder, encoded_frame, &output_code);
+ * ...
+ *
+ * mutex_unlock(&mutex);
+ */
+
+
+
+/***********************************************/
+/******* COMMON STRUCTURES AND FUNCTIONS *******/
+/***********************************************/
+
+
+#define IMX_VPU_ALIGN_VAL_TO(LENGTH, ALIGN_SIZE) ( ((uintptr_t)(((uint8_t*)(LENGTH)) + (ALIGN_SIZE) - 1) / (ALIGN_SIZE)) * (ALIGN_SIZE) )
+
+
+typedef uint32_t imx_vpu_phys_addr_t;
+typedef uint32_t imx_vpu_cpu_addr_t; /* used only in allocators so far */
+
+
+typedef enum
+{
+ IMX_VPU_PIC_TYPE_UNKNOWN = 0,
+ IMX_VPU_PIC_TYPE_I,
+ IMX_VPU_PIC_TYPE_P,
+ IMX_VPU_PIC_TYPE_B,
+ IMX_VPU_PIC_TYPE_IDR,
+ IMX_VPU_PIC_TYPE_BI,
+ IMX_VPU_PIC_TYPE_SKIP
+}
+ImxVpuPicType;
+
+
+typedef enum
+{
+ IMX_VPU_CODEC_FORMAT_MPEG2 = 0, /* includes MPEG1 */
+ IMX_VPU_CODEC_FORMAT_MPEG4,
+ IMX_VPU_CODEC_FORMAT_H263,
+ IMX_VPU_CODEC_FORMAT_H264,
+ IMX_VPU_CODEC_FORMAT_H264_MVC,
+ IMX_VPU_CODEC_FORMAT_WMV3,
+ IMX_VPU_CODEC_FORMAT_WVC1,
+ IMX_VPU_CODEC_FORMAT_MJPEG,
+ IMX_VPU_CODEC_FORMAT_VP8
+ /* XXX others will be added when the firmware supports them */
+}
+ImxVpuCodecFormats;
+
+
+typedef enum
+{
+ IMX_VPU_MJPEG_FORMAT_YUV420 = 0, /* also known as I420 */
+ IMX_VPU_MJPEG_FORMAT_YUV422_HORIZONTAL = 1,
+ IMX_VPU_MJPEG_FORMAT_YUV422_VERTICAL = 2, /* 4:2:2 vertical, actually 2:2:4 (according to the VPU docs) */
+ IMX_VPU_MJPEG_FORMAT_YUV444 = 3,
+ IMX_VPU_MJPEG_FORMAT_YUV400 = 4 /* 8-bit grayscale */
+}
+ImxVpuMJpegFormat;
+
+
+typedef struct
+{
+ /* Stride of the Y and of the Cb&Cr components.
+ * Specified in bytes. */
+ unsigned int y_stride, cbcr_stride;
+
+ /* The virtual address of is actually not used by the VPU,
+ * and only of interest to the user. It can be NULL for cases
+ * where only a physical address exists or where a virtual
+ * address is not necessary. */
+ void *virtual_address;
+ /* The physical address must always be valid. */
+ imx_vpu_phys_addr_t physical_address;
+
+ /* These define the starting offsets of each component
+ * relative to the start of the buffer. Specified in bytes.
+ *
+ * mvcol is the "co-located motion vector" data. */
+ size_t
+ y_offset,
+ cb_offset,
+ cr_offset,
+ mvcol_offset;
+
+ /* User-defined pointer. The library does not touch this value.
+ * This can be used to identify framebuffers for example.
+ * Not to be confused with the user_data fields of ImxVpuEncodedFrame
+ * and ImxVpuDecodedFrame. */
+ void *user_data;
+
+ /* Internal, implementation-defined data. Do not modify. */
+ void *internal;
+}
+ImxVpuFramebuffer;
+
+
+typedef struct
+{
+ /* Virtual and physical addresses pointing to the encoded data.
+ * The virtual address must always be valid. The physical address
+ * is only required for encoding. */
+ void *virtual_address;
+ imx_vpu_phys_addr_t physical_address;
+
+ /* Size of the encoded data, in bytes. */
+ unsigned int data_size;
+
+ /* Pointer to out-of-band codec/header data. If such data exists,
+ * specify the pointer to the memory block containing the data,
+ * as well as the size of the memory block (in bytes).
+ * Set pointer and size for every encoded frame when decoding.
+ * If no such data exists or is required, set pointer to NULL and
+ * size to 0. */
+ void *codec_data;
+ unsigned int codec_data_size;
+
+ /* User-defined pointer. The library does not touch this value.
+ * This pointer and the one from the corresponding
+ * decoded frame will have the same value. The library will
+ * pass then through.
+ * It can be used to identify frames and associated corresponding
+ * en- and decoded frames for example. */
+ void *user_data;
+}
+ImxVpuEncodedFrame;
+
+
+typedef struct
+{
+ /* When decoding: pointer to the framebuffer containing the decoded frame.
+ * When encoding: pointer to the framebuffer containing the frame to be encoded.
+ * Must always be valid. */
+ ImxVpuFramebuffer *framebuffer;
+
+ /* picture type (I, P, B, ..) */
+ ImxVpuPicType pic_type;
+
+ /* User-defined pointer. The library does not touch this value.
+ * This pointer and the one from the corresponding
+ * encoded frame will have the same value. The library will
+ * pass then through.
+ * It can be used to identify frames and associated corresponding
+ * en- and decoded frames for example. */
+ void *user_data;
+}
+ImxVpuDecodedFrame;
+
+
+/* This structure is only used by the allocate/deallocate calls below,
+ * which in turn are convenience calls that wrap VPU-provided DMA buffer
+ * allocators. If a different DMA buffer allocator is used (like ION),
+ * this structure does not have to be used. */
+typedef struct
+{
+ size_t size;
+ unsigned int alignment;
+
+ void* virtual_address;
+ imx_vpu_phys_addr_t physical_address;
+ imx_vpu_cpu_addr_t cpu_address;
+
+ void* virtual_address_unaligned;
+ imx_vpu_phys_addr_t physical_address_unaligned;
+}
+ImxVpuMemBlock;
+
+
+
+
+/************************************************/
+/******* DECODER STRUCTURES AND FUNCTIONS *******/
+/************************************************/
+
+
+typedef struct _ImxVpuDecoder ImxVpuDecoder;
+
+
+typedef enum
+{
+ IMX_VPU_DEC_RETURN_CODE_OK = 0,
+ IMX_VPU_DEC_RETURN_CODE_ERROR,
+ IMX_VPU_DEC_RETURN_CODE_INVALID_PARAMS,
+ IMX_VPU_DEC_RETURN_CODE_INVALID_HANDLE,
+ IMX_VPU_DEC_RETURN_CODE_INVALID_FRAMEBUFFER,
+ IMX_VPU_DEC_RETURN_CODE_INSUFFICIENT_FRAMEBUFFERS,
+ IMX_VPU_DEC_RETURN_CODE_INVALID_STRIDE,
+ IMX_VPU_DEC_RETURN_CODE_WRONG_CALL_SEQUENCE,
+ IMX_VPU_DEC_RETURN_CODE_TIMEOUT
+}
+ImxVpuDecReturnCodes;
+
+
+typedef enum
+{
+ IMX_VPU_DEC_OUTPUT_CODE_INPUT_USED = (1UL << 0),
+ IMX_VPU_DEC_OUTPUT_CODE_EOS = (1UL << 1),
+ IMX_VPU_DEC_OUTPUT_CODE_FRAME_OUTPUT = (1UL << 2),
+ IMX_VPU_DEC_OUTPUT_CODE_NO_FRAME_OUTPUT = (1UL << 3),
+ IMX_VPU_DEC_OUTPUT_CODE_DROPPED = (1UL << 4),
+ IMX_VPU_DEC_OUTPUT_CODE_NOT_ENOUGH_OUTPUT_FRAMES = (1UL << 5),
+ IMX_VPU_DEC_OUTPUT_CODE_NOT_ENOUGH_INPUT_DATA = (1UL << 6),
+ IMX_VPU_DEC_OUTPUT_CODE_INITIAL_INFO_AVAILABLE = (1UL << 7),
+ IMX_VPU_DEC_OUTPUT_CODE_RESOLUTION_CHANGED = (1UL << 8),
+ IMX_VPU_DEC_OUTPUT_CODE_DECODE_ONLY = (1UL << 9),
+ IMX_VPU_DEC_OUTPUT_CODE_INTERNAL_RESET = (1UL << 10)
+}
+ImxVpuDecOutputCodes;
+
+
+typedef struct
+{
+ ImxVpuCodecFormats codec_format;
+
+ int enable_frame_reordering;
+ unsigned int frame_width, frame_height;
+}
+ImxVpuDecOpenParams;
+
+
+typedef struct
+{
+ /* Width of height of frames, in pixels. */
+ unsigned int frame_width, frame_height;
+ /* Frame rate ratio. */
+ unsigned int frame_rate_numerator, frame_rate_denominator;
+
+ /* Caller must register at least this many framebuffers
+ * with the decoder. */
+ unsigned int min_num_required_framebuffers;
+
+ /* Pixel format of the decoded frames. For codec formats
+ * other than motion JPEG, this value will always be
+ * IMX_VPU_MJPEG_FORMAT_YUV420. */
+ ImxVpuMJpegFormat mjpeg_source_format;
+
+ /* 0 = no interlacing, 1 = interlacing. */
+ int interlacing;
+
+ /* Fixed point, shifted by 16.
+ * Example: 1.0 -> floor(1.0*(1<<16)) = 0x10000
+ * 0.5 -> floor(0.5*(1<<16)) = 0x8000 */
+ unsigned int width_height_ratio;
+
+ /* Physical framebuffer addresses must be aligned to this value. */
+ unsigned int framebuffer_alignment;
+}
+ImxVpuDecInitialInfo;
+
+
+/* Returns a human-readable description of the error code.
+ * Useful for logging. */
+char const * imx_vpu_dec_error_string(ImxVpuDecReturnCodes code);
+
+/* These two functions load/unload the decoder. Thanks to an internal reference
+ * counter, it is safe to call these functions more than once. However, the
+ * number of unload() calls must match the number of load() calls.
+ *
+ * The decoder must be loaded before doing anything else with the decoder.
+ * Similarly, the decoder must not be unloaded before all decoder activities
+ * have been finished. This includes opening/decoding decoder instances. */
+ImxVpuDecReturnCodes imx_vpu_dec_load(void);
+ImxVpuDecReturnCodes imx_vpu_dec_unload(void);
+
+/* Convenience allocator for allocating DMA buffers. */
+ImxVpuDecReturnCodes imx_vpu_dec_allocate_memory(ImxVpuMemBlock *mem_block);
+ImxVpuDecReturnCodes imx_vpu_dec_deallocate_memory(ImxVpuMemBlock *mem_block);
+
+/* Called before imx_vpu_dec_open(), it returns the alignment and size for the
+ * physical memory block necessary for the decoder's bitstream buffer. The user
+ * must allocate a DMA buffer of at least this size, and its physical address
+ * must be aligned according to the alignment value. */
+void imx_vpu_dec_get_bitstream_buffer_info(unsigned int *alignment, size_t *size);
+
+ImxVpuDecReturnCodes imx_vpu_dec_open(ImxVpuDecoder **decoder, ImxVpuDecOpenParams const *open_params, void *bitstream_buffer_virtual_address, imx_vpu_phys_addr_t bitstream_buffer_physical_address);
+ImxVpuDecReturnCodes imx_vpu_dec_close(ImxVpuDecoder *decoder);
+
+ImxVpuDecReturnCodes imx_vpu_dec_set_drain_mode(ImxVpuDecoder *decoder, int enabled);
+ImxVpuDecReturnCodes imx_vpu_dec_flush(ImxVpuDecoder *decoder);
+
+ImxVpuDecReturnCodes imx_vpu_dec_register_framebuffers(ImxVpuDecoder *decoder, ImxVpuFramebuffer *framebuffers, unsigned int num_framebuffers);
+void imx_vpu_dec_calc_framebuffer_sizes(ImxVpuDecInitialInfo const *initial_info, unsigned int *frame_width, unsigned int *frame_height, unsigned int *y_stride, unsigned int *cbcr_stride, unsigned int *y_size, unsigned int *cbcr_size, unsigned int *mvcol_size, unsigned int *total_size);
+
+ImxVpuDecReturnCodes imx_vpu_dec_get_initial_info(ImxVpuDecoder *decoder, ImxVpuDecInitialInfo *info);
+
+ImxVpuDecReturnCodes imx_vpu_dec_decode_frame(ImxVpuDecoder *decoder, ImxVpuEncodedFrame const *encoded_frame, unsigned int *output_code);
+ImxVpuDecReturnCodes imx_vpu_dec_get_decoded_frame(ImxVpuDecoder *decoder, ImxVpuDecodedFrame *decoded_frame);
+void* imx_vpu_dec_get_dropped_frame_user_data(ImxVpuDecoder *decoder);
+int imx_vpu_dec_get_num_free_framebuffers(ImxVpuDecoder *decoder);
+int imx_vpu_dec_get_min_num_free_required(ImxVpuDecoder *decoder);
+ImxVpuDecReturnCodes imx_vpu_dec_mark_framebuffer_as_displayed(ImxVpuDecoder *decoder, ImxVpuFramebuffer const *framebuffer);
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
diff --git a/src/media/gpu/imxvpucodec_fslwrapper.c b/src/media/gpu/imxvpucodec_fslwrapper.c
new file mode 100644
index 0000000..e425060
--- /dev/null
+++ b/src/media/gpu/imxvpucodec_fslwrapper.c
@@ -0,0 +1,1055 @@
+/*
+ * imxvpucodec - i.MX6 VPU hardware codec engine API library
+ * Copyright (c) 2014 Carlos Rafael Giani
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any
+ * damages arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute
+ * it freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must
+ * not claim that you wrote the original software. If you use this
+ * software in a product, an acknowledgment in the product
+ * documentation would be appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must
+ * not be misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <vpu_wrapper.h>
+#include "imxvpucodec.h"
+#include "imxvpucodec_platform.h"
+
+
+
+
+/***********************************************/
+/******* COMMON STRUCTURES AND FUNCTIONS *******/
+/***********************************************/
+
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+
+#ifndef TRUE
+#define TRUE (1)
+#endif
+
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+
+#ifndef BOOL
+#define BOOL int
+#endif
+
+
+static ImxVpuMJpegFormat convert_from_wrapper_mjpg_format(int format)
+{
+ return (ImxVpuMJpegFormat)format;
+}
+
+
+static ImxVpuPicType convert_from_wrapper_pic_type(VpuPicType type)
+{
+ switch (type)
+ {
+ case VPU_I_PIC: return IMX_VPU_PIC_TYPE_I;
+ case VPU_P_PIC: return IMX_VPU_PIC_TYPE_P;
+ case VPU_B_PIC: return IMX_VPU_PIC_TYPE_B;
+ case VPU_IDR_PIC: return IMX_VPU_PIC_TYPE_IDR;
+ case VPU_BI_PIC: return IMX_VPU_PIC_TYPE_BI;
+ case VPU_SKIP_PIC: return IMX_VPU_PIC_TYPE_SKIP;
+ default: return IMX_VPU_PIC_TYPE_UNKNOWN;
+ }
+}
+
+
+static VpuCodStd convert_to_wrapper_codec_std(ImxVpuCodecFormats format)
+{
+ switch (format)
+ {
+ case IMX_VPU_CODEC_FORMAT_MPEG4: return VPU_V_MPEG4;
+ case IMX_VPU_CODEC_FORMAT_H263: return VPU_V_H263;
+ case IMX_VPU_CODEC_FORMAT_H264: return VPU_V_AVC;
+ case IMX_VPU_CODEC_FORMAT_H264_MVC: return VPU_V_AVC_MVC;
+ case IMX_VPU_CODEC_FORMAT_WMV3: return VPU_V_VC1;
+ case IMX_VPU_CODEC_FORMAT_WVC1: return VPU_V_VC1_AP;
+ case IMX_VPU_CODEC_FORMAT_MPEG2: return VPU_V_MPEG2;
+ case IMX_VPU_CODEC_FORMAT_MJPEG: return VPU_V_MJPG;
+ case IMX_VPU_CODEC_FORMAT_VP8: return VPU_V_VP8;
+ default: assert(FALSE);
+ }
+
+ return VPU_V_MPEG2; /* should never be reached */
+}
+
+
+static void convert_from_wrapper_mem_desc(VpuMemDesc *mem_desc, ImxVpuMemBlock *mem_block)
+{
+ mem_block->size = mem_desc->nSize;
+ mem_block->virtual_address_unaligned = (void*)(mem_desc->nVirtAddr);
+ mem_block->physical_address_unaligned = mem_desc->nPhyAddr;
+ mem_block->cpu_address = mem_desc->nCpuAddr;
+}
+
+
+static void convert_to_wrapper_mem_desc(ImxVpuMemBlock *mem_block, VpuMemDesc *mem_desc)
+{
+ mem_desc->nSize = mem_block->size;
+ mem_desc->nVirtAddr = (unsigned long)(mem_block->virtual_address_unaligned);
+ mem_desc->nPhyAddr = mem_block->physical_address_unaligned;
+ mem_desc->nCpuAddr = mem_block->cpu_address;
+}
+
+
+static void convert_to_wrapper_framebuffer(ImxVpuFramebuffer *fb, VpuFrameBuffer *wrapper_fb)
+{
+ memset(wrapper_fb, 0, sizeof(VpuFrameBuffer));
+
+ wrapper_fb->nStrideY = fb->y_stride;
+ wrapper_fb->nStrideC = fb->cbcr_stride;
+
+ wrapper_fb->pbufY = (unsigned char*)(fb->physical_address + fb->y_offset);
+ wrapper_fb->pbufCb = (unsigned char*)(fb->physical_address + fb->cb_offset);
+ wrapper_fb->pbufCr = (unsigned char*)(fb->physical_address + fb->cr_offset);
+ wrapper_fb->pbufMvCol = (unsigned char*)(fb->physical_address + fb->mvcol_offset);
+}
+
+
+
+
+/************************************************/
+/******* DECODER STRUCTURES AND FUNCTIONS *******/
+/************************************************/
+
+
+#define MIN_NUM_FREE_FB_REQUIRED 6
+#define FRAME_ALIGN 16
+
+
+struct _ImxVpuDecoder
+{
+ VpuDecHandle handle;
+
+ void *virt_mem_sub_block;
+ size_t virt_mem_sub_block_size;
+
+ ImxVpuCodecFormats codec_format;
+
+ unsigned int num_framebuffers;
+ VpuFrameBuffer **wrapper_framebuffers;
+ ImxVpuFramebuffer *framebuffers;
+ void **user_data_for_frames;
+ void *pending_user_data;
+ void *dropped_frame_user_data;
+ int num_user_data;
+ BOOL delay_pending_user_data;
+ void *last_pending_user_data;
+
+ BOOL consumption_info_available;
+ BOOL flush_vpu_upon_reset;
+
+ BOOL recalculate_num_avail_framebuffers;
+ int num_available_framebuffers;
+ int num_times_counter_decremented;
+ int num_framebuffers_in_use;
+};
+
+
+static ImxVpuDecReturnCodes dec_convert_retcode(VpuDecRetCode code)
+{
+ switch (code)
+ {
+ case VPU_DEC_RET_SUCCESS: return IMX_VPU_DEC_RETURN_CODE_OK;
+ case VPU_DEC_RET_FAILURE: return IMX_VPU_DEC_RETURN_CODE_ERROR;
+ case VPU_DEC_RET_INVALID_PARAM: return IMX_VPU_DEC_RETURN_CODE_INVALID_PARAMS;
+ case VPU_DEC_RET_INVALID_HANDLE: return IMX_VPU_DEC_RETURN_CODE_INVALID_HANDLE;
+ case VPU_DEC_RET_INVALID_FRAME_BUFFER: return IMX_VPU_DEC_RETURN_CODE_INVALID_FRAMEBUFFER;
+ case VPU_DEC_RET_INSUFFICIENT_FRAME_BUFFERS: return IMX_VPU_DEC_RETURN_CODE_INSUFFICIENT_FRAMEBUFFERS;
+ case VPU_DEC_RET_INVALID_STRIDE: return IMX_VPU_DEC_RETURN_CODE_INVALID_STRIDE;
+ case VPU_DEC_RET_WRONG_CALL_SEQUENCE: return IMX_VPU_DEC_RETURN_CODE_WRONG_CALL_SEQUENCE;
+ case VPU_DEC_RET_FAILURE_TIMEOUT: return IMX_VPU_DEC_RETURN_CODE_TIMEOUT;
+
+ default: return IMX_VPU_DEC_RETURN_CODE_ERROR;
+ }
+}
+
+
+static unsigned int dec_convert_outcode(VpuDecBufRetCode code)
+{
+ /* TODO: REPEAT? SKIP? */
+ unsigned int out = 0;
+ if (code & VPU_DEC_INPUT_USED) out |= IMX_VPU_DEC_OUTPUT_CODE_INPUT_USED;
+ if (code & VPU_DEC_OUTPUT_EOS) out |= IMX_VPU_DEC_OUTPUT_CODE_EOS;
+ if (code & VPU_DEC_OUTPUT_DIS) out |= IMX_VPU_DEC_OUTPUT_CODE_FRAME_OUTPUT;
+ if (code & VPU_DEC_OUTPUT_NODIS) out |= IMX_VPU_DEC_OUTPUT_CODE_NO_FRAME_OUTPUT;
+ if (code & VPU_DEC_OUTPUT_DROPPED) out |= IMX_VPU_DEC_OUTPUT_CODE_DROPPED;
+ if (code & VPU_DEC_OUTPUT_MOSAIC_DIS) out |= IMX_VPU_DEC_OUTPUT_CODE_DROPPED; /* mosaic frames are dropped */
+ if (code & VPU_DEC_NO_ENOUGH_BUF) out |= IMX_VPU_DEC_OUTPUT_CODE_NOT_ENOUGH_OUTPUT_FRAMES;
+ if (code & VPU_DEC_NO_ENOUGH_INBUF) out |= IMX_VPU_DEC_OUTPUT_CODE_NOT_ENOUGH_INPUT_DATA;
+ if (code & VPU_DEC_INIT_OK) out |= IMX_VPU_DEC_OUTPUT_CODE_INITIAL_INFO_AVAILABLE;
+ if (code & VPU_DEC_RESOLUTION_CHANGED) out |= IMX_VPU_DEC_OUTPUT_CODE_RESOLUTION_CHANGED;
+ return out;
+}
+
+
+static void dec_convert_to_wrapper_open_param(ImxVpuDecOpenParams const *open_params, VpuDecOpenParam *wrapper_open_param)
+{
+ memset(wrapper_open_param, 0, sizeof(VpuDecOpenParam));
+
+ wrapper_open_param->CodecFormat = convert_to_wrapper_codec_std(open_params->codec_format);
+ wrapper_open_param->nReorderEnable = open_params->enable_frame_reordering;
+ wrapper_open_param->nPicWidth = open_params->frame_width;
+ wrapper_open_param->nPicHeight = open_params->frame_height;
+}
+
+
+static void dec_convert_from_wrapper_initial_info(VpuDecInitInfo *wrapper_info, ImxVpuDecInitialInfo *info)
+{
+ info->frame_width = wrapper_info->nPicWidth;
+ info->frame_height = wrapper_info->nPicHeight;
+ info->frame_rate_numerator = wrapper_info->nFrameRateRes;
+ info->frame_rate_denominator = wrapper_info->nFrameRateDiv;
+
+ info->min_num_required_framebuffers = wrapper_info->nMinFrameBufferCount + MIN_NUM_FREE_FB_REQUIRED;
+ info->mjpeg_source_format = convert_from_wrapper_mjpg_format(wrapper_info->nMjpgSourceFormat);
+
+ info->interlacing = wrapper_info->nInterlace;
+
+ info->width_height_ratio = wrapper_info->nQ16ShiftWidthDivHeightRatio;
+
+ info->framebuffer_alignment = wrapper_info->nAddressAlignment;
+}
+
+
+static int dec_get_wrapper_framebuffer_index(ImxVpuDecoder *decoder, VpuFrameBuffer *wrapper_fb)
+{
+ unsigned int i;
+
+ // TODO: do something faster, like a hash table
+ for (i = 0; i < decoder->num_framebuffers; ++i)
+ {
+ if (wrapper_fb == decoder->wrapper_framebuffers[i])
+ return (int)i;
+ }
+ return -1;
+}
+
+
+char const * imx_vpu_dec_error_string(ImxVpuDecReturnCodes code)
+{
+ switch (code)
+ {
+ case IMX_VPU_DEC_RETURN_CODE_OK: return "ok";
+ case IMX_VPU_DEC_RETURN_CODE_ERROR: return "unspecified error";
+ case IMX_VPU_DEC_RETURN_CODE_INVALID_PARAMS: return "invalid params";
+ case IMX_VPU_DEC_RETURN_CODE_INVALID_HANDLE: return "invalid handle";
+ case IMX_VPU_DEC_RETURN_CODE_INVALID_FRAMEBUFFER: return "invalid framebuffer";
+ case IMX_VPU_DEC_RETURN_CODE_INSUFFICIENT_FRAMEBUFFERS: return "insufficient_framebuffers";
+ case IMX_VPU_DEC_RETURN_CODE_INVALID_STRIDE: return "invalid stride";
+ case IMX_VPU_DEC_RETURN_CODE_WRONG_CALL_SEQUENCE: return "wrong call sequence";
+ case IMX_VPU_DEC_RETURN_CODE_TIMEOUT: return "timeout";
+ default: return "<unknown>";
+ }
+}
+
+
+static unsigned long vpu_load_inst_counter = 0;
+
+
+ImxVpuDecReturnCodes imx_vpu_dec_load(void)
+{
+ IMX_VPU_TRACE("VPU load instance counter: %lu", vpu_load_inst_counter);
+ if (vpu_load_inst_counter == 0)
+ {
+ ImxVpuDecReturnCodes ret = dec_convert_retcode(VPU_DecLoad());
+ if (ret != IMX_VPU_DEC_RETURN_CODE_OK)
+ {
+ IMX_VPU_ERROR("loading decoder failed: %s", imx_vpu_dec_error_string(ret));
+ return ret;
+ }
+ else
+ IMX_VPU_TRACE("loaded decoder");
+ }
+
+ ++vpu_load_inst_counter;
+
+ return IMX_VPU_DEC_RETURN_CODE_OK;
+}
+
+
+ImxVpuDecReturnCodes imx_vpu_dec_unload(void)
+{
+ IMX_VPU_TRACE("VPU load instance counter: %lu", vpu_load_inst_counter);
+ if (vpu_load_inst_counter == 1)
+ {
+ ImxVpuDecReturnCodes ret = dec_convert_retcode(VPU_DecUnLoad());
+ if (ret != IMX_VPU_DEC_RETURN_CODE_OK)
+ {
+ IMX_VPU_ERROR("unloading decoder failed: %s", imx_vpu_dec_error_string(ret));
+ return ret;
+ }
+ else
+ IMX_VPU_TRACE("unloaded decoder");
+ }
+
+ if (vpu_load_inst_counter > 0)
+ --vpu_load_inst_counter;
+
+ return IMX_VPU_DEC_RETURN_CODE_OK;
+}
+
+
+ImxVpuDecReturnCodes imx_vpu_dec_allocate_memory(ImxVpuMemBlock *mem_block)
+{
+ VpuDecRetCode ret;
+ VpuMemDesc mem_desc;
+
+ if (mem_block->alignment == 0)
+ mem_block->alignment = 1;
+
+ mem_desc.nSize = mem_block->size + mem_block->alignment;
+
+ if ((ret = VPU_DecGetMem(&mem_desc)) != VPU_DEC_RET_SUCCESS)
+ {
+ IMX_VPU_ERROR("allocating %d bytes of physical memory failed: %s", mem_block->size, imx_vpu_dec_error_string(dec_convert_retcode(ret)));
+ return dec_convert_retcode(ret);
+ }
+ else
+ IMX_VPU_TRACE("allocated %d bytes of physical memory", mem_block->size);
+
+ convert_from_wrapper_mem_desc(&mem_desc, mem_block);
+
+ mem_block->virtual_address = (void *)IMX_VPU_ALIGN_VAL_TO(mem_block->virtual_address_unaligned, mem_block->alignment);
+ mem_block->physical_address = (imx_vpu_phys_addr_t)IMX_VPU_ALIGN_VAL_TO(mem_block->physical_address_unaligned, mem_block->alignment);
+
+ return IMX_VPU_DEC_RETURN_CODE_OK;
+}
+
+
+ImxVpuDecReturnCodes imx_vpu_dec_deallocate_memory(ImxVpuMemBlock *mem_block)
+{
+ ImxVpuDecReturnCodes ret;
+ VpuMemDesc mem_desc;
+
+ convert_to_wrapper_mem_desc(mem_block, &mem_desc);
+
+ ret = dec_convert_retcode(VPU_DecFreeMem(&mem_desc));
+ if (ret != IMX_VPU_DEC_RETURN_CODE_OK)
+ IMX_VPU_ERROR("deallocating %d bytes of physical memory failed: %s", mem_block->size, imx_vpu_dec_error_string(ret));
+ else
+ IMX_VPU_TRACE("deallocated %d bytes of physical memory", mem_block->size);
+
+ return ret;
+}
+
+
+void imx_vpu_dec_get_bitstream_buffer_info(unsigned int *alignment, size_t *size)
+{
+ int i;
+ VpuMemInfo mem_info;
+
+ VPU_DecQueryMem(&mem_info);
+
+ /* only two sub blocks are ever present - get the VPU_MEM_PHY one */
+
+ for (i = 0; i < mem_info.nSubBlockNum; ++i)
+ {
+ if (mem_info.MemSubBlock[i].MemType == VPU_MEM_PHY)
+ {
+ *alignment = mem_info.MemSubBlock[i].nAlignment;
+ *size = mem_info.MemSubBlock[i].nSize;
+ IMX_VPU_TRACE("determined alignment %d and size %d for the physical memory for the bitstream buffer", *alignment, *size);
+ break;
+ }
+ }
+
+ /* virtual memory block is allocated internally inside imx_vpu_dec_open() */
+}
+
+
+ImxVpuDecReturnCodes imx_vpu_dec_open(ImxVpuDecoder **decoder, ImxVpuDecOpenParams const *open_params, void *bitstream_buffer_virtual_address, imx_vpu_phys_addr_t bitstream_buffer_physical_addres)
+{
+ int config_param;
+ VpuDecRetCode ret;
+ VpuMemInfo mem_info;
+ VpuDecOpenParam open_param;
+
+ *decoder = IMX_VPU_ALLOC(sizeof(ImxVpuDecoder));
+ if ((*decoder) == NULL)
+ {
+ IMX_VPU_ERROR("allocating memory for decoder object failed");
+ return IMX_VPU_DEC_RETURN_CODE_ERROR;
+ }
+
+ memset(*decoder, 0, sizeof(ImxVpuDecoder));
+
+ {
+ int i;
+
+ VPU_DecQueryMem(&mem_info);
+
+ IMX_VPU_INFO("about to allocate %d memory sub blocks", mem_info.nSubBlockNum);
+ for (i = 0; i < mem_info.nSubBlockNum; ++i)
+ {
+ char const *type_str = "<unknown>";
+ VpuMemSubBlockInfo *sub_block = &(mem_info.MemSubBlock[i]);
+
+ switch (sub_block->MemType)
+ {
+ case VPU_MEM_VIRT:
+ type_str = "virtual";
+
+ (*decoder)->virt_mem_sub_block_size = sub_block->nSize + sub_block->nAlignment;
+ (*decoder)->virt_mem_sub_block = IMX_VPU_ALLOC((*decoder)->virt_mem_sub_block_size);
+ if ((*decoder)->virt_mem_sub_block == NULL)
+ {
+ IMX_VPU_ERROR("allocating memory for sub block failed");
+ return IMX_VPU_DEC_RETURN_CODE_ERROR;
+ }
+
+ sub_block->pVirtAddr = (unsigned char *)IMX_VPU_ALIGN_VAL_TO((*decoder)->virt_mem_sub_block, sub_block->nAlignment);
+ sub_block->pPhyAddr = 0;
+ break;
+
+ case VPU_MEM_PHY:
+ type_str = "physical";
+
+ sub_block->pVirtAddr = (unsigned char *)(bitstream_buffer_virtual_address);
+ sub_block->pPhyAddr = (unsigned char *)(bitstream_buffer_physical_addres);
+ break;
+ default:
+ break;
+ }
+
+ IMX_VPU_INFO("allocated memory sub block #%d: type: %s size: %d alignment: %d virtual address: %p physical address: %p", i, type_str, sub_block->nSize, sub_block->nAlignment, sub_block->pVirtAddr, sub_block->pPhyAddr);
+ }
+ }
+
+ dec_convert_to_wrapper_open_param(open_params, &open_param);
+
+ IMX_VPU_TRACE("opening decoder");
+
+ switch (open_params->codec_format)
+ {
+ case IMX_VPU_CODEC_FORMAT_H264:
+ case IMX_VPU_CODEC_FORMAT_H264_MVC:
+ case IMX_VPU_CODEC_FORMAT_MPEG2:
+ case IMX_VPU_CODEC_FORMAT_MPEG4:
+ (*decoder)->consumption_info_available = TRUE;
+ (*decoder)->flush_vpu_upon_reset = TRUE;
+ break;
+ case IMX_VPU_CODEC_FORMAT_H263:
+ case IMX_VPU_CODEC_FORMAT_WMV3:
+ case IMX_VPU_CODEC_FORMAT_WVC1:
+ (*decoder)->consumption_info_available = FALSE;
+ (*decoder)->flush_vpu_upon_reset = FALSE;
+ break;
+ case IMX_VPU_CODEC_FORMAT_MJPEG:
+ case IMX_VPU_CODEC_FORMAT_VP8:
+ (*decoder)->consumption_info_available = FALSE;
+ (*decoder)->flush_vpu_upon_reset = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ ret = VPU_DecOpen(&((*decoder)->handle), &open_param, &mem_info);
+ if (ret != VPU_DEC_RET_SUCCESS)
+ {
+ IMX_VPU_ERROR("opening decoder failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
+ goto cleanup;
+ }
+
+ IMX_VPU_TRACE("setting configuration");
+
+ config_param = VPU_DEC_SKIPNONE;
+ ret = VPU_DecConfig((*decoder)->handle, VPU_DEC_CONF_SKIPMODE, &config_param);
+ if (ret != VPU_DEC_RET_SUCCESS)
+ {
+ IMX_VPU_ERROR("setting skipmode to NONE failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
+ goto cleanup;
+ }
+
+ config_param = 0;
+ ret = VPU_DecConfig((*decoder)->handle, VPU_DEC_CONF_BUFDELAY, &config_param);
+ if (ret != VPU_DEC_RET_SUCCESS)
+ {
+ IMX_VPU_ERROR("setting bufdelay to 0 failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
+ goto cleanup;
+ }
+
+ config_param = VPU_DEC_IN_NORMAL;
+ ret = VPU_DecConfig((*decoder)->handle, VPU_DEC_CONF_INPUTTYPE, &config_param);
+ if (ret != VPU_DEC_RET_SUCCESS)
+ {
+ IMX_VPU_ERROR("setting input type to \"normal\" failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
+ goto cleanup;
+ }
+
+ (*decoder)->codec_format = open_params->codec_format;
+
+finish:
+ if (ret == VPU_DEC_RET_SUCCESS)
+ IMX_VPU_TRACE("successfully opened decoder");
+
+ return dec_convert_retcode(ret);
+
+cleanup:
+ if ((*decoder)->virt_mem_sub_block != NULL)
+ IMX_VPU_FREE((*decoder)->virt_mem_sub_block, (*decoder)->virt_mem_sub_block_size);
+ IMX_VPU_FREE(*decoder, sizeof(ImxVpuDecoder));
+ *decoder = NULL;
+
+ goto finish;
+}
+
+
+ImxVpuDecReturnCodes imx_vpu_dec_close(ImxVpuDecoder *decoder)
+{
+ VpuDecRetCode ret;
+
+ IMX_VPU_TRACE("closing decoder");
+
+ ret = VPU_DecFlushAll(decoder->handle);
+ if (ret == VPU_DEC_RET_FAILURE_TIMEOUT)
+ {
+ IMX_VPU_WARNING("resetting decoder after a timeout occurred");
+ ret = VPU_DecReset(decoder->handle);
+ if (ret != VPU_DEC_RET_SUCCESS)
+ IMX_VPU_ERROR("resetting decoder failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
+ }
+ else if (ret != VPU_DEC_RET_SUCCESS)
+ IMX_VPU_ERROR("flushing decoder failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
+
+ ret = VPU_DecClose(decoder->handle);
+ if (ret != VPU_DEC_RET_SUCCESS)
+ IMX_VPU_ERROR("closing decoder failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
+
+ if (decoder->user_data_for_frames != NULL)
+ IMX_VPU_FREE(decoder->user_data_for_frames, sizeof(void*) * decoder->num_framebuffers);
+ if (decoder->wrapper_framebuffers != NULL)
+ IMX_VPU_FREE(decoder->wrapper_framebuffers, sizeof(VpuFrameBuffer*) * decoder->num_framebuffers);
+ if (decoder->virt_mem_sub_block != NULL)
+ IMX_VPU_FREE(decoder->virt_mem_sub_block, decoder->virt_mem_sub_block_size);
+ IMX_VPU_FREE(decoder, sizeof(ImxVpuDecoder));
+
+ IMX_VPU_TRACE("closed decoder");
+
+ return dec_convert_retcode(ret);
+}
+
+
+ImxVpuDecReturnCodes imx_vpu_dec_set_drain_mode(ImxVpuDecoder *decoder, int enabled)
+{
+ int config_param;
+ VpuDecRetCode ret;
+
+ config_param = enabled ? VPU_DEC_IN_DRAIN : VPU_DEC_IN_NORMAL;
+ ret = VPU_DecConfig(decoder->handle, VPU_DEC_CONF_INPUTTYPE, &config_param);
+
+ if (ret != VPU_DEC_RET_SUCCESS)
+ IMX_VPU_ERROR("setting decoder drain mode failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
+ else
+ IMX_VPU_INFO("set decoder drain mode to %d", enabled);
+
+ return dec_convert_retcode(ret);
+}
+
+
+ImxVpuDecReturnCodes imx_vpu_dec_flush(ImxVpuDecoder *decoder)
+{
+ VpuDecRetCode ret = VPU_DEC_RET_SUCCESS;
+
+ decoder->delay_pending_user_data = FALSE;
+
+ if (decoder->flush_vpu_upon_reset)
+ {
+ ret = VPU_DecFlushAll(decoder->handle);
+ if (ret == VPU_DEC_RET_FAILURE_TIMEOUT)
+ {
+ IMX_VPU_WARNING("resetting decoder after a timeout occurred");
+ ret = VPU_DecReset(decoder->handle);
+ if (ret != VPU_DEC_RET_SUCCESS)
+ IMX_VPU_ERROR("resetting decoder failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
+ }
+ else if (ret != VPU_DEC_RET_SUCCESS)
+ IMX_VPU_ERROR("flushing decoder failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
+ else
+ IMX_VPU_INFO("flushed decoder");
+
+ decoder->recalculate_num_avail_framebuffers = TRUE;
+ }
+ else
+ IMX_VPU_INFO("decoder not flushed, because it is unnecessary for this codec format");
+
+ if (decoder->user_data_for_frames != NULL)
+ memset(decoder->user_data_for_frames, 0, sizeof(void*) * decoder->num_framebuffers);
+ decoder->num_user_data = 0;
+
+ return dec_convert_retcode(ret);
+}
+
+
+ImxVpuDecReturnCodes imx_vpu_dec_register_framebuffers(ImxVpuDecoder *decoder, ImxVpuFramebuffer *framebuffers, unsigned int num_framebuffers)
+{
+ unsigned int i;
+ VpuDecRetCode ret;
+ VpuFrameBuffer *temp_fbs;
+
+ IMX_VPU_TRACE("attempting to register %u framebuffers", num_framebuffers);
+
+ decoder->wrapper_framebuffers = NULL;
+
+ temp_fbs = IMX_VPU_ALLOC(sizeof(VpuFrameBuffer) * num_framebuffers);
+ if (temp_fbs == NULL)
+ {
+ IMX_VPU_ERROR("allocating memory for framebuffers failed");
+ return IMX_VPU_DEC_RETURN_CODE_ERROR;
+ }
+
+ for (i = 0; i < num_framebuffers; ++i)
+ convert_to_wrapper_framebuffer(&framebuffers[i], &(temp_fbs[i]));
+
+ ret = VPU_DecRegisterFrameBuffer(decoder->handle, temp_fbs, num_framebuffers);
+
+ IMX_VPU_FREE(temp_fbs, sizeof(VpuFrameBuffer) * num_framebuffers);
+
+ if (ret != VPU_DEC_RET_SUCCESS)
+ {
+ ImxVpuDecReturnCodes imxret = dec_convert_retcode(ret);
+ IMX_VPU_ERROR("registering framebuffers failed: %s", imx_vpu_dec_error_string(imxret));
+ return ret;
+ }
+
+ decoder->wrapper_framebuffers = IMX_VPU_ALLOC(sizeof(VpuFrameBuffer*) * num_framebuffers);
+ {
+ int out_num;
+ VPU_DecAllRegFrameInfo(decoder->handle, decoder->wrapper_framebuffers, &out_num);
+ IMX_VPU_LOG("out_num: %d num_framebuffers: %u", out_num, num_framebuffers);
+ }
+
+ decoder->framebuffers = framebuffers;
+ decoder->num_framebuffers = num_framebuffers;
+ decoder->num_available_framebuffers = num_framebuffers;
+
+ decoder->user_data_for_frames = IMX_VPU_ALLOC(sizeof(void*) * num_framebuffers);
+ if (decoder->user_data_for_frames == NULL)
+ {
+ IMX_VPU_ERROR("allocating memory for user data failed");
+ IMX_VPU_FREE(decoder->wrapper_framebuffers, sizeof(VpuFrameBuffer*) * num_framebuffers);
+ decoder->wrapper_framebuffers = NULL;
+ return IMX_VPU_DEC_RETURN_CODE_ERROR;
+ }
+
+ memset(decoder->user_data_for_frames, 0, sizeof(void*) * num_framebuffers);
+ decoder->num_user_data = 0;
+
+ return IMX_VPU_DEC_RETURN_CODE_OK;
+}
+
+
+void imx_vpu_dec_calc_framebuffer_sizes(ImxVpuDecInitialInfo const *initial_info, unsigned int *frame_width, unsigned int *frame_height, unsigned int *y_stride, unsigned int *uv_stride, unsigned int *y_size, unsigned int *uv_size, unsigned int *mvcol_size, unsigned int *total_size)
+{
+ int alignment;
+
+ *frame_width = IMX_VPU_ALIGN_VAL_TO(*frame_width, FRAME_ALIGN);
+ if (initial_info->interlacing)
+ *frame_height = IMX_VPU_ALIGN_VAL_TO(*frame_height, (2 * FRAME_ALIGN));
+ else
+ *frame_height = IMX_VPU_ALIGN_VAL_TO(*frame_height, FRAME_ALIGN);
+
+ *y_stride = *frame_width;
+ *y_size = (*y_stride) * (*frame_height);
+
+ switch (initial_info->mjpeg_source_format)
+ {
+ case IMX_VPU_MJPEG_FORMAT_YUV420:
+ *uv_stride = *y_stride / 2;
+ *uv_size = *mvcol_size = *y_size / 4;
+ break;
+ case IMX_VPU_MJPEG_FORMAT_YUV422_HORIZONTAL:
+ *uv_stride = *y_stride / 2;
+ *uv_size = *mvcol_size = *y_size / 2;
+ break;
+ case IMX_VPU_MJPEG_FORMAT_YUV444:
+ *uv_stride = *y_stride;
+ *uv_size = *mvcol_size = *y_size;
+ break;
+ case IMX_VPU_MJPEG_FORMAT_YUV400:
+ /* TODO: check if this is OK */
+ *uv_stride = 0;
+ *uv_size = *mvcol_size = 0;
+ break;
+ default:
+ assert(FALSE);
+ }
+
+ alignment = initial_info->framebuffer_alignment;
+ if (alignment > 1)
+ {
+ *y_size = IMX_VPU_ALIGN_VAL_TO(*y_size, alignment);
+ *uv_size = IMX_VPU_ALIGN_VAL_TO(*uv_size, alignment);
+ *mvcol_size = IMX_VPU_ALIGN_VAL_TO(*mvcol_size, alignment);
+ }
+
+ *total_size = *y_size + *uv_size + *uv_size + *mvcol_size + alignment;
+}
+
+
+ImxVpuDecReturnCodes imx_vpu_dec_get_initial_info(ImxVpuDecoder *decoder, ImxVpuDecInitialInfo *info)
+{
+ VpuDecRetCode ret;
+ VpuDecInitInfo init_info;
+
+ ret = VPU_DecGetInitialInfo(decoder->handle, &init_info);
+ IMX_VPU_LOG("VPU_DecGetInitialInfo: min num framebuffers required: %d", init_info.nMinFrameBufferCount);
+ dec_convert_from_wrapper_initial_info(&init_info, info);
+ return dec_convert_retcode(ret);
+}
+
+
+ImxVpuDecReturnCodes imx_vpu_dec_decode_frame(ImxVpuDecoder *decoder, ImxVpuEncodedFrame const *encoded_frame, unsigned int *output_code)
+{
+ VpuDecRetCode ret;
+ VpuBufferNode node;
+ int buf_ret_code;
+
+ node.pVirAddr = encoded_frame->virtual_address;
+ node.pPhyAddr = 0; /* encoded data is always read from a regular memory block, not a DMA buffer */
+ node.nSize = encoded_frame->data_size;
+
+ node.sCodecData.pData = encoded_frame->codec_data;
+ node.sCodecData.nSize = encoded_frame->codec_data_size;
+
+ decoder->pending_user_data = encoded_frame->user_data;
+
+ ret = VPU_DecDecodeBuf(decoder->handle, &node, &buf_ret_code);
+ IMX_VPU_LOG("VPU_DecDecodeBuf buf ret code: 0x%x", buf_ret_code);
+
+ *output_code = dec_convert_outcode(buf_ret_code);
+
+ if (ret != VPU_DEC_RET_SUCCESS)
+ {
+ IMX_VPU_ERROR("decoding frame failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret)));
+ return dec_convert_retcode(ret);
+ }
+
+ if (decoder->recalculate_num_avail_framebuffers)
+ {
+ decoder->num_available_framebuffers = decoder->num_framebuffers - decoder->num_framebuffers_in_use;
+ IMX_VPU_LOG("recalculated number of available framebuffers to %d", decoder->num_available_framebuffers);
+ decoder->recalculate_num_avail_framebuffers = FALSE;
+ }
+
+ if (buf_ret_code & VPU_DEC_INIT_OK)
+ {
+ decoder->delay_pending_user_data = TRUE;
+ decoder->last_pending_user_data = decoder->pending_user_data;
+ }
+
+ if (buf_ret_code & VPU_DEC_FLUSH)
+ {
+ IMX_VPU_INFO("VPU requested a decoder flush");
+ ret = VPU_DecFlushAll(decoder->handle);
+ if (ret == VPU_DEC_RET_FAILURE_TIMEOUT)
+ {
+ IMX_VPU_WARNING("timeout detected, resetting decoder");
+
+ ret = VPU_DecReset(decoder->handle);
+ if (ret != VPU_DEC_RET_SUCCESS)
+ {
+ ImxVpuDecReturnCodes imxret = dec_convert_retcode(ret);
+ IMX_VPU_ERROR("resetting decoder failed: %s", imx_vpu_dec_error_string(imxret));
+ return imxret;
+ }
+ else
+ *output_code |= IMX_VPU_DEC_OUTPUT_CODE_INTERNAL_RESET;
+ }
+ else if (ret != VPU_DEC_RET_SUCCESS)
+ {
+ ImxVpuDecReturnCodes imxret = dec_convert_retcode(ret);
+ IMX_VPU_ERROR("flushing decoder failed: %s", imx_vpu_dec_error_string(imxret));
+ return imxret;
+ }
+ else
+ IMX_VPU_INFO("flushed decoder");
+ }
+
+ if (buf_ret_code & VPU_DEC_RESOLUTION_CHANGED)
+ {
+ IMX_VPU_INFO("resolution changed - resetting internal states");
+
+ *output_code |= IMX_VPU_DEC_OUTPUT_CODE_INITIAL_INFO_AVAILABLE;
+
+ decoder->delay_pending_user_data = TRUE;
+ decoder->recalculate_num_avail_framebuffers = FALSE;
+
+ decoder->num_user_data = 0;
+
+ if (decoder->user_data_for_frames != NULL)
+ IMX_VPU_FREE(decoder->user_data_for_frames, sizeof(void*) * decoder->num_framebuffers);
+ if (decoder->wrapper_framebuffers != NULL)
+ IMX_VPU_FREE(decoder->wrapper_framebuffers, sizeof(VpuFrameBuffer*) * decoder->num_framebuffers);
+
+ decoder->user_data_for_frames = NULL;
+ decoder->wrapper_framebuffers = NULL;
+ }
+
+ if (buf_ret_code & VPU_DEC_NO_ENOUGH_INBUF)
+ {
+ /* Not dropping frame here on purpose; the next input frame may
+ * complete the input */
+ }
+
+ {
+ void *user_data = decoder->delay_pending_user_data ? decoder->last_pending_user_data : decoder->pending_user_data;
+
+ /* The first time this location is reached, VPU_DEC_INIT_OK will be set in the output_code.
+ * This implies that the framebuffers have not been allocated and registered yet,
+ * so no user data can be stored yet.
+ * With codec formats that produce consumption info, this is not a problem, because
+ * VPU_DEC_ONE_FRM_CONSUMED will be returned only when framebuffers are present.
+ * But with other formats, an explicit decoder->framebuffers != NULL check is necessary
+ * (see below). The user_data pointer does not get lost; it is stored in last_pending_user_data. */
+ if ((buf_ret_code & VPU_DEC_ONE_FRM_CONSUMED) && !(buf_ret_code & VPU_DEC_OUTPUT_DROPPED))
+ {
+ int fb_index;
+
+ VpuDecFrameLengthInfo consumed_frame_info;
+ ret = VPU_DecGetConsumedFrameInfo(decoder->handle, &consumed_frame_info);
+ if (ret != VPU_DEC_RET_SUCCESS)
+ {
+ ImxVpuDecReturnCodes imxret = dec_convert_retcode(ret);
+ IMX_VPU_ERROR("getting consumed frame info failed: %s", imx_vpu_dec_error_string(imxret));
+ return imxret;
+ }
+
+ fb_index = dec_get_wrapper_framebuffer_index(decoder, consumed_frame_info.pFrame);
+
+ if (consumed_frame_info.pFrame != NULL)
+ {
+ if ((fb_index >= 0) && (fb_index < (int)(decoder->num_framebuffers)))
+ {
+ IMX_VPU_LOG("framebuffer index %d for framebuffer %p user data %p", fb_index, (void *)(consumed_frame_info.pFrame), user_data);
+ decoder->user_data_for_frames[fb_index] = user_data;
+ }
+ else
+ IMX_VPU_ERROR("framebuffer index %d for framebuffer %p user data %p out of bounds", fb_index, (void *)(consumed_frame_info.pFrame), user_data);
+ }
+ else
+ IMX_VPU_WARNING("consumed frame info contains a NULL frame");
+ }
+ else if (!(decoder->consumption_info_available) && (decoder->framebuffers != NULL))
+ {
+ if (decoder->num_user_data < (int)(decoder->num_framebuffers))
+ {
+ decoder->user_data_for_frames[decoder->num_user_data] = user_data;
+ decoder->num_user_data++;
+
+ IMX_VPU_LOG("user data %p stored as newest", user_data);
+
+ IMX_VPU_TRACE("incremented number of userdata pointers to %d", decoder->num_user_data);
+ }
+ else
+ IMX_VPU_WARNING("too many user data pointers in memory - cannot store current one");
+ }
+
+ decoder->last_pending_user_data = decoder->pending_user_data;
+ decoder->pending_user_data = NULL;
+ }
+
+ if ((buf_ret_code & VPU_DEC_ONE_FRM_CONSUMED) && !(buf_ret_code & VPU_DEC_OUTPUT_DROPPED))
+ {
+ decoder->num_available_framebuffers--;
+ decoder->num_times_counter_decremented++;
+ IMX_VPU_LOG("decremented number of available framebuffers to %d (with consumed frame info); number of times decremented is now %d", decoder->num_available_framebuffers, decoder->num_times_counter_decremented);
+ }
+
+ if (buf_ret_code & VPU_DEC_OUTPUT_NODIS)
+ {
+ if ((encoded_frame->virtual_address != NULL) && (decoder->codec_format == IMX_VPU_CODEC_FORMAT_VP8))
+ *output_code |= IMX_VPU_DEC_OUTPUT_CODE_DECODE_ONLY;
+ }
+
+ /* VPU_DEC_NO_ENOUGH_BUF handled by caller - should be treated as an error */
+
+ if ((buf_ret_code & VPU_DEC_OUTPUT_DIS) && !(decoder->consumption_info_available))
+ {
+ decoder->num_available_framebuffers--;
+ decoder->num_times_counter_decremented++;
+ IMX_VPU_LOG("decremented number of available framebuffers to %d (no consumed frame info); number of times decremented is now %d", decoder->num_available_framebuffers, decoder->num_times_counter_decremented);
+ }
+ else if (buf_ret_code & VPU_DEC_OUTPUT_MOSAIC_DIS)
+ {
+ IMX_VPU_TRACE("dropping mosaic frame");
+
+ /* mosaic frames do not seem to be useful for anything, so they are just dropped here */
+
+ ImxVpuDecReturnCodes imxret;
+ ImxVpuDecodedFrame decoded_frame;
+
+ if ((imxret = imx_vpu_dec_get_decoded_frame(decoder, &decoded_frame)) != IMX_VPU_DEC_RETURN_CODE_OK)
+ {
+ IMX_VPU_ERROR("error getting output mosaic frame: %s", imx_vpu_dec_error_string(imxret));
+ return imxret;
+ }
+
+ if ((imxret = imx_vpu_dec_mark_framebuffer_as_displayed(decoder, decoded_frame.framebuffer)) != IMX_VPU_DEC_RETURN_CODE_OK)
+ {
+ IMX_VPU_ERROR("error marking mosaic frame as displayed: %s", imx_vpu_dec_error_string(imxret));
+ return imxret;
+ }
+
+ decoder->dropped_frame_user_data = decoded_frame.user_data;
+
+ *output_code |= IMX_VPU_DEC_OUTPUT_CODE_DROPPED;
+ }
+ else if (buf_ret_code & VPU_DEC_OUTPUT_DROPPED)
+ {
+ // TODO make this work for formats with consumption info
+ if (decoder->num_user_data > 0)
+ {
+ decoder->dropped_frame_user_data = decoder->user_data_for_frames[0];
+ decoder->user_data_for_frames[0] = NULL;
+ memmove(decoder->user_data_for_frames, decoder->user_data_for_frames + 1, sizeof(void*) * (decoder->num_user_data - 1));
+ decoder->num_user_data--;
+ }
+ else
+ decoder->dropped_frame_user_data = NULL;
+ }
+
+ /* In case the VPU didn't use the input and no consumed frame info is available,
+ * drop the input frame to make sure timestamps are okay
+ * (If consumed frame info is present it is still possible it might be used for input-output frame
+ * associations; unlikely to occur thought) */
+ if ((encoded_frame->virtual_address != NULL) && !(buf_ret_code & (VPU_DEC_ONE_FRM_CONSUMED | VPU_DEC_INPUT_USED | VPU_DEC_RESOLUTION_CHANGED)))
+ {
+ decoder->dropped_frame_user_data = encoded_frame->user_data;
+ *output_code |= IMX_VPU_DEC_OUTPUT_CODE_DROPPED;
+ }
+
+ return IMX_VPU_DEC_RETURN_CODE_OK;
+}
+
+
+ImxVpuDecReturnCodes imx_vpu_dec_get_decoded_frame(ImxVpuDecoder *decoder, ImxVpuDecodedFrame *decoded_frame)
+{
+ VpuDecRetCode ret;
+ VpuDecOutFrameInfo out_frame_info;
+ int fb_index;
+ void *user_data;
+
+ ret = VPU_DecGetOutputFrame(decoder->handle, &out_frame_info);
+ if (ret != VPU_DEC_RET_SUCCESS)
+ {
+ ImxVpuDecReturnCodes imxret = dec_convert_retcode(ret);
+ IMX_VPU_ERROR("error getting decoded output frame: %s", imx_vpu_dec_error_string(imxret));
+ return imxret;
+ }
+
+ fb_index = dec_get_wrapper_framebuffer_index(decoder, out_frame_info.pDisplayFrameBuf);
+
+ user_data = NULL;
+ if (decoder->consumption_info_available)
+ {
+ if ((fb_index >= 0) && (fb_index < (int)(decoder->num_framebuffers)))
+ {
+ user_data = decoder->user_data_for_frames[fb_index];
+ IMX_VPU_LOG("framebuffer index %d for framebuffer %p and user data %p", fb_index, (void *)(out_frame_info.pDisplayFrameBuf), user_data);
+ decoder->user_data_for_frames[fb_index] = NULL;
+ }
+ else
+ IMX_VPU_ERROR("framebuffer index %d for framebuffer %p and user data %p out of bounds", fb_index, (void *)(out_frame_info.pDisplayFrameBuf), user_data);
+ }
+ else
+ {
+ if (decoder->num_user_data > 0)
+ {
+ user_data = decoder->user_data_for_frames[0];
+ decoder->user_data_for_frames[0] = NULL;
+ IMX_VPU_LOG("framebuffer index %d user data %p retrieved as oldest", fb_index, user_data);
+ memmove(decoder->user_data_for_frames, decoder->user_data_for_frames + 1, sizeof(void*) * (decoder->num_user_data - 1));
+ decoder->num_user_data--;
+ }
+ }
+
+ decoded_frame->pic_type = convert_from_wrapper_pic_type(out_frame_info.ePicType);
+ decoded_frame->user_data = user_data;
+
+ /* XXX
+ * This association assumes that the order of internal framebuffer entries
+ * inside the VPU wrapper is the same as the order of the framebuffers here.
+ * So, decoder->framebuffers[1] equals internal framebuffer entry with index 1 etc.
+ */
+ decoded_frame->framebuffer = &(decoder->framebuffers[fb_index]);
+ /* This is used in imx_vpu_dec_mark_framebuffer_as_displayed() to be able
+ * to mark the vpuwrapper framebuffer as displayed */
+ decoded_frame->framebuffer->internal = out_frame_info.pDisplayFrameBuf;
+
+ decoder->num_framebuffers_in_use++;
+
+ return IMX_VPU_DEC_RETURN_CODE_OK;
+}
+
+
+void* imx_vpu_dec_get_dropped_frame_user_data(ImxVpuDecoder *decoder)
+{
+ return decoder->dropped_frame_user_data;
+}
+
+
+int imx_vpu_dec_get_num_free_framebuffers(ImxVpuDecoder *decoder)
+{
+ return decoder->num_available_framebuffers;
+}
+
+
+int imx_vpu_dec_get_min_num_free_required(ImxVpuDecoder *decoder)
+{
+ IMXVPUCODEC_UNUSED_PARAM(decoder);
+ return MIN_NUM_FREE_FB_REQUIRED;
+}
+
+
+ImxVpuDecReturnCodes imx_vpu_dec_mark_framebuffer_as_displayed(ImxVpuDecoder *decoder, ImxVpuFramebuffer const *framebuffer)
+{
+ VpuDecRetCode ret;
+ VpuFrameBuffer *wrapper_fb = (VpuFrameBuffer *)(framebuffer->internal);
+
+ ret = VPU_DecOutFrameDisplayed(decoder->handle, wrapper_fb);
+ if (ret != VPU_DEC_RET_SUCCESS)
+ {
+ ImxVpuDecReturnCodes imxret = dec_convert_retcode(ret);
+ IMX_VPU_ERROR("error marking output frame as displayed: %s", imx_vpu_dec_error_string(imxret));
+ return imxret;
+ }
+
+ IMX_VPU_LOG("marked framebuffer %p with physical address 0x%x as displayed", (void *)framebuffer, framebuffer->physical_address);
+
+ if (decoder->num_times_counter_decremented > 0)
+ {
+ decoder->num_available_framebuffers++;
+ decoder->num_times_counter_decremented--;
+ decoder->num_framebuffers_in_use--;
+
+ IMX_VPU_LOG("num_available_framebuffers %d num_times_counter_decremented %d num_framebuffers_in_use %d", decoder->num_available_framebuffers, decoder->num_times_counter_decremented, decoder->num_framebuffers_in_use);
+ }
+
+ return IMX_VPU_DEC_RETURN_CODE_OK;
+}
+
diff --git a/src/media/gpu/imxvpucodec_platform.h b/src/media/gpu/imxvpucodec_platform.h
new file mode 100644
index 0000000..83fe05a
--- /dev/null
+++ b/src/media/gpu/imxvpucodec_platform.h
@@ -0,0 +1,35 @@
+/*
+ * imxvpucodec - i.MX6 VPU hardware codec engine API library
+ * Copyright (c) 2014 Carlos Rafael Giani
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any
+ * damages arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute
+ * it freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must
+ * not claim that you wrote the original software. If you use this
+ * software in a product, an acknowledgment in the product
+ * documentation would be appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must
+ * not be misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+
+#ifndef IMXVPUCODEC_PLATFORM_H
+#define IMXVPUCODEC_PLATFORM_H
+
+
+#define IMXVPUCODEC_UNUSED_PARAM(x) ((void)(x))
+
+
+#include "imxvpucodec_platform_chromium.h"
+
+
+#endif
diff --git a/src/media/gpu/imxvpucodec_platform_chromium.cc b/src/media/gpu/imxvpucodec_platform_chromium.cc
new file mode 100644
index 0000000..b5e861d
--- /dev/null
+++ b/src/media/gpu/imxvpucodec_platform_chromium.cc
@@ -0,0 +1,40 @@
+#include "imxvpucodec_platform_chromium.h"
+#include "base/logging.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void imx_vpu_log(ImxVpuLogLevel level, char const *file, int const line, char const *fn, const char * format, ...)
+{
+ va_list args;
+ char buf[500];
+
+ va_start(args, format);
+ vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+
+ #define DO_LOG(severity) do { LOG(severity) << file << ":" << line << " (" << fn << ") " << buf; } while(0)
+ #define DO_VLOG(severity) do { VLOG(severity) << file << ":" << line << " (" << fn << ") " << buf; } while(0)
+
+ switch (level)
+ {
+ case IMX_VPU_LOG_LEVEL_ERROR: DO_LOG(ERROR); break;
+ case IMX_VPU_LOG_LEVEL_WARNING: DO_LOG(WARNING); break;
+ case IMX_VPU_LOG_LEVEL_INFO: DO_LOG(INFO); break;
+ case IMX_VPU_LOG_LEVEL_DEBUG: DO_VLOG(0); break;
+ case IMX_VPU_LOG_LEVEL_LOG: DO_VLOG(1); break;
+ case IMX_VPU_LOG_LEVEL_TRACE: DO_VLOG(2); break;
+ default: break;
+ }
+}
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/media/gpu/imxvpucodec_platform_chromium.h b/src/media/gpu/imxvpucodec_platform_chromium.h
new file mode 100644
index 0000000..8803d3a
--- /dev/null
+++ b/src/media/gpu/imxvpucodec_platform_chromium.h
@@ -0,0 +1,71 @@
+/*
+ * imxvpucodec - i.MX6 VPU hardware codec engine API library
+ * Copyright (c) 2014 Carlos Rafael Giani
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any
+ * damages arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute
+ * it freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must
+ * not claim that you wrote the original software. If you use this
+ * software in a product, an acknowledgment in the product
+ * documentation would be appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must
+ * not be misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+
+#ifndef IMXVPUCODEC_PLATFORM_CHROMIUM_H
+#define IMXVPUCODEC_PLATFORM_CHROMIUM_H
+
+
+#include <stdlib.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define IMX_VPU_ALLOC(SIZE) malloc(SIZE)
+#define IMX_VPU_FREE(PTR, SIZE) free(PTR)
+
+
+#define IMX_VPU_ERROR(...) imx_vpu_log(IMX_VPU_LOG_LEVEL_ERROR, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
+#define IMX_VPU_WARNING(...) imx_vpu_log(IMX_VPU_LOG_LEVEL_WARNING, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
+#define IMX_VPU_INFO(...) imx_vpu_log(IMX_VPU_LOG_LEVEL_INFO, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
+#define IMX_VPU_DEBUG(...) imx_vpu_log(IMX_VPU_LOG_LEVEL_DEBUG, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
+#define IMX_VPU_LOG(...) imx_vpu_log(IMX_VPU_LOG_LEVEL_LOG, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
+#define IMX_VPU_TRACE(...) imx_vpu_log(IMX_VPU_LOG_LEVEL_TRACE, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
+
+
+typedef enum
+{
+ IMX_VPU_LOG_LEVEL_ERROR = 0,
+ IMX_VPU_LOG_LEVEL_WARNING,
+ IMX_VPU_LOG_LEVEL_INFO,
+ IMX_VPU_LOG_LEVEL_DEBUG,
+ IMX_VPU_LOG_LEVEL_LOG,
+ IMX_VPU_LOG_LEVEL_TRACE
+}
+ImxVpuLogLevel;
+
+
+void imx_vpu_log(ImxVpuLogLevel level, char const *file, int const line, char const *fn, const char * format, ...);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
+
--
1.9.1
More information about the meta-freescale
mailing list