Index: content/common/gpu/media/video_decode_accelerator_unittest.cc |
diff --git a/content/common/gpu/media/video_decode_accelerator_unittest.cc b/content/common/gpu/media/video_decode_accelerator_unittest.cc |
index b62a9089b06ce7a047eac5a3db5054989319c261..743b6605dcdb3b0c2d7ea836830c917c35d0dc67 100644 |
--- a/content/common/gpu/media/video_decode_accelerator_unittest.cc |
+++ b/content/common/gpu/media/video_decode_accelerator_unittest.cc |
@@ -74,8 +74,10 @@ |
#endif // OS_WIN |
#if defined(USE_OZONE) |
+#include "ui/ozone/public/native_pixmap.h" |
#include "ui/ozone/public/ozone_gpu_test_helper.h" |
#include "ui/ozone/public/ozone_platform.h" |
+#include "ui/ozone/public/surface_factory_ozone.h" |
#endif // defined(USE_OZONE) |
using media::VideoDecodeAccelerator; |
@@ -125,6 +127,10 @@ int g_num_play_throughs = 0; |
// Fake decode |
int g_fake_decoder = 0; |
+// Test buffer import into VDA, providing buffers allocated by us, instead of |
+// requesting the VDA itself to allocate buffers. |
+bool g_test_import = false; |
+ |
// Environment to store rendering thread. |
class VideoDecodeAcceleratorTestEnvironment; |
VideoDecodeAcceleratorTestEnvironment* g_env; |
@@ -269,26 +275,106 @@ class VideoDecodeAcceleratorTestEnvironment : public ::testing::Environment { |
DISALLOW_COPY_AND_ASSIGN(VideoDecodeAcceleratorTestEnvironment); |
}; |
-// A helper class used to manage the lifetime of a Texture. |
+// A helper class used to manage the lifetime of a Texture. Can be backed by |
+// either a buffer allocated by the VDA, or by a preallocated pixmap. |
class TextureRef : public base::RefCounted<TextureRef> { |
public: |
- TextureRef(uint32_t texture_id, const base::Closure& no_longer_needed_cb) |
- : texture_id_(texture_id), no_longer_needed_cb_(no_longer_needed_cb) {} |
+ static scoped_refptr<TextureRef> Create( |
+ uint32_t texture_id, |
+ const base::Closure& no_longer_needed_cb); |
+ |
+ static scoped_refptr<TextureRef> CreatePreallocated( |
+ uint32_t texture_id, |
+ const base::Closure& no_longer_needed_cb, |
+ media::VideoPixelFormat pixel_format, |
+ const gfx::Size& size); |
+ |
+ std::vector<gfx::GpuMemoryBufferHandle> ExportGpuMemoryBufferHandles() const; |
int32_t texture_id() const { return texture_id_; } |
private: |
friend class base::RefCounted<TextureRef>; |
+ |
+ TextureRef(uint32_t texture_id, const base::Closure& no_longer_needed_cb) |
+ : texture_id_(texture_id), no_longer_needed_cb_(no_longer_needed_cb) {} |
+ |
~TextureRef(); |
uint32_t texture_id_; |
base::Closure no_longer_needed_cb_; |
+#if defined(USE_OZONE) |
+ scoped_refptr<ui::NativePixmap> pixmap_; |
+#endif |
}; |
TextureRef::~TextureRef() { |
base::ResetAndReturn(&no_longer_needed_cb_).Run(); |
} |
+// static |
+scoped_refptr<TextureRef> TextureRef::Create( |
+ uint32_t texture_id, |
+ const base::Closure& no_longer_needed_cb) { |
+ return make_scoped_refptr(new TextureRef(texture_id, no_longer_needed_cb)); |
+} |
+ |
+#if defined(USE_OZONE) |
+gfx::BufferFormat VideoPixelFormatToGfxBufferFormat( |
+ media::VideoPixelFormat pixel_format) { |
+ switch (pixel_format) { |
+ case media::VideoPixelFormat::PIXEL_FORMAT_ARGB: |
+ return gfx::BufferFormat::BGRA_8888; |
+ case media::VideoPixelFormat::PIXEL_FORMAT_XRGB: |
+ return gfx::BufferFormat::BGRX_8888; |
+ case media::VideoPixelFormat::PIXEL_FORMAT_NV12: |
+ return gfx::BufferFormat::YUV_420_BIPLANAR; |
+ default: |
+ LOG_ASSERT(false) << "Unknown VideoPixelFormat"; |
+ return gfx::BufferFormat::BGRX_8888; |
+ } |
+} |
+#endif |
+ |
+// static |
+scoped_refptr<TextureRef> TextureRef::CreatePreallocated( |
+ uint32_t texture_id, |
+ const base::Closure& no_longer_needed_cb, |
+ media::VideoPixelFormat pixel_format, |
+ const gfx::Size& size) { |
+ scoped_refptr<TextureRef> texture_ref; |
+#if defined(USE_OZONE) |
+ texture_ref = TextureRef::Create(texture_id, no_longer_needed_cb); |
+ LOG_ASSERT(texture_ref); |
+ |
+ ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance(); |
+ ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone(); |
+ gfx::BufferFormat buffer_format = |
+ VideoPixelFormatToGfxBufferFormat(pixel_format); |
+ texture_ref->pixmap_ = |
+ factory->CreateNativePixmap(gfx::kNullAcceleratedWidget, size, |
+ buffer_format, gfx::BufferUsage::SCANOUT); |
+ LOG_ASSERT(texture_ref->pixmap_); |
+#endif |
+ |
+ return texture_ref; |
+} |
+ |
+std::vector<gfx::GpuMemoryBufferHandle> |
+TextureRef::ExportGpuMemoryBufferHandles() const { |
+ std::vector<gfx::GpuMemoryBufferHandle> handles; |
+#if defined(USE_OZONE) |
+ CHECK(pixmap_); |
+ int duped_fd = HANDLE_EINTR(dup(pixmap_->GetDmaBufFd())); |
+ LOG_ASSERT(duped_fd != -1) << "Failed duplicating dmabuf fd"; |
+ gfx::GpuMemoryBufferHandle handle; |
+ handle.type = gfx::OZONE_NATIVE_PIXMAP; |
+ handle.native_pixmap_handle.fd = base::FileDescriptor(duped_fd, true); |
+ handles.push_back(handle); |
+#endif |
+ return handles; |
+} |
+ |
// Client that can accept callbacks from a VideoDecodeAccelerator and is used by |
// the TESTs below. |
class GLRenderingVDAClient |
@@ -531,6 +617,10 @@ void GLRenderingVDAClient::CreateAndStartDecoder() { |
} |
VideoDecodeAccelerator::Config config(profile_); |
+ if (g_test_import) { |
+ config.output_mode = |
+ media::VideoDecodeAccelerator::Config::OutputMode::IMPORT; |
+ } |
gpu::GpuPreferences gpu_preferences; |
decoder_ = vda_factory_->CreateVDA(this, config, gpu_preferences); |
} |
@@ -564,21 +654,46 @@ void GLRenderingVDAClient::ProvidePictureBuffers( |
texture_target_, &texture_id, dimensions, &done); |
done.Wait(); |
+ scoped_refptr<TextureRef> texture_ref; |
+ base::Closure delete_texture_cb = |
+ base::Bind(&RenderingHelper::DeleteTexture, |
+ base::Unretained(rendering_helper_), texture_id); |
+ |
+ if (g_test_import) { |
+ media::VideoPixelFormat pixel_format = decoder_->GetOutputFormat(); |
+ if (pixel_format == media::PIXEL_FORMAT_UNKNOWN) |
+ pixel_format = media::PIXEL_FORMAT_ARGB; |
+ texture_ref = TextureRef::CreatePreallocated( |
+ texture_id, delete_texture_cb, pixel_format, dimensions); |
+ } else { |
+ texture_ref = TextureRef::Create(texture_id, delete_texture_cb); |
+ } |
+ |
+ LOG_ASSERT(texture_ref); |
+ |
int32_t picture_buffer_id = next_picture_buffer_id_++; |
- LOG_ASSERT(active_textures_ |
- .insert(std::make_pair( |
- picture_buffer_id, |
- new TextureRef(texture_id, |
- base::Bind(&RenderingHelper::DeleteTexture, |
- base::Unretained(rendering_helper_), |
- texture_id)))) |
- .second); |
+ LOG_ASSERT( |
+ active_textures_.insert(std::make_pair(picture_buffer_id, texture_ref)) |
+ .second); |
media::PictureBuffer::TextureIds ids; |
ids.push_back(texture_id); |
buffers.push_back(media::PictureBuffer(picture_buffer_id, dimensions, ids)); |
} |
decoder_->AssignPictureBuffers(buffers); |
+ |
+ if (g_test_import) { |
+ for (const auto& buffer : buffers) { |
+ TextureRefMap::iterator texture_it = active_textures_.find(buffer.id()); |
+ ASSERT_NE(active_textures_.end(), texture_it); |
+ |
+ std::vector<gfx::GpuMemoryBufferHandle> handles = |
+ texture_it->second->ExportGpuMemoryBufferHandles(); |
+ LOG_ASSERT(!handles.empty()) << "Failed producing GMB handles"; |
+ |
+ decoder_->ImportBufferForPicture(buffer.id(), handles); |
+ } |
+ } |
} |
void GLRenderingVDAClient::DismissPictureBuffer(int32_t picture_buffer_id) { |
@@ -1557,6 +1672,10 @@ int main(int argc, char **argv) { |
continue; |
if (it->first == "ozone-platform" || it->first == "ozone-use-surfaceless") |
continue; |
+ if (it->first == "test_import") { |
+ content::g_test_import = true; |
+ continue; |
+ } |
LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; |
} |