Skip to content

Instantly share code, notes, and snippets.

@fredldotme
Created September 28, 2022 16:10
Show Gist options
  • Save fredldotme/4c594c4b1164e8f02cd55333930f1bf1 to your computer and use it in GitHub Desktop.
Save fredldotme/4c594c4b1164e8f02cd55333930f1bf1 to your computer and use it in GitHub Desktop.
QtWebEngine + OMX video decoding on libhybris
diff --git a/qtwebengine-chromium/chromium/content/gpu/BUILD.gn b/qtwebengine-chromium/chromium/content/gpu/BUILD.gn
index 872ddb841..2c2c1e8d2 100644
--- a/qtwebengine-chromium/chromium/content/gpu/BUILD.gn
+++ b/qtwebengine-chromium/chromium/content/gpu/BUILD.gn
@@ -92,7 +92,8 @@ target(link_target_type, "gpu_sources") {
"//ui/gl",
"//ui/gl/init",
"//ui/latency/ipc",
- ]
+ "//components/services/quarantine/public/mojom",
+ ]
if (is_android) {
deps += [
diff --git a/qtwebengine-chromium/chromium/media/gpu/BUILD.gn b/qtwebengine-chromium/chromium/media/gpu/BUILD.gn
index b1a84b1ad..52cf59d05 100644
--- a/qtwebengine-chromium/chromium/media/gpu/BUILD.gn
+++ b/qtwebengine-chromium/chromium/media/gpu/BUILD.gn
@@ -94,6 +94,17 @@ component("gpu") {
public_deps += [ "//media/gpu/mac" ]
}
+ if (is_linux) {
+ defines += [ "ENABLE_HYBRIS_MEDIA" ]
+ sources += [
+ "hybris/video_decoder_hybris.cc",
+ "hybris/video_decoder_hybris.h",
+ "hybris/media.c",
+ "//media/base/android/extract_sps_and_pps.cc",
+ "//media/base/android/extract_sps_and_pps.h",
+ ]
+ }
+
if (is_android) {
sources += [
"android/android_video_surface_chooser.cc",
diff --git a/qtwebengine-chromium/chromium/media/gpu/hybris/media.c b/qtwebengine-chromium/chromium/media/gpu/hybris/media.c
new file mode 100644
index 000000000..175833e8a
--- /dev/null
+++ b/qtwebengine-chromium/chromium/media/gpu/hybris/media.c
@@ -0,0 +1,443 @@
+/*
+ * Copyright (C) 2013-2014 Canonical Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
+ * Ricardo Salveti de Araujo <ricardo.salveti@canonical.com>
+ */
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <stddef.h>
+#include <stdbool.h>
+
+#include <hybris/common/binding.h>
+//#include <hybris/media/decoding_service.h>
+#include <hybris/media/media_compatibility_layer.h>
+#include <hybris/media/media_codec_layer.h>
+#include <hybris/media/media_codec_list.h>
+#include <hybris/media/media_format_layer.h>
+#include <hybris/media/media_recorder_layer.h>
+#include <hybris/media/surface_texture_client_hybris.h>
+#include <hybris/media/media_codec_source_layer.h>
+#include <hybris/media/media_buffer_layer.h>
+
+
+#define COMPAT_LIBRARY_PATH "libmedia_compat_layer.so"
+
+#ifdef __ARM_PCS_VFP
+#define FP_ATTRIB __attribute__((pcs("aapcs")))
+#else
+#define FP_ATTRIB
+#endif
+
+HYBRIS_LIBRARY_INITIALIZE(media, COMPAT_LIBRARY_PATH);
+
+int media_compat_check_availability()
+{
+ /* Both are defined via HYBRIS_LIBRARY_INITIALIZE */
+ hybris_media_initialize();
+ return media_handle ? 1 : 0;
+}
+
+unsigned int hybris_media_get_version()
+{
+ static unsigned int (*f)() FP_ATTRIB = NULL;
+ HYBRIS_DLSYSM(media, &f, "hybris_media_get_version");
+
+ /* When the method is not available we return zero here
+ * rather than crashing to indicate the client the
+ * Android side implementation is not versioned yet. */
+ if (!f)
+ return 0;
+
+ return f();
+}
+
+HYBRIS_IMPLEMENT_FUNCTION0(media, struct MediaPlayerWrapper*,
+ android_media_new_player);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, android_media_update_surface_texture,
+ struct MediaPlayerWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_media_play,
+ struct MediaPlayerWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_media_pause,
+ struct MediaPlayerWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_media_stop,
+ struct MediaPlayerWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, bool, android_media_is_playing,
+ struct MediaPlayerWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_seek_to,
+ struct MediaPlayerWrapper*, int);
+
+// Setters
+HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_set_data_source,
+ struct MediaPlayerWrapper*, const char*);
+HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_set_preview_texture,
+ struct MediaPlayerWrapper*, int);
+HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_set_volume,
+ struct MediaPlayerWrapper*, int);
+
+// Getters
+HYBRIS_IMPLEMENT_VOID_FUNCTION2(media, android_media_surface_texture_get_transformation_matrix,
+ struct MediaPlayerWrapper*, float*);
+HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_get_current_position,
+ struct MediaPlayerWrapper*, int*);
+HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_get_duration,
+ struct MediaPlayerWrapper*, int*);
+HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_media_get_volume,
+ struct MediaPlayerWrapper*, int*);
+
+// Callbacks
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_media_set_video_size_cb,
+ struct MediaPlayerWrapper*, on_msg_set_video_size, void*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_media_set_video_texture_needs_update_cb,
+ struct MediaPlayerWrapper*, on_video_texture_needs_update, void*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_media_set_error_cb,
+ struct MediaPlayerWrapper*, on_msg_error, void*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_media_set_playback_complete_cb,
+ struct MediaPlayerWrapper*, on_playback_complete, void*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_media_set_media_prepared_cb,
+ struct MediaPlayerWrapper*, on_media_prepared, void*);
+
+// DecodingService
+HYBRIS_IMPLEMENT_VOID_FUNCTION0(media, decoding_service_init);
+HYBRIS_IMPLEMENT_FUNCTION0(media, IGBCWrapperHybris,
+ decoding_service_get_igraphicbufferconsumer);
+HYBRIS_IMPLEMENT_FUNCTION0(media, IGraphicBufferProducerHybris,
+ decoding_service_get_igraphicbufferproducer);
+HYBRIS_IMPLEMENT_FUNCTION1(media, DSSessionWrapperHybris,
+ decoding_service_create_session, uint32_t);
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, decoding_service_set_client_death_cb,
+ DecodingClientDeathCbHybris, uint32_t, void*);
+
+// Media Codecs
+HYBRIS_IMPLEMENT_FUNCTION1(media, MediaCodecDelegate,
+ media_codec_create_by_codec_name, const char*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_codec_delegate_destroy,
+ MediaCodecDelegate);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_codec_delegate_ref,
+ MediaCodecDelegate);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_codec_delegate_unref,
+ MediaCodecDelegate);
+
+#ifdef SIMPLE_PLAYER
+HYBRIS_IMPLEMENT_FUNCTION4(media, int, media_codec_configure,
+ MediaCodecDelegate, MediaFormat, void*, uint32_t);
+#else
+HYBRIS_IMPLEMENT_FUNCTION4(media, int, media_codec_configure,
+ MediaCodecDelegate, MediaFormat, SurfaceTextureClientHybris, uint32_t);
+#endif
+HYBRIS_IMPLEMENT_FUNCTION2(media, int, media_codec_set_surface_texture_client,
+ MediaCodecDelegate, SurfaceTextureClientHybris);
+HYBRIS_IMPLEMENT_FUNCTION2(media, int, media_codec_queue_csd,
+ MediaCodecDelegate, MediaFormat);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int, media_codec_start,
+ MediaCodecDelegate);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int, media_codec_stop,
+ MediaCodecDelegate);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int, media_codec_release,
+ MediaCodecDelegate);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int, media_codec_flush,
+ MediaCodecDelegate);
+HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_codec_get_input_buffers_size,
+ MediaCodecDelegate);
+HYBRIS_IMPLEMENT_FUNCTION2(media, uint8_t*, media_codec_get_nth_input_buffer,
+ MediaCodecDelegate, size_t);
+HYBRIS_IMPLEMENT_FUNCTION2(media, size_t, media_codec_get_nth_input_buffer_capacity,
+ MediaCodecDelegate, size_t);
+HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_codec_get_output_buffers_size,
+ MediaCodecDelegate);
+HYBRIS_IMPLEMENT_FUNCTION2(media, uint8_t*, media_codec_get_nth_output_buffer,
+ MediaCodecDelegate, size_t);
+HYBRIS_IMPLEMENT_FUNCTION2(media, size_t, media_codec_get_nth_output_buffer_capacity,
+ MediaCodecDelegate, size_t);
+HYBRIS_IMPLEMENT_FUNCTION3(media, int, media_codec_dequeue_output_buffer,
+ MediaCodecDelegate, MediaCodecBufferInfo*, int64_t);
+HYBRIS_IMPLEMENT_FUNCTION2(media, int, media_codec_queue_input_buffer,
+ MediaCodecDelegate, const MediaCodecBufferInfo*);
+HYBRIS_IMPLEMENT_FUNCTION3(media, int, media_codec_dequeue_input_buffer,
+ MediaCodecDelegate, size_t*, int64_t);
+HYBRIS_IMPLEMENT_FUNCTION3(media, int, media_codec_release_output_buffer,
+ MediaCodecDelegate, size_t, uint8_t);
+HYBRIS_IMPLEMENT_FUNCTION1(media, MediaFormat, media_codec_get_output_format,
+ MediaCodecDelegate);
+
+HYBRIS_IMPLEMENT_FUNCTION3(media, ssize_t, media_codec_list_find_codec_by_type,
+ const char*, bool, size_t);
+HYBRIS_IMPLEMENT_FUNCTION1(media, ssize_t, media_codec_list_find_codec_by_name,
+ const char *);
+HYBRIS_IMPLEMENT_FUNCTION0(media, size_t, media_codec_list_count_codecs);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_codec_list_get_codec_info_at_id,
+ size_t);
+HYBRIS_IMPLEMENT_FUNCTION1(media, const char*, media_codec_list_get_codec_name,
+ size_t);
+HYBRIS_IMPLEMENT_FUNCTION1(media, bool, media_codec_list_is_encoder,
+ size_t);
+HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_codec_list_get_num_supported_types,
+ size_t);
+HYBRIS_IMPLEMENT_FUNCTION2(media, size_t, media_codec_list_get_nth_supported_type_len,
+ size_t, size_t);
+HYBRIS_IMPLEMENT_FUNCTION3(media, int, media_codec_list_get_nth_supported_type,
+ size_t, char *, size_t);
+HYBRIS_IMPLEMENT_FUNCTION2(media, size_t, media_codec_list_get_num_profile_levels,
+ size_t, const char*);
+HYBRIS_IMPLEMENT_FUNCTION2(media, size_t, media_codec_list_get_num_color_formats,
+ size_t, const char*);
+HYBRIS_IMPLEMENT_FUNCTION4(media, int, media_codec_list_get_nth_codec_profile_level,
+ size_t, const char*, profile_level*, size_t);
+HYBRIS_IMPLEMENT_FUNCTION3(media, int, media_codec_list_get_codec_color_formats,
+ size_t, const char*, uint32_t*);
+
+HYBRIS_IMPLEMENT_FUNCTION5(media, MediaFormat, media_format_create_video_format,
+ const char*, int32_t, int32_t, int64_t, int32_t);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_format_destroy,
+ MediaFormat);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_format_ref,
+ MediaFormat);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_format_unref,
+ MediaFormat);
+HYBRIS_IMPLEMENT_VOID_FUNCTION4(media, media_format_set_byte_buffer,
+ MediaFormat, const char*, uint8_t*, size_t);
+HYBRIS_IMPLEMENT_FUNCTION1(media, const char*, media_format_get_mime,
+ MediaFormat);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int64_t, media_format_get_duration_us,
+ MediaFormat);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_width,
+ MediaFormat);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_height,
+ MediaFormat);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_max_input_size,
+ MediaFormat);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_stride,
+ MediaFormat);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_slice_height,
+ MediaFormat);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_color_format,
+ MediaFormat);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_crop_left,
+ MediaFormat);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_crop_right,
+ MediaFormat);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_crop_top,
+ MediaFormat);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int32_t, media_format_get_crop_bottom,
+ MediaFormat);
+
+// SurfaceTextureClientHybris
+HYBRIS_IMPLEMENT_FUNCTION1(media, SurfaceTextureClientHybris,
+ surface_texture_client_create, EGLNativeWindowType);
+HYBRIS_IMPLEMENT_FUNCTION1(media, SurfaceTextureClientHybris,
+ surface_texture_client_create_by_id, unsigned int);
+HYBRIS_IMPLEMENT_FUNCTION1(media, SurfaceTextureClientHybris,
+ surface_texture_client_create_by_igbp, IGBPWrapperHybris);
+HYBRIS_IMPLEMENT_FUNCTION2(media, GLConsumerWrapperHybris,
+ gl_consumer_create_by_id_with_igbc, unsigned int, IGBCWrapperHybris);
+HYBRIS_IMPLEMENT_FUNCTION3(media, int,
+ gl_consumer_set_frame_available_cb, GLConsumerWrapperHybris, FrameAvailableCbHybris, void*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION2(media, gl_consumer_get_transformation_matrix,
+ GLConsumerWrapperHybris, GLfloat*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, gl_consumer_update_texture,
+ GLConsumerWrapperHybris);
+HYBRIS_IMPLEMENT_FUNCTION1(media, uint8_t,
+ surface_texture_client_is_ready_for_rendering, SurfaceTextureClientHybris);
+HYBRIS_IMPLEMENT_FUNCTION1(media, uint8_t,
+ surface_texture_client_hardware_rendering, SurfaceTextureClientHybris);
+HYBRIS_IMPLEMENT_VOID_FUNCTION2(media, surface_texture_client_set_hardware_rendering,
+ SurfaceTextureClientHybris, uint8_t);
+HYBRIS_IMPLEMENT_VOID_FUNCTION2(media, surface_texture_client_get_transformation_matrix,
+ SurfaceTextureClientHybris, GLfloat*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, surface_texture_client_update_texture,
+ SurfaceTextureClientHybris);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, surface_texture_client_destroy,
+ SurfaceTextureClientHybris);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, surface_texture_client_ref,
+ SurfaceTextureClientHybris);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, surface_texture_client_unref,
+ SurfaceTextureClientHybris);
+HYBRIS_IMPLEMENT_VOID_FUNCTION2(media, surface_texture_client_set_surface_texture,
+ SurfaceTextureClientHybris, EGLNativeWindowType);
+
+// Recorder Observer
+HYBRIS_IMPLEMENT_FUNCTION0(media, struct MediaRecorderObserver*,
+ android_media_recorder_observer_new);
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_media_recorder_observer_set_cb,
+ struct MediaRecorderObserver*, media_recording_started_cb, void*);
+
+// Recorder
+HYBRIS_IMPLEMENT_FUNCTION0(media, struct MediaRecorderWrapper*,
+ android_media_new_recorder);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_initCheck,
+ struct MediaRecorderWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setCamera,
+ struct MediaRecorderWrapper*, struct CameraControl*);
+HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setVideoSource,
+ struct MediaRecorderWrapper*, VideoSource);
+HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setAudioSource,
+ struct MediaRecorderWrapper*, AudioSource);
+HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setOutputFormat,
+ struct MediaRecorderWrapper*, OutputFormat);
+HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setVideoEncoder,
+ struct MediaRecorderWrapper*, VideoEncoder);
+HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setAudioEncoder,
+ struct MediaRecorderWrapper*, AudioEncoder);
+HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setOutputFile,
+ struct MediaRecorderWrapper*, int);
+HYBRIS_IMPLEMENT_FUNCTION3(media, int, android_recorder_setVideoSize,
+ struct MediaRecorderWrapper*, int, int);
+HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setVideoFrameRate,
+ struct MediaRecorderWrapper*, int);
+HYBRIS_IMPLEMENT_FUNCTION2(media, int, android_recorder_setParameters,
+ struct MediaRecorderWrapper*, const char*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_start,
+ struct MediaRecorderWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_stop,
+ struct MediaRecorderWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_prepare,
+ struct MediaRecorderWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_reset,
+ struct MediaRecorderWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_close,
+ struct MediaRecorderWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int, android_recorder_release,
+ struct MediaRecorderWrapper*);
+
+// Recorder Callbacks
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_recorder_set_error_cb,
+ struct MediaRecorderWrapper*, on_recorder_msg_error, void*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_recorder_set_audio_read_cb,
+ struct MediaRecorderWrapper*, on_recorder_read_audio, void*);
+
+// Media Message
+HYBRIS_IMPLEMENT_FUNCTION0(media, MediaMessageWrapper*, media_message_create);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_message_release, MediaMessageWrapper*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_message_clear, MediaMessageWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, const char*, media_message_dump, MediaMessageWrapper*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_message_set_int32, MediaMessageWrapper*,
+ const char*, int32_t);
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_message_set_int64, MediaMessageWrapper*,
+ const char*, int64_t);
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_message_set_size, MediaMessageWrapper*,
+ const char*, size_t);
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_message_set_float, MediaMessageWrapper*,
+ const char*, float);
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_message_set_double, MediaMessageWrapper*,
+ const char*, double);
+HYBRIS_IMPLEMENT_VOID_FUNCTION4(media, media_message_set_string, MediaMessageWrapper*,
+ const char*, const char*, ssize_t);
+HYBRIS_IMPLEMENT_FUNCTION2(media, bool, media_message_contains, MediaMessageWrapper*,
+ const char*);
+HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_message_find_int32, MediaMessageWrapper*,
+ const char*, int32_t*);
+HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_message_find_int64, MediaMessageWrapper*,
+ const char*, int64_t*);
+HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_message_find_size, MediaMessageWrapper*,
+ const char*, size_t*);
+HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_message_find_float, MediaMessageWrapper*,
+ const char*, float*);
+HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_message_find_double, MediaMessageWrapper*,
+ const char*, double*);
+
+// Media Meta Data
+HYBRIS_IMPLEMENT_FUNCTION1(media, uint32_t, media_meta_data_get_key_id, int);
+HYBRIS_IMPLEMENT_FUNCTION0(media, MediaMetaDataWrapper*, media_meta_data_create);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_meta_data_release, MediaMetaDataWrapper*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_meta_data_clear, MediaMetaDataWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION2(media, bool, media_meta_data_remove, MediaMetaDataWrapper*,
+ uint32_t);
+HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_set_cstring, MediaMetaDataWrapper*,
+ uint32_t, const char*);
+HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_set_int32, MediaMetaDataWrapper*,
+ uint32_t, int32_t);
+HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_set_int64, MediaMetaDataWrapper*,
+ uint32_t, int64_t);
+HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_set_float, MediaMetaDataWrapper*,
+ uint32_t, float);
+HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_set_pointer, MediaMetaDataWrapper*,
+ uint32_t, void*);
+HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_find_cstring, MediaMetaDataWrapper*,
+ uint32_t, const char**);
+HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_find_int32, MediaMetaDataWrapper*,
+ uint32_t, int32_t*);
+HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_find_int64, MediaMetaDataWrapper*,
+ uint32_t, int64_t*);
+HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_find_float, MediaMetaDataWrapper*,
+ uint32_t, float*);
+HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_find_pointer, MediaMetaDataWrapper*,
+ uint32_t, void**);
+
+// Media Buffer
+HYBRIS_IMPLEMENT_FUNCTION1(media, MediaBufferWrapper*, media_buffer_create, size_t);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_buffer_destroy, MediaBufferWrapper*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_buffer_release, MediaBufferWrapper*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_buffer_ref, MediaBufferWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, int, media_buffer_get_refcount, MediaBufferWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, void*, media_buffer_get_data, MediaBufferWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_buffer_get_size, MediaBufferWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_buffer_get_range_offset, MediaBufferWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_buffer_get_range_length, MediaBufferWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, MediaMetaDataWrapper*, media_buffer_get_meta_data, MediaBufferWrapper*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_buffer_set_return_callback, MediaBufferWrapper*,
+ MediaBufferReturnCallback, void*);
+
+// Media ABuffer
+HYBRIS_IMPLEMENT_FUNCTION1(media, MediaABufferWrapper*, media_abuffer_create,
+ size_t);
+HYBRIS_IMPLEMENT_FUNCTION2(media, MediaABufferWrapper*, media_abuffer_create_with_data,
+ uint8_t*, size_t);
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_abuffer_set_range,
+ MediaABufferWrapper*, size_t, size_t);
+HYBRIS_IMPLEMENT_VOID_FUNCTION2(media, media_abuffer_set_media_buffer_base,
+ MediaABufferWrapper*, MediaBufferWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, MediaBufferWrapper*, media_abuffer_get_media_buffer_base,
+ MediaABufferWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, void*, media_abuffer_get_data,
+ MediaABufferWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_abuffer_get_size,
+ MediaABufferWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_abuffer_get_range_offset,
+ MediaABufferWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_abuffer_get_capacity,
+ MediaABufferWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, MediaMessageWrapper*, media_abuffer_get_meta,
+ MediaABufferWrapper*);
+
+// Media Codec Source
+HYBRIS_IMPLEMENT_FUNCTION3(media, MediaCodecSourceWrapper*, media_codec_source_create,
+ MediaMessageWrapper*, MediaSourceWrapper*, int);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_codec_source_release, MediaCodecSourceWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, void*, media_codec_source_get_native_window_handle,
+ MediaCodecSourceWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, MediaMetaDataWrapper*, media_codec_source_get_format,
+ MediaCodecSourceWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, bool, media_codec_source_start, MediaCodecSourceWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, bool, media_codec_source_stop, MediaCodecSourceWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION1(media, bool, media_codec_source_pause, MediaCodecSourceWrapper*);
+HYBRIS_IMPLEMENT_FUNCTION2(media, bool, media_codec_source_read, MediaCodecSourceWrapper*,
+ MediaBufferWrapper**);
+HYBRIS_IMPLEMENT_FUNCTION1(media, bool, media_codec_source_request_idr_frame,
+ MediaCodecSourceWrapper*);
+
+// Media Source
+HYBRIS_IMPLEMENT_FUNCTION0(media, MediaSourceWrapper*, media_source_create);
+HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_source_release, MediaSourceWrapper*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION2(media, media_source_set_format, MediaSourceWrapper*,
+ MediaMetaDataWrapper*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_source_set_start_callback,
+ MediaSourceWrapper*, MediaSourceStartCallback, void*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_source_set_stop_callback,
+ MediaSourceWrapper*, MediaSourceStopCallback, void*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_source_set_read_callback,
+ MediaSourceWrapper*, MediaSourceReadCallback, void*);
+HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_source_set_pause_callback,
+ MediaSourceWrapper*, MediaSourcePauseCallback, void*);
diff --git a/qtwebengine-chromium/chromium/media/gpu/hybris/video_decoder_hybris.cc b/qtwebengine-chromium/chromium/media/gpu/hybris/video_decoder_hybris.cc
new file mode 100644
index 000000000..3739bba38
--- /dev/null
+++ b/qtwebengine-chromium/chromium/media/gpu/hybris/video_decoder_hybris.cc
@@ -0,0 +1,780 @@
+// Copyright 2022 Alfred Neumayer. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/gpu/hybris/video_decoder_hybris.h"
+#include "media/formats/mp4/box_definitions.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
+#include "gpu/ipc/service/command_buffer_stub.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface.h"
+#include "ui/gl/scoped_binders.h"
+#include "ui/gl/init/gl_factory.h"
+
+#define BUFFER_FLAG_KEY_FRAME 1
+#define BUFFER_FLAG_CODEC_CONFIG 2
+#define BUFFER_FLAG_END_OF_STREAM 4
+#define INFO_TRY_AGAIN_LATER -1
+#define INFO_OUTPUT_FORMAT_CHANGED -2
+#define INFO_OUTPUT_BUFFERS_CHANGED -4
+
+extern "C" {
+int media_compat_check_availability();
+}
+
+namespace media {
+
+static const char* kVideoMimeTypeH264 = "video/avc";
+static const char* kVideoMimeTypeVP8 = "video/x-vnd.on2.vp8";
+static const char* kVideoMimeTypeVP9 = "video/x-vnd.on2.vp9";
+
+std::vector<SupportedVideoDecoderConfig> HybrisMediaCodecVideoDecoder::GetSupportedConfigs() {
+ static const auto configs = GetSupportedConfigsInternal();
+ return configs;
+}
+
+std::vector<SupportedVideoDecoderConfig> HybrisMediaCodecVideoDecoder::GetSupportedConfigsInternal() {
+ std::vector<SupportedVideoDecoderConfig> supported_configs;
+
+ if (IsSupported(VP8PROFILE_MIN)) {
+ supported_configs.emplace_back(VP8PROFILE_ANY, VP8PROFILE_ANY,
+ gfx::Size(480, 360), gfx::Size(3840, 2160),
+ false, // allow_encrypted
+ false); // require_encrypted
+ // Encrypted content must be decoded by MediaCodec.
+ supported_configs.emplace_back(VP8PROFILE_ANY, VP8PROFILE_ANY,
+ gfx::Size(0, 0), gfx::Size(3840, 2160),
+ true, // allow_encrypted
+ true); // require_encrypted
+ }
+
+ if (IsSupported(VP9PROFILE_MIN)) {
+ std::vector<CodecProfileLevel> profiles;
+
+ profiles.push_back({kCodecVP9, VP9PROFILE_PROFILE0, 0});
+
+ for (const auto& p : profiles) {
+ if (p.codec != kCodecVP9)
+ continue;
+
+ // We don't compile support into libvpx for these profiles, so allow them
+ // for all resolutions. See notes on H264 profiles below for more detail.
+ if (p.profile > VP9PROFILE_PROFILE1) {
+ supported_configs.emplace_back(p.profile, p.profile, gfx::Size(0, 0),
+ gfx::Size(3840, 2160),
+ true, // allow_encrypted
+ false); // require_encrypted
+ supported_configs.emplace_back(p.profile, p.profile, gfx::Size(0, 0),
+ gfx::Size(2160, 3840),
+ true, // allow_encrypted
+ false); // require_encrypted
+ continue;
+ }
+
+ // Encrypted content must be decoded by MediaCodec.
+ supported_configs.emplace_back(p.profile, p.profile, gfx::Size(0, 0),
+ gfx::Size(3840, 2160),
+ true, // allow_encrypted
+ true); // require_encrypted
+ supported_configs.emplace_back(p.profile, p.profile, gfx::Size(0, 0),
+ gfx::Size(2160, 3840),
+ true, // allow_encrypted
+ true); // require_encrypted
+ }
+ }
+
+ supported_configs.emplace_back(H264PROFILE_MIN, H264PROFILE_MAX,
+ gfx::Size(0, 0), gfx::Size(3840, 2160),
+ true, // allow_encrypted
+ false); // require_encrypted
+ supported_configs.emplace_back(H264PROFILE_MIN, H264PROFILE_MAX,
+ gfx::Size(0, 0), gfx::Size(2160, 3840),
+ true, // allow_encrypted
+ false); // require_encrypted
+
+//#if BUILDFLAG(ENABLE_PLATFORM_HEVC)
+#if 0
+ supported_configs.emplace_back(HEVCPROFILE_MIN, HEVCPROFILE_MAX,
+ gfx::Size(0, 0), gfx::Size(3840, 2160),
+ true, // allow_encrypted
+ false); // require_encrypted
+#endif
+
+ return supported_configs;
+}
+
+ HybrisMediaCodecVideoDecoder::HybrisMediaCodecVideoDecoder(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
+ GetStubCB stub_cb) :
+ running_(false),
+ n_buffers_in_(0),
+ n_buffers_out_(0),
+ queue_timeout_(10000),
+ is_draining_(false),
+ is_flushing_(false),
+ media_codec_(nullptr),
+ media_format_(nullptr),
+ stc_(nullptr),
+ igbp_(nullptr),
+ igbc_(nullptr),
+ gl_texture(nullptr),
+ pending_input_runner_(base::ThreadPool::CreateSingleThreadTaskRunner(
+ {base::WithBaseSyncPrimitives(), base::TaskPriority::USER_VISIBLE},
+ base::SingleThreadTaskRunnerThreadMode::DEDICATED)),
+ pending_output_runner_(base::ThreadPool::CreateSingleThreadTaskRunner(
+ {base::WithBaseSyncPrimitives(), base::TaskPriority::USER_VISIBLE},
+ base::SingleThreadTaskRunnerThreadMode::DEDICATED)),
+ task_runner_(task_runner),
+ gpu_task_runner_(gpu_task_runner) {
+ gpu::CommandBufferStub* stub = std::move(stub_cb).Run();
+ decoder_context_ = stub->decoder_context();
+ decoder_helper_ = GLES2DecoderHelper::Create(decoder_context_);
+ }
+
+ HybrisMediaCodecVideoDecoder::~HybrisMediaCodecVideoDecoder() {
+ Destroy();
+ }
+
+ bool HybrisMediaCodecVideoDecoder::IsSupportedProfile(VideoCodecProfile type)
+ {
+ if (!((type >= H264PROFILE_MIN && type <= H264PROFILE_MAX) ||
+ (type >= VP8PROFILE_MIN && type <= VP8PROFILE_MAX) ||
+ (type >= VP9PROFILE_MIN && type <= VP9PROFILE_MAX))) {
+ return false;
+ }
+ return true;
+ }
+
+ bool HybrisMediaCodecVideoDecoder::IsSupported(VideoCodecProfile type)
+ {
+ if (!IsSupportedProfile(type)) {
+ return false;
+ }
+
+ const char* hybris_codec_type = MimeTypeForCodecType(type);
+ if (!hybris_codec_type) {
+ return false;
+ }
+
+ std::string codec_type = std::string(hybris_codec_type);
+ std::string hybris_codec_name = FindSuitableCodec(codec_type, true);
+ if (hybris_codec_name.length() == 0) {
+ hybris_codec_name = FindSuitableCodec(codec_type, false);
+ }
+ return (hybris_codec_name.length() > 0);
+ }
+
+ const char* HybrisMediaCodecVideoDecoder::MimeTypeForCodecType(VideoCodecProfile type) {
+ if (type >= H264PROFILE_MIN && type <= H264PROFILE_MAX) {
+ return kVideoMimeTypeH264;
+ } else if (type >= VP8PROFILE_MIN && type <= VP8PROFILE_MAX) {
+ return kVideoMimeTypeVP8;
+ } else if (type >= VP9PROFILE_MIN && type <= VP9PROFILE_MAX) {
+ return kVideoMimeTypeVP9;
+ }
+ return nullptr;
+ }
+
+ std::string HybrisMediaCodecVideoDecoder::FindSuitableCodec(const std::string& codec_type, const bool hwCodecOnly) {
+ std::string hybris_codec_name;
+
+ // Find a decoder corresponding to our requested type
+ const size_t media_codec_num = media_codec_list_count_codecs();
+ for (size_t media_codec_pos = 0; media_codec_pos < media_codec_num; media_codec_pos++) {
+ media_codec_list_get_codec_info_at_id(media_codec_pos);
+
+ if (media_codec_list_is_encoder(media_codec_pos))
+ continue;
+
+ const char* codec_name_ptr = media_codec_list_get_codec_name(media_codec_pos);
+ if (!codec_name_ptr)
+ continue;
+
+ std::string codec_name(codec_name_ptr);
+
+ if (hwCodecOnly) {
+ if (codec_name.rfind("OMX.google.", 0) == 0)
+ continue;
+ }
+
+ LOG(INFO) << "Inspecting codec: " << codec_name;
+
+ const size_t num_supported_types = media_codec_list_get_num_supported_types(media_codec_pos);
+ for (size_t supported_type_pos = 0; supported_type_pos < num_supported_types; supported_type_pos++) {
+ const size_t mime_len = media_codec_list_get_nth_supported_type_len(media_codec_pos, supported_type_pos);
+ if (mime_len == 0)
+ continue;
+
+ char* potential_mime = new char[mime_len + 1]();
+ media_codec_list_get_nth_supported_type(media_codec_pos, potential_mime, supported_type_pos);
+ if (!potential_mime)
+ continue;
+
+ potential_mime[mime_len] = '\0';
+ std::string potential_type(potential_mime);
+ LOG(ERROR) << "Type: " << potential_type;
+
+ if (potential_type == codec_type) {
+ LOG(INFO) << "Found codec for type " << potential_type << ", called " << codec_name;
+ hybris_codec_name = codec_name;
+ delete[] potential_mime;
+ break;
+ }
+
+ delete[] potential_mime;
+ }
+
+ if (hybris_codec_name.length() > 0)
+ break;
+ }
+
+ return hybris_codec_name;
+ }
+
+void HybrisMediaCodecVideoDecoder::Initialize(
+ const VideoDecoderConfig& config,
+ bool low_delay,
+ CdmContext* cdm_context,
+ InitCB init_cb,
+ const OutputCB& output_cb,
+ const WaitingCB& waiting_cb) {
+ if (!IsSupportedProfile(config.profile())) {
+ return;
+ }
+
+ // Initialize hybris compat layer
+ const char* hybris_codec_type = MimeTypeForCodecType(config.profile());
+ if (!hybris_codec_type) {
+ return;
+ }
+
+ codec_type_ = std::string(hybris_codec_type);
+
+ // Look for hardware-codecs first
+ std::string hybris_codec_name = FindSuitableCodec(codec_type_, true);
+ if (hybris_codec_name.length() == 0) {
+ hybris_codec_name = FindSuitableCodec(codec_type_, false);
+ }
+
+ if (hybris_codec_name.length() == 0) {
+ return;
+ }
+
+ media_codec_ = media_codec_create_by_codec_name(hybris_codec_name.c_str());
+ if (!media_codec_) {
+ return;
+ }
+
+ output_cb_ = output_cb;
+ config_ = config;
+
+ gpu_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&HybrisMediaCodecVideoDecoder::Reconfigure,
+ base::Unretained(this), config, std::move(init_cb)));
+}
+
+void HybrisMediaCodecVideoDecoder::Drain() {
+ std::unique_lock<decltype(drain_mutex_)> lk(drain_mutex_);
+ is_draining_ = true;
+ QueuedBuffer eos_buffer { DecoderBuffer::CreateEOSBuffer(), base::DoNothing() };
+ ProcessInput(eos_buffer);
+ drain_condition_.wait(lk, [this]{ return !is_draining_; });
+ LOG(INFO) << "Queue drained";
+}
+
+void HybrisMediaCodecVideoDecoder::Flush() {
+ std::unique_lock<decltype(drain_mutex_)> lk(flush_mutex_);
+ is_flushing_ = true;
+ media_codec_flush(media_codec_);
+ is_flushing_ = false;
+ flush_condition_.notify_all();
+ LOG(INFO) << "Queue flushed";
+}
+
+void HybrisMediaCodecVideoDecoder::EnqueueOrderedInput(
+ scoped_refptr<DecoderBuffer> buffer,
+ DecodeCB decode_cb) {
+ LOG(INFO) << __func__;
+ while (!pending_inputs_.empty()) {
+ QueuedBuffer dequeued_buffer = std::move(pending_inputs_.front());
+ pending_inputs_.pop_front();
+ if (!ProcessInput(dequeued_buffer)) {
+ pending_inputs_.push_front(std::move(dequeued_buffer));
+ break;
+ }
+ }
+
+ QueuedBuffer next_input { buffer, std::move(decode_cb) };
+ if (pending_inputs_.empty()) {
+ if (!ProcessInput(next_input)) {
+ pending_inputs_.push_back(std::move(next_input));
+ }
+ } else {
+ pending_inputs_.push_back(std::move(next_input));
+ }
+}
+
+bool HybrisMediaCodecVideoDecoder::ProcessInput(
+ QueuedBuffer& in_flight_buffer) {
+ LOG(INFO) << __func__;
+
+ int32_t flags_for_input = 0;
+ if (in_flight_buffer.buffer->is_key_frame()) {
+ flags_for_input |= BUFFER_FLAG_KEY_FRAME;
+ }
+ if (in_flight_buffer.buffer->end_of_stream()) {
+ flags_for_input |= BUFFER_FLAG_END_OF_STREAM;
+ }
+
+ size_t offset = SkipForbiddenNALUs(in_flight_buffer.buffer->data(),
+ in_flight_buffer.buffer->data_size());
+ if (offset > 0) {
+ flags_for_input |= BUFFER_FLAG_CODEC_CONFIG;
+ }
+
+ size_t buf_index;
+ uint8_t* input_ptr = nullptr;
+ int ret;
+ int dequeue_attempts = 25;
+
+ while (!input_ptr && dequeue_attempts-- > 0) {
+ ret = media_codec_dequeue_input_buffer(media_codec_, &buf_index, queue_timeout_);
+ if (ret >= 0) {
+ input_ptr = codec_input_buffers_[buf_index].data;
+ }
+ }
+
+ if (!input_ptr) {
+ LOG(ERROR) << "Error in " << __func__ << ":" << __LINE__;
+ return false;
+ }
+
+ // Fill the input buffer
+ const size_t capacity = codec_input_buffers_[buf_index].size;
+ const size_t mem_size = std::min<size_t>(in_flight_buffer.buffer->data_size(), capacity);
+ LOG(INFO) << "Capacity " << capacity << " vs mem_size " << mem_size;
+ if (mem_size > 0) {
+ memcpy(input_ptr, in_flight_buffer.buffer->data(), mem_size);
+ }
+
+ const int64_t presentation_time =
+ in_flight_buffer.buffer->timestamp().InMicroseconds();
+ const int64_t presentation_duration =
+ in_flight_buffer.buffer->duration().InMicroseconds();
+
+ // Queue it into the decoder
+ MediaCodecBufferInfo buffer_info;
+ memset(&buffer_info, 0, sizeof(buffer_info));
+ buffer_info.index = buf_index;
+ buffer_info.size = mem_size;
+ buffer_info.flags = flags_for_input;
+ buffer_info.presentation_time_us = std::max<size_t>(1, presentation_time + presentation_duration);
+ buffer_info.offset = 0;
+ ret = media_codec_queue_input_buffer(media_codec_, &buffer_info);
+
+ if (ret < 0) {
+ LOG(ERROR) << "Error in " << __func__ << ":" << __LINE__;
+ return false;
+ }
+
+ pending_outputs_.push_back(std::move(in_flight_buffer));
+ return true;
+}
+
+void HybrisMediaCodecVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb) {
+ LOG(INFO) << __func__;
+
+ if (!buffer) {
+ return;
+ }
+
+ if (buffer->end_of_stream()) {
+ std::lock_guard<decltype(running_mutex_)> lk(running_mutex_);
+ running_ = false;
+ eos_decode_cb_ = std::move(decode_cb);
+ return;
+ }
+
+ pending_input_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&HybrisMediaCodecVideoDecoder::EnqueueOrderedInput,
+ base::Unretained(this), buffer, std::move(decode_cb)));
+}
+
+void HybrisMediaCodecVideoDecoder::OnFrameAvailable(GLConsumerWrapperHybris, void* data) {
+ LOG(INFO) << "OnFrameAvailable";
+ HybrisMediaCodecVideoDecoder* thiz = static_cast<HybrisMediaCodecVideoDecoder*>(data);
+ if (!thiz) {
+ return;
+ }
+ thiz->FrameAvailable();
+}
+
+void HybrisMediaCodecVideoDecoder::FrameAvailable() {
+ gpu_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&HybrisMediaCodecVideoDecoder::RedrawTexture, base::Unretained(this)));
+}
+
+void HybrisMediaCodecVideoDecoder::RedrawTexture() {
+ while (!pending_redraws_.empty()) {
+ LOG(ERROR) << "1";
+ std::lock_guard<decltype(redraw_mutex_)> lk(redraw_mutex_);
+ QueuedDrawOperation& draw_operation = pending_redraws_.front();
+
+ LOG(ERROR) << "2";
+ decoder_context_->MakeCurrent();
+ gl_consumer_update_texture(gl_texture_consumer_);
+
+ LOG(ERROR) << "3";
+ base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds(draw_operation.timestamp);
+ VideoPixelFormat pixel_format = PIXEL_FORMAT_ABGR;
+
+ LOG(ERROR) << "4";
+ gpu::Mailbox mailbox = decoder_helper_->CreateMailbox(gl_texture.get());
+ gpu::SyncToken sync_token = gpu::SyncToken();
+ gpu::MailboxHolder mailbox_holders_[VideoFrame::kMaxPlanes];
+ mailbox_holders_[0] = gpu::MailboxHolder(mailbox, sync_token, GL_TEXTURE_EXTERNAL_OES);
+
+ LOG(ERROR) << "5";
+ auto frame = VideoFrame::WrapNativeTextures(
+ pixel_format, mailbox_holders_, VideoFrame::ReleaseMailboxCB(),
+ coded_size_, visible_rect_, natural_size_, timestamp);
+
+ LOG(ERROR) << "6";
+ std::move(draw_operation.decode_cb).Run(DecodeStatus::OK);
+ pending_redraws_.pop_front();
+
+ if (!frame) {
+ return;
+ }
+
+ LOG(ERROR) << "7";
+ frame->metadata()->power_efficient = true;
+ output_cb_.Run(frame);
+
+ // We can safely reduce the timeout for de-/queueing now
+ //queue_timeout_ = 10000;
+ }
+}
+
+ void HybrisMediaCodecVideoDecoder::Destroy() {
+ if (media_codec_) {
+ running_ = false;
+ media_codec_flush(media_codec_);
+ media_codec_stop(media_codec_);
+ media_codec_delegate_destroy(media_codec_);
+ media_codec_ = nullptr;
+ }
+ /*if (media_format_) {
+ media_format_destroy(media_format_);
+ media_format_ = nullptr;
+ }
+ if (stc_) {
+ surface_texture_client_destroy(stc_);
+ stc_ = nullptr;
+ }*/
+ }
+
+ void HybrisMediaCodecVideoDecoder::Reset(base::OnceClosure closure) {
+ std::lock_guard<decltype(running_mutex_)> lk(running_mutex_);
+ running_ = false;
+ media_codec_flush(media_codec_);
+ media_codec_stop(media_codec_);
+ std::move(closure).Run();
+ }
+
+ bool HybrisMediaCodecVideoDecoder::NeedsBitstreamConversion() const {
+ return false;
+ }
+
+ bool HybrisMediaCodecVideoDecoder::CanReadWithoutStalling() const {
+ return false;
+ }
+
+ int HybrisMediaCodecVideoDecoder::GetMaxDecodeRequests() const {
+ return n_buffers_in_;
+ }
+
+ std::string HybrisMediaCodecVideoDecoder::GetDisplayName() const {
+ return "HybrisMediaCodecVideoDecoder";
+ }
+
+ void HybrisMediaCodecVideoDecoder::Reconfigure(const VideoDecoderConfig config, InitCB init_cb) {
+ LOG(INFO) << "Configuring decoder: " << config.AsHumanReadableString();
+
+ const int32_t width = config.coded_size().width();
+ const int32_t height = config.coded_size().height();
+ const int32_t buf_size = width * height;
+
+ decoder_context_->MakeCurrent();
+ gl_texture = decoder_helper_->CreateTexture(GL_TEXTURE_EXTERNAL_OES, GL_RGBA, width, height, GL_RGBA, GL_UNSIGNED_BYTE);
+
+ igbp_ = decoding_service_get_igraphicbufferproducer();
+ if (!igbp_) {
+ std::move(init_cb).Run(StatusCode::kDecoderInitializationFailed);
+ return;
+ }
+
+ igbc_ = decoding_service_get_igraphicbufferconsumer();
+ if (!igbc_) {
+ std::move(init_cb).Run(StatusCode::kDecoderInitializationFailed);
+ return;
+ }
+
+ gl_texture_consumer_ = gl_consumer_create_by_id_with_igbc(gl_texture->service_id(), igbc_);
+ if (!gl_texture_consumer_) {
+ std::move(init_cb).Run(StatusCode::kDecoderInitializationFailed);
+ return;
+ }
+
+/*
+ gl_consumer_set_frame_available_cb(gl_texture_consumer_,
+ HybrisMediaCodecVideoDecoder::OnFrameAvailable,
+ this);
+*/
+
+ stc_ = surface_texture_client_create_by_igbp(igbp_);
+ if (!stc_) {
+ std::move(init_cb).Run(StatusCode::kDecoderInitializationFailed);
+ return;
+ }
+
+ surface_texture_client_set_hardware_rendering(stc_, true);
+ media_format_ = media_format_create_video_format(codec_type_.c_str(), width, height, 0, buf_size);
+
+ if (config.codec() == kCodecH264) {
+ ExtractSpsAndPps(config.extra_data(), &csd0_, &csd1_);
+ media_format_set_byte_buffer(media_format_, "csd-0", csd0_.data(), csd0_.size());
+ media_format_set_byte_buffer(media_format_, "csd-1", csd1_.data(), csd1_.size());
+ }
+
+ int ret = media_codec_configure(media_codec_, media_format_, stc_, 0);
+ media_format_destroy(media_format_);
+ media_format_ = nullptr;
+
+ if (ret > 0) {
+ LOG(ERROR) << "Error in " << __func__ << ":" << __LINE__;
+ std::move(init_cb).Run(StatusCode::kDecoderInitializationFailed);
+ return;
+ }
+
+ // RecreateGeometry();
+
+ if (!running_) {
+ ret = media_codec_start(media_codec_);
+ if (ret < 0) {
+ LOG(ERROR) << "Error in " << __func__ << ":" << __LINE__;
+ std::move(init_cb).Run(StatusCode::kDecoderInitializationFailed);
+ return;
+ }
+ }
+
+ running_ = true;
+ pending_output_runner_->PostTask(FROM_HERE,
+ base::Bind(&HybrisMediaCodecVideoDecoder::RunPipeline,
+ base::Unretained(this)));
+
+ //LOG(INFO) << "Queue CSD: " << media_codec_queue_csd(media_codec_, media_format_);
+
+/*
+ Drain();
+ Flush();
+
+ {
+ std::unique_lock<decltype(flush_mutex_)> lk(flush_mutex_);
+ flush_condition_.wait(lk, [this]{ return !is_flushing_; });
+ }
+*/
+
+ if (!RecreateInputBuffers()) {
+ media_codec_stop(media_codec_);
+ std::move(init_cb).Run(StatusCode::kDecoderInitializationFailed);
+ return;
+ }
+
+ if (!RecreateOutputBuffers()) {
+ media_codec_stop(media_codec_);
+ std::move(init_cb).Run(StatusCode::kDecoderInitializationFailed);
+ return;
+ }
+
+ std::move(init_cb).Run(OkStatus());
+ LOG(INFO) << "Codec configured";
+ return;
+ }
+
+void HybrisMediaCodecVideoDecoder::ExtractSpsAndPps(
+ const std::vector<uint8_t>& avcc,
+ std::vector<uint8_t>* sps_out,
+ std::vector<uint8_t>* pps_out) {
+ if (avcc.empty())
+ return;
+
+ mp4::AVCDecoderConfigurationRecord record;
+ if (!record.Parse(avcc.data(), avcc.size())) {
+ DVLOG(1) << "Failed to extract SPS and PPS";
+ return;
+ }
+
+ constexpr std::array<uint8_t, 4> prefix = {{0, 0, 0, 1}};
+ for (const std::vector<uint8_t>& sps : record.sps_list) {
+ sps_out->insert(sps_out->end(), prefix.begin(), prefix.end());
+ sps_out->insert(sps_out->end(), sps.begin(), sps.end());
+ }
+
+ for (const std::vector<uint8_t>& pps : record.pps_list) {
+ pps_out->insert(pps_out->end(), prefix.begin(), prefix.end());
+ pps_out->insert(pps_out->end(), pps.begin(), pps.end());
+ }
+}
+
+void HybrisMediaCodecVideoDecoder::RunPipeline() {
+ int ret = 0;
+
+ while (running_) {
+ std::lock_guard<decltype(running_mutex_)> lk(running_mutex_);
+
+ // Get the decoded frame
+ MediaCodecBufferInfo buffer_info_out;
+ memset(&buffer_info_out, 0, sizeof(buffer_info_out));
+
+ ret = media_codec_dequeue_output_buffer(media_codec_, &buffer_info_out, queue_timeout_);
+ LOG(INFO) << "buffer_into_out.flags: " << buffer_info_out.flags << ", ret: " << ret;
+ const bool is_eos = (buffer_info_out.flags & BUFFER_FLAG_END_OF_STREAM);
+
+ if (is_eos) {
+ bool notify = false;
+ {
+ std::lock_guard<decltype(drain_mutex_)> lk(drain_mutex_);
+ if (is_draining_) {
+ is_draining_ = false;
+ notify = true;
+ }
+ }
+ if (notify) {
+ drain_condition_.notify_all();
+ }
+ }
+
+ if (ret == INFO_TRY_AGAIN_LATER) {
+ continue;
+ } else if (ret == INFO_OUTPUT_BUFFERS_CHANGED + 1) {
+ RecreateOutputBuffers();
+ continue;
+ } else if (ret == INFO_OUTPUT_FORMAT_CHANGED) {
+ RecreateGeometry();
+ continue;
+ } else {
+ QueuedBuffer& pending_output = pending_outputs_.front();
+
+ std::lock_guard<decltype(redraw_mutex_)> lk(redraw_mutex_);
+ pending_redraws_.push_back({ buffer_info_out.presentation_time_us, std::move(pending_output.decode_cb) });
+ ret = media_codec_release_output_buffer(media_codec_, buffer_info_out.index, !is_eos);
+ if (ret < 0) {
+ LOG(ERROR) << "Error in " << __func__ << ":" << __LINE__;
+ std::move(pending_redraws_.back().decode_cb).Run(DecodeStatus::DECODE_ERROR);
+ pending_redraws_.pop_back();
+ } else {
+ FrameAvailable();
+ }
+
+ pending_outputs_.pop_front();
+ }
+ }
+
+ if (eos_decode_cb_) {
+ std::lock_guard<decltype(running_mutex_)> lk(running_mutex_);
+ std::move(eos_decode_cb_).Run(DecodeStatus::OK);
+ }
+}
+
+bool HybrisMediaCodecVideoDecoder::RecreateInputBuffers() {
+ codec_input_buffers_.clear();
+ n_buffers_in_ = media_codec_get_input_buffers_size(media_codec_);
+ if (n_buffers_in_ <= 0) {
+ return false;
+ }
+
+ for (size_t i = 0; i < n_buffers_in_; i++) {
+ MediaCodecBuffer media_codec_buffer;
+ media_codec_buffer.data = media_codec_get_nth_input_buffer(media_codec_, i);
+ media_codec_buffer.size = media_codec_get_nth_input_buffer_capacity(media_codec_, i);
+ codec_input_buffers_.push_back(media_codec_buffer);
+ }
+
+ return true;
+}
+
+bool HybrisMediaCodecVideoDecoder::RecreateOutputBuffers() {
+ n_buffers_out_ = media_codec_get_output_buffers_size(media_codec_);
+ if (n_buffers_out_ <= 0) {
+ return false;
+ }
+ for (size_t i = 0; i < n_buffers_out_; i++) {
+ media_codec_get_nth_output_buffer(media_codec_, i);
+ media_codec_get_nth_output_buffer_capacity(media_codec_, i);
+ }
+ return true;
+}
+
+void HybrisMediaCodecVideoDecoder::RecreateGeometry()
+{
+ MediaFormat output_format = media_codec_get_output_format(media_codec_);
+
+ const int width = media_format_get_width(output_format);
+ const int height = media_format_get_height(output_format);
+ const int crop_left = media_format_get_crop_left(output_format);
+ const int crop_right = media_format_get_crop_right(output_format);
+ const int crop_bottom = media_format_get_crop_bottom(output_format);
+ const int crop_top = media_format_get_crop_top(output_format);
+
+ media_format_destroy(output_format);
+
+ gfx::Size coded_size(width, height);
+ gfx::Rect visible_rect(crop_left, crop_top, width - crop_right - crop_left, height - crop_bottom - crop_top);
+ gfx::Size natural_size(width, height);
+
+ coded_size_ = coded_size;
+ visible_rect_ = visible_rect;
+ natural_size_ = natural_size;
+}
+
+size_t HybrisMediaCodecVideoDecoder::SkipForbiddenNALUs(const uint8_t* data, size_t size)
+{
+ size_t new_offset = 0;
+
+ if (config_.codec() == VideoCodec::kCodecH264) {
+ LOG(INFO) << "H264";
+ if (size > 4 &&
+ data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x01) {
+ LOG(INFO) << "NAL header";
+ return 1;
+ } else if (size > 5 &&
+ data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x00 && data[3] == 0x01) {
+ LOG(INFO) << "NAL header";
+ return 1;
+ }
+ } else if (config_.codec() == VideoCodec::kCodecHEVC) {
+
+ }
+
+ return new_offset;
+}
+
+bool HybrisVideoDecoder::IsSupported() {
+ return (media_compat_check_availability() == 1);
+}
+
+std::unique_ptr<VideoDecoder> HybrisVideoDecoder::Create(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
+ GetStubCB stub_cb) {
+ return std::unique_ptr<VideoDecoder>(new HybrisMediaCodecVideoDecoder(task_runner, gpu_task_runner, stub_cb));
+}
+
+} // namespace media
diff --git a/qtwebengine-chromium/chromium/media/gpu/hybris/video_decoder_hybris.h b/qtwebengine-chromium/chromium/media/gpu/hybris/video_decoder_hybris.h
new file mode 100644
index 000000000..05b96a7bf
--- /dev/null
+++ b/qtwebengine-chromium/chromium/media/gpu/hybris/video_decoder_hybris.h
@@ -0,0 +1,179 @@
+// Copyright 2022 Alfred Neumayer. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_GPU_VIDEO_DECODE_HYBRIS_ACCELERATOR_OVERRIDE_H_
+#define MEDIA_GPU_VIDEO_DECODE_HYBRIS_ACCELERATOR_OVERRIDE_H_
+
+#include "media/base/video_decoder.h"
+#include "media/base/video_decoder_config.h"
+#include "media/gpu/media_gpu_export.h"
+#include "media/video/supported_video_decoder_config.h"
+#include "base/memory/ptr_util.h"
+#include "base/timer/timer.h"
+#include "gpu/config/gpu_preferences.h"
+#include "media/gpu/gles2_decoder_helper.h"
+#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/texture_manager.h"
+#include "media/base/video_frame.h"
+
+#include <memory>
+#include <set>
+#include <vector>
+#include <chrono>
+#include <mutex>
+#include <condition_variable>
+
+#include <hybris/media/media_codec_list.h>
+#include <hybris/media/media_codec_layer.h>
+#include <hybris/media/media_format_layer.h>
+#include <hybris/media/surface_texture_client_hybris.h>
+
+namespace gpu {
+class CommandBufferStub;
+}
+
+namespace media {
+
+using GetStubCB = base::RepeatingCallback<gpu::CommandBufferStub*()>;
+typedef std::function<void(int)> BufferDoneCB;
+
+class MEDIA_GPU_EXPORT HybrisMediaCodecVideoDecoder : public VideoDecoder
+{
+public:
+ static std::vector<SupportedVideoDecoderConfig> GetSupportedConfigs();
+
+ HybrisMediaCodecVideoDecoder(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
+ GetStubCB stub_cb);
+
+protected:
+ ~HybrisMediaCodecVideoDecoder() override;
+
+private:
+ static std::vector<SupportedVideoDecoderConfig> GetSupportedConfigsInternal();
+ static bool IsSupportedProfile(VideoCodecProfile type);
+ static bool IsSupported(VideoCodecProfile type);
+ static const char* MimeTypeForCodecType(VideoCodecProfile type);
+ static std::string FindSuitableCodec(const std::string& codec_type, const bool hwCodecOnly);
+ static void OnFrameAvailable(GLConsumerWrapperHybris, void* data);
+
+public:
+ void Initialize(const VideoDecoderConfig& config,
+ bool low_delay,
+ CdmContext* cdm_context,
+ InitCB init_cb,
+ const OutputCB& output_cb,
+ const WaitingCB& waiting_cb) override;
+
+ void Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb) override;
+ void FrameAvailable();
+ void RedrawTexture();
+ void Destroy();
+ void Reset(base::OnceClosure closure) override;
+ bool NeedsBitstreamConversion() const override;
+ bool CanReadWithoutStalling() const override;
+ int GetMaxDecodeRequests() const override;
+ std::string GetDisplayName() const override;
+
+private:
+ struct QueuedBuffer {
+ scoped_refptr<DecoderBuffer> buffer;
+ DecodeCB decode_cb;
+ };
+
+ struct QueuedDrawOperation {
+ int64_t timestamp;
+ DecodeCB decode_cb;
+ };
+
+ struct MediaCodecBuffer {
+ uint8_t* data;
+ size_t size;
+ };
+
+ void Reconfigure(const VideoDecoderConfig config, InitCB init_cb);
+ void Drain();
+ void Flush();
+ bool ProcessInput(
+ QueuedBuffer& in_flight_buffer);
+ void EnqueueOrderedInput(
+ scoped_refptr<DecoderBuffer> buffer,
+ DecodeCB decode_cb);
+ void RunPipeline();
+ void ExtractSpsAndPps(
+ const std::vector<uint8_t>& avcc,
+ std::vector<uint8_t>* sps_out,
+ std::vector<uint8_t>* pps_out);
+ bool RecreateInputBuffers();
+ bool RecreateOutputBuffers();
+ void RecreateGeometry();
+
+ size_t SkipForbiddenNALUs(const uint8_t* data, size_t size);
+
+ OutputCB output_cb_;
+ DecodeCB eos_decode_cb_;
+
+ bool running_;
+
+ int32_t n_buffers_in_;
+ int32_t n_buffers_out_;
+
+ std::vector<MediaCodecBuffer> codec_input_buffers_;
+
+ std::deque<QueuedBuffer> pending_inputs_;
+ std::deque<QueuedBuffer> pending_outputs_;
+ std::deque<QueuedDrawOperation> pending_redraws_;
+ int32_t queue_timeout_;
+
+ std::mutex drain_mutex_;
+ std::condition_variable drain_condition_;
+ bool is_draining_;
+
+ std::mutex flush_mutex_;
+ std::condition_variable flush_condition_;
+ bool is_flushing_;
+
+ std::mutex redraw_mutex_;
+ std::mutex running_mutex_;
+
+ MediaCodecDelegate media_codec_;
+ MediaFormat media_format_;
+ SurfaceTextureClientHybris stc_;
+ IGBPWrapperHybris igbp_;
+ IGBCWrapperHybris igbc_;
+ GLConsumerWrapperHybris gl_texture_consumer_;
+
+ gpu::DecoderContext* decoder_context_;
+ std::unique_ptr<GLES2DecoderHelper> decoder_helper_;
+ std::unique_ptr<gpu::gles2::AbstractTexture> gl_texture;
+
+ std::string codec_type_;
+ VideoDecoderConfig config_;
+
+ scoped_refptr<base::SingleThreadTaskRunner> pending_input_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> pending_output_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_;
+ base::RepeatingTimer pump_codec_timer_;
+
+ gfx::Size coded_size_;
+ gfx::Rect visible_rect_;
+ gfx::Size natural_size_;
+ std::vector<uint8_t> csd0_;
+ std::vector<uint8_t> csd1_;
+};
+
+class MEDIA_GPU_EXPORT HybrisVideoDecoder {
+ public:
+ static bool IsSupported();
+ static std::unique_ptr<VideoDecoder> Create(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
+ GetStubCB stub_cb);
+};
+
+} // namespace media
+
+#endif // MEDIA_GPU_VIDEO_DECODE_HYBRIS_ACCELERATOR_OVERRIDE_H_
diff --git a/qtwebengine-chromium/chromium/media/media_options.gni b/qtwebengine-chromium/chromium/media/media_options.gni
index acacfcd62..852d9b745 100644
--- a/qtwebengine-chromium/chromium/media/media_options.gni
+++ b/qtwebengine-chromium/chromium/media/media_options.gni
@@ -213,7 +213,7 @@ if (is_chromecast) {
"video_decoder",
]
_default_mojo_media_host = "gpu"
-} else if (is_chromeos || is_mac || is_win || (is_linux && use_vaapi)) {
+} else if (is_chromeos || is_mac || is_win || is_linux) {
_default_mojo_media_services = [ "video_decoder" ]
_default_mojo_media_host = "gpu"
}
diff --git a/qtwebengine-chromium/chromium/media/mojo/services/BUILD.gn b/qtwebengine-chromium/chromium/media/mojo/services/BUILD.gn
index 0782f9fd2..efa3220b4 100644
--- a/qtwebengine-chromium/chromium/media/mojo/services/BUILD.gn
+++ b/qtwebengine-chromium/chromium/media/mojo/services/BUILD.gn
@@ -4,9 +4,14 @@
import("//build/config/chromecast_build.gni")
import("//build/config/jumbo.gni")
+import("//build/config/linux/pkg_config.gni")
import("//media/media_options.gni")
import("//testing/test.gni")
+pkg_config("libmedia") {
+ packages = [ "libmedia" ]
+}
+
jumbo_component("services") {
output_name = "media_mojo_services"
sources = [
@@ -144,6 +149,9 @@ jumbo_component("services") {
deps +=
[ "//chromeos/components/cdm_factory_daemon:cdm_factory_daemon_gpu" ]
}
+ if (is_linux) {
+ defines += [ "ENABLE_HYBRIS_MEDIA" ]
+ }
}
source_set("unit_tests") {
diff --git a/qtwebengine-chromium/chromium/media/mojo/services/gpu_mojo_media_client.cc b/qtwebengine-chromium/chromium/media/mojo/services/gpu_mojo_media_client.cc
index b1f553ce7..4d53d0c05 100644
--- a/qtwebengine-chromium/chromium/media/mojo/services/gpu_mojo_media_client.cc
+++ b/qtwebengine-chromium/chromium/media/mojo/services/gpu_mojo_media_client.cc
@@ -40,6 +40,10 @@
#include "media/mojo/services/mojo_provision_fetcher.h"
#endif // defined(OS_ANDROID)
+#if defined(ENABLE_HYBRIS_MEDIA)
+#include "media/gpu/hybris/video_decoder_hybris.h"
+#endif
+
#if defined(OS_WIN)
#include "media/gpu/windows/d3d11_video_decoder.h"
#include "ui/gl/direct_composition_surface_win.h"
@@ -168,9 +172,16 @@ GpuMojoMediaClient::GetSupportedVideoDecoderConfigs() {
MediaCodecVideoDecoder::GetSupportedConfigs()},
};
return supported_configs;
+
+#elif defined(ENABLE_HYBRIS_MEDIA)
+ static SupportedVideoDecoderConfigMap supported_configs{
+ {VideoDecoderImplementation::kDefault,
+ HybrisMediaCodecVideoDecoder::GetSupportedConfigs()},
+ };
+ return supported_configs;
+
#else
SupportedVideoDecoderConfigMap supported_config_map;
-
#if defined(OS_WIN)
// Start with the configurations supported by D3D11VideoDecoder.
// VdaVideoDecoder is still used as a fallback.
@@ -305,13 +316,23 @@ std::unique_ptr<VideoDecoder> GpuMojoMediaClient::CreateVideoDecoder(
if (gpu_workarounds_.disable_dxva_video_decoder)
return nullptr;
#endif // defined(OS_WIN)
- video_decoder = VdaVideoDecoder::Create(
- task_runner, gpu_task_runner_, media_log->Clone(), target_color_space,
- gpu_preferences_, gpu_workarounds_,
- base::BindRepeating(&GetCommandBufferStub, gpu_task_runner_,
- media_gpu_channel_manager_,
- command_buffer_id->channel_token,
- command_buffer_id->route_id));
+#if defined(ENABLE_HYBRIS_MEDIA)
+ if (HybrisVideoDecoder::IsSupported())
+ video_decoder = HybrisVideoDecoder::Create(
+ task_runner, gpu_task_runner_,
+ base::BindRepeating(&GetCommandBufferStub, gpu_task_runner_,
+ media_gpu_channel_manager_,
+ command_buffer_id->channel_token,
+ command_buffer_id->route_id));
+ else
+#endif // defined(ENABLE_HYBRIS_MEDIA)
+ video_decoder = VdaVideoDecoder::Create(
+ task_runner, gpu_task_runner_, media_log->Clone(), target_color_space,
+ gpu_preferences_, gpu_workarounds_,
+ base::BindRepeating(&GetCommandBufferStub, gpu_task_runner_,
+ media_gpu_channel_manager_,
+ command_buffer_id->channel_token,
+ command_buffer_id->route_id));
#endif // defined(OS_ANDROID)
} break;
diff --git a/src/core/core_module.pro b/src/core/core_module.pro
index 5e8f8d96f..21702ef2c 100644
--- a/src/core/core_module.pro
+++ b/src/core/core_module.pro
@@ -7,7 +7,7 @@ api_library_name = qtwebenginecoreapi$$qtPlatformTargetSuffix()
api_library_path = $$OUT_PWD/api/$$getConfigDir()
LIBS_PRIVATE += -L$$api_library_path
linux:LIBS_PRIVATE += -landroid-properties
-linux:LIBS_PRIVATE += -lhybris-common -lcamera
+linux:LIBS_PRIVATE += -lhybris-common -lcamera -lmedia
CONFIG *= no_smart_library_merge
osx {
LIBS_PRIVATE += -Wl,-force_load,$${api_library_path}$${QMAKE_DIR_SEP}lib$${api_library_name}.a
diff --git a/src/core/gn_run.pro b/src/core/gn_run.pro
index 3d6fda80e..6e9f5b9d9 100644
--- a/src/core/gn_run.pro
+++ b/src/core/gn_run.pro
@@ -33,6 +33,8 @@ build_pass|!debug_and_release {
gn_args += "qtwebengine_target=\"$$system_path($$OUT_PWD/$$getConfigDir()):QtWebEngineCore\""
+ gn_args += "mojo_media_host=\"utility\" mojo_media_services=[\"video_decoder\"]"
+
!qtConfig(webengine-system-gn) {
gn_binary = $$system_quote($$system_path($$gnPath()))
}
@fredldotme
Copy link
Author

Note: Might be missing some parts and is very unclean, has has various experiments behind it.
Maybe someone else can finish this for more than just VP8 & VP9.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment