Commit 9f529e3a authored by Xing Liu's avatar Xing Liu Committed by Commit Bot

Android Video Thumbnail: Render video frame to bitmap.

This CL finishes the video thumbnail pipeline for most codec except
vp8, vp9. Now it's ready to hook to the UI frontend. It does following:

1. Render the video frame with existing media toolkit, which can read
back pixel data from a texture in GPU process.

2. Plumbs a few metadata fields and thumbnail bitmap to Java layer.

Bug: 826021
Change-Id: Id6635975726f4b12ab51e01cb6b3e78a198632f4
Reviewed-on: https://chromium-review.googlesource.com/1222694Reviewed-by: default avatarMin Qin <qinmin@chromium.org>
Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Commit-Queue: Xing Liu <xingliu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#591406}
parent 44db0257
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.download;
import android.graphics.Bitmap;
import org.chromium.base.annotations.CalledByNative;
/**
* Contains local media metadata and thumbnails.
*/
public class DownloadMediaData {
/**
* The duration of the media file in seconds. Or -1 if no duration in the metadata.
*/
public final double duration;
/**
* Title of the media.
*/
public final String title;
/**
* Artist of the media.
*/
public final String artist;
/**
* A thumbnail represents the media. Can be a poster image retrieved with metadata for both
* audio and video file. Or retrieved from a video key frame for video files.
*/
public final Bitmap thumbnail;
@CalledByNative
private DownloadMediaData(double duration, String title, String artist, Bitmap thumbnail) {
this.duration = duration;
this.title = title;
this.artist = artist;
this.thumbnail = thumbnail;
}
}
...@@ -19,8 +19,8 @@ public class DownloadMediaParserBridge { ...@@ -19,8 +19,8 @@ public class DownloadMediaParserBridge {
* @param totalSize Total size of the media file. * @param totalSize Total size of the media file.
* @param callback Callback to get the result. * @param callback Callback to get the result.
*/ */
public DownloadMediaParserBridge( public DownloadMediaParserBridge(String mimeType, String filePath, long totalSize,
String mimeType, String filePath, long totalSize, Callback<Boolean> callback) { Callback<DownloadMediaData> callback) {
mNativeDownloadMediaParserBridge = nativeInit(mimeType, filePath, totalSize, callback); mNativeDownloadMediaParserBridge = nativeInit(mimeType, filePath, totalSize, callback);
} }
...@@ -43,7 +43,7 @@ public class DownloadMediaParserBridge { ...@@ -43,7 +43,7 @@ public class DownloadMediaParserBridge {
} }
private native long nativeInit( private native long nativeInit(
String mimeType, String filePath, long totalSize, Callback<Boolean> callback); String mimeType, String filePath, long totalSize, Callback<DownloadMediaData> callback);
private native void nativeDestory(long nativeDownloadMediaParserBridge); private native void nativeDestory(long nativeDownloadMediaParserBridge);
private native void nativeStart(long nativeDownloadMediaParserBridge); private native void nativeStart(long nativeDownloadMediaParserBridge);
} }
...@@ -440,6 +440,7 @@ chrome_java_sources = [ ...@@ -440,6 +440,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/download/DownloadLocationDialogBridge.java", "java/src/org/chromium/chrome/browser/download/DownloadLocationDialogBridge.java",
"java/src/org/chromium/chrome/browser/download/DownloadManagerDelegate.java", "java/src/org/chromium/chrome/browser/download/DownloadManagerDelegate.java",
"java/src/org/chromium/chrome/browser/download/DownloadManagerService.java", "java/src/org/chromium/chrome/browser/download/DownloadManagerService.java",
"java/src/org/chromium/chrome/browser/download/DownloadMediaData.java",
"java/src/org/chromium/chrome/browser/download/DownloadMediaParserBridge.java", "java/src/org/chromium/chrome/browser/download/DownloadMediaParserBridge.java",
"java/src/org/chromium/chrome/browser/download/DownloadMetrics.java", "java/src/org/chromium/chrome/browser/download/DownloadMetrics.java",
"java/src/org/chromium/chrome/browser/download/DownloadNotificationFactory.java", "java/src/org/chromium/chrome/browser/download/DownloadNotificationFactory.java",
......
...@@ -46,7 +46,7 @@ public class DownloadMediaParserTest { ...@@ -46,7 +46,7 @@ public class DownloadMediaParserTest {
*/ */
public static class MediaParseResult { public static class MediaParseResult {
public boolean done; public boolean done;
public boolean success; public DownloadMediaData mediaData;
} }
@Before @Before
...@@ -68,8 +68,8 @@ public class DownloadMediaParserTest { ...@@ -68,8 +68,8 @@ public class DownloadMediaParserTest {
// The native DownloadMediaParser needs to be created on UI thread. // The native DownloadMediaParser needs to be created on UI thread.
ThreadUtils.runOnUiThreadBlocking(() -> { ThreadUtils.runOnUiThreadBlocking(() -> {
DownloadMediaParserBridge parser = new DownloadMediaParserBridge( DownloadMediaParserBridge parser = new DownloadMediaParserBridge(
"audio/mp3", filePath, audioFile.length(), (success) -> { "audio/mp3", filePath, audioFile.length(), (DownloadMediaData mediaData) -> {
result.success = success; result.mediaData = mediaData;
result.done = true; result.done = true;
}); });
parser.start(); parser.start();
...@@ -82,7 +82,7 @@ public class DownloadMediaParserTest { ...@@ -82,7 +82,7 @@ public class DownloadMediaParserTest {
} }
}, MAX_MEDIA_PARSER_POLL_TIME_MS, MEDIA_PARSER_POLL_INTERVAL_MS); }, MAX_MEDIA_PARSER_POLL_TIME_MS, MEDIA_PARSER_POLL_INTERVAL_MS);
Assert.assertTrue("Failed to parse audio metadata.", result.success); Assert.assertTrue("Failed to parse audio metadata.", result.mediaData != null);
} }
@Test @Test
...@@ -99,8 +99,8 @@ public class DownloadMediaParserTest { ...@@ -99,8 +99,8 @@ public class DownloadMediaParserTest {
// The native DownloadMediaParser needs to be created on UI thread. // The native DownloadMediaParser needs to be created on UI thread.
ThreadUtils.runOnUiThreadBlocking(() -> { ThreadUtils.runOnUiThreadBlocking(() -> {
DownloadMediaParserBridge parser = new DownloadMediaParserBridge( DownloadMediaParserBridge parser = new DownloadMediaParserBridge(
"video/mp4", filePath, videoFile.length(), (success) -> { "video/mp4", filePath, videoFile.length(), (DownloadMediaData mediaData) -> {
result.success = success; result.mediaData = mediaData;
result.done = true; result.done = true;
}); });
parser.start(); parser.start();
...@@ -113,6 +113,10 @@ public class DownloadMediaParserTest { ...@@ -113,6 +113,10 @@ public class DownloadMediaParserTest {
} }
}, MAX_MEDIA_PARSER_POLL_TIME_MS, MEDIA_PARSER_POLL_INTERVAL_MS); }, MAX_MEDIA_PARSER_POLL_TIME_MS, MEDIA_PARSER_POLL_INTERVAL_MS);
Assert.assertTrue("Failed to parse video file.", result.success); Assert.assertTrue("Failed to parse video file.", result.mediaData != null);
Assert.assertTrue(
"Failed to retrieve thumbnail.", result.mediaData.thumbnail.getWidth() > 0);
Assert.assertTrue(
"Failed to retrieve thumbnail.", result.mediaData.thumbnail.getHeight() > 0);
} }
} }
...@@ -2125,6 +2125,8 @@ jumbo_split_static_library("browser") { ...@@ -2125,6 +2125,8 @@ jumbo_split_static_library("browser") {
"android/download/service/download_background_task.cc", "android/download/service/download_background_task.cc",
"android/download/service/download_task_scheduler.cc", "android/download/service/download_task_scheduler.cc",
"android/download/service/download_task_scheduler.h", "android/download/service/download_task_scheduler.h",
"android/download/video_frame_thumbnail_converter.cc",
"android/download/video_frame_thumbnail_converter.h",
"android/explore_sites/catalog.cc", "android/explore_sites/catalog.cc",
"android/explore_sites/catalog.h", "android/explore_sites/catalog.h",
"android/explore_sites/explore_sites_bridge.cc", "android/explore_sites/explore_sites_bridge.cc",
...@@ -4570,6 +4572,7 @@ if (is_android) { ...@@ -4570,6 +4572,7 @@ if (is_android) {
"../android/java/src/org/chromium/chrome/browser/download/DownloadItem.java", "../android/java/src/org/chromium/chrome/browser/download/DownloadItem.java",
"../android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialogBridge.java", "../android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialogBridge.java",
"../android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java", "../android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java",
"../android/java/src/org/chromium/chrome/browser/download/DownloadMediaData.java",
"../android/java/src/org/chromium/chrome/browser/download/DownloadMediaParserBridge.java", "../android/java/src/org/chromium/chrome/browser/download/DownloadMediaParserBridge.java",
"../android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java", "../android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java",
"../android/java/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorFactory.java", "../android/java/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorFactory.java",
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/task/post_task.h" #include "base/task/post_task.h"
#include "base/task/task_traits.h" #include "base/task/task_traits.h"
#include "chrome/browser/android/download/local_media_data_source_factory.h" #include "chrome/browser/android/download/local_media_data_source_factory.h"
#include "chrome/browser/android/download/video_frame_thumbnail_converter.h"
#include "content/public/browser/android/gpu_video_accelerator_factories_provider.h" #include "content/public/browser/android/gpu_video_accelerator_factories_provider.h"
#include "content/public/common/service_manager_connection.h" #include "content/public/common/service_manager_connection.h"
#include "media/base/overlay_info.h" #include "media/base/overlay_info.h"
...@@ -19,6 +20,8 @@ ...@@ -19,6 +20,8 @@
#include "media/mojo/services/media_interface_provider.h" #include "media/mojo/services/media_interface_provider.h"
#include "media/video/gpu_video_accelerator_factories.h" #include "media/video/gpu_video_accelerator_factories.h"
#include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/connector.h"
#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "third_party/skia/include/core/SkBitmap.h"
namespace { namespace {
...@@ -91,6 +94,7 @@ void DownloadMediaParser::OnMediaMetadataParsed( ...@@ -91,6 +94,7 @@ void DownloadMediaParser::OnMediaMetadataParsed(
return; return;
} }
metadata_ = std::move(metadata); metadata_ = std::move(metadata);
DCHECK(metadata_);
// TODO(xingliu): Make |attached_images| movable and use this as a thumbnail // TODO(xingliu): Make |attached_images| movable and use this as a thumbnail
// source as well as video frame. // source as well as video frame.
...@@ -99,14 +103,14 @@ void DownloadMediaParser::OnMediaMetadataParsed( ...@@ -99,14 +103,14 @@ void DownloadMediaParser::OnMediaMetadataParsed(
// For audio file, we only need metadata and poster. // For audio file, we only need metadata and poster.
if (base::StartsWith(mime_type_, "audio/", if (base::StartsWith(mime_type_, "audio/",
base::CompareCase::INSENSITIVE_ASCII)) { base::CompareCase::INSENSITIVE_ASCII)) {
NotifyComplete(); NotifyComplete(SkBitmap());
return; return;
} }
DCHECK(base::StartsWith(mime_type_, "video/", DCHECK(base::StartsWith(mime_type_, "video/",
base::CompareCase::INSENSITIVE_ASCII)); base::CompareCase::INSENSITIVE_ASCII));
// Retrieves video thumbnail if needed. // Start to retrieve video thumbnail.
base::ThreadTaskRunnerHandle::Get()->PostTask( base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&DownloadMediaParser::RetrieveEncodedVideoFrame, FROM_HERE, base::BindOnce(&DownloadMediaParser::RetrieveEncodedVideoFrame,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
...@@ -213,9 +217,29 @@ void DownloadMediaParser::OnVideoFrameDecoded( ...@@ -213,9 +217,29 @@ void DownloadMediaParser::OnVideoFrameDecoded(
DCHECK(frame->HasTextures()); DCHECK(frame->HasTextures());
decode_done_ = true; decode_done_ = true;
// TODO(xingliu): render the |frame| in the browser process, with cc or skia RenderVideoFrame(frame);
// or gl. The |frame| is associated with a native texture in GPU process. }
NotifyComplete();
void DownloadMediaParser::RenderVideoFrame(
const scoped_refptr<media::VideoFrame>& video_frame) {
auto converter = VideoFrameThumbnailConverter::Create(
config_.codec(), gpu_factories_->GetMediaContextProvider());
converter->ConvertToBitmap(
video_frame,
base::BindOnce(&DownloadMediaParser::OnBitmapGenerated,
weak_factory_.GetWeakPtr(), std::move(converter)));
}
void DownloadMediaParser::OnBitmapGenerated(
std::unique_ptr<VideoFrameThumbnailConverter>,
bool success,
SkBitmap bitmap) {
if (!success) {
OnError();
return;
}
NotifyComplete(std::move(bitmap));
} }
media::mojom::InterfaceFactory* media::mojom::InterfaceFactory*
...@@ -250,14 +274,17 @@ void DownloadMediaParser::OnMediaDataReady( ...@@ -250,14 +274,17 @@ void DownloadMediaParser::OnMediaDataReady(
std::move(callback).Run(std::vector<uint8_t>(data->begin(), data->end())); std::move(callback).Run(std::vector<uint8_t>(data->begin(), data->end()));
} }
void DownloadMediaParser::NotifyComplete() { void DownloadMediaParser::NotifyComplete(SkBitmap bitmap) {
// TODO(xingliu): Return the metadata and video thumbnail data in // TODO(xingliu): Return the metadata and video thumbnail data in
// |parse_complete_cb_|. // |parse_complete_cb_|.
DCHECK(metadata_);
if (parse_complete_cb_) if (parse_complete_cb_)
std::move(parse_complete_cb_).Run(true); std::move(parse_complete_cb_)
.Run(true, std::move(metadata_), std::move(bitmap));
} }
void DownloadMediaParser::OnError() { void DownloadMediaParser::OnError() {
if (parse_complete_cb_) if (parse_complete_cb_)
std::move(parse_complete_cb_).Run(false); std::move(parse_complete_cb_)
.Run(false, chrome::mojom::MediaMetadata::New(), SkBitmap());
} }
...@@ -28,11 +28,21 @@ class MojoVideoDecoder; ...@@ -28,11 +28,21 @@ class MojoVideoDecoder;
class VideoDecoderConfig; class VideoDecoderConfig;
} // namespace media } // namespace media
// Local media files parser is used to process local media files. This object class SkBitmap;
// lives on main thread in browser process. class VideoFrameThumbnailConverter;
// Parse local media files, including media metadata and thumbnails.
// Metadata is always parsed in utility process for both audio and video files.
//
// For video file, the thumbnail may be poster image in metadata or extracted
// video frame. The frame extraction always happens in utility process. The
// decoding may happen in utility or GPU process based on video codec.
class DownloadMediaParser : public MediaParserProvider, public media::MediaLog { class DownloadMediaParser : public MediaParserProvider, public media::MediaLog {
public: public:
using ParseCompleteCB = base::OnceCallback<void(bool)>; using ParseCompleteCB =
base::OnceCallback<void(bool success,
chrome::mojom::MediaMetadataPtr media_metadata,
SkBitmap bitmap)>;
DownloadMediaParser(int64_t size, DownloadMediaParser(int64_t size,
const std::string& mime_type, const std::string& mime_type,
...@@ -42,8 +52,8 @@ class DownloadMediaParser : public MediaParserProvider, public media::MediaLog { ...@@ -42,8 +52,8 @@ class DownloadMediaParser : public MediaParserProvider, public media::MediaLog {
// Parse media metadata in a local file. All file IO will run on // Parse media metadata in a local file. All file IO will run on
// |file_task_runner|. The metadata is parsed in an utility process safely. // |file_task_runner|. The metadata is parsed in an utility process safely.
// However, the result is still comes from user-defined input, thus should be // The thumbnail is retrieved from GPU process or utility process based on
// used with caution. // different codec.
void Start(); void Start();
private: private:
...@@ -75,12 +85,18 @@ class DownloadMediaParser : public MediaParserProvider, public media::MediaLog { ...@@ -75,12 +85,18 @@ class DownloadMediaParser : public MediaParserProvider, public media::MediaLog {
media::mojom::InterfaceFactory* GetMediaInterfaceFactory(); media::mojom::InterfaceFactory* GetMediaInterfaceFactory();
void OnDecoderConnectionError(); void OnDecoderConnectionError();
// Renders the video frame to bitmap.
void RenderVideoFrame(const scoped_refptr<media::VideoFrame>& video_frame);
void OnBitmapGenerated(std::unique_ptr<VideoFrameThumbnailConverter>,
bool success,
SkBitmap bitmap);
// Overlays media data source read operation. Gradually read data from media // Overlays media data source read operation. Gradually read data from media
// file. // file.
void OnMediaDataReady(chrome::mojom::MediaDataSource::ReadCallback callback, void OnMediaDataReady(chrome::mojom::MediaDataSource::ReadCallback callback,
std::unique_ptr<std::string> data); std::unique_ptr<std::string> data);
void NotifyComplete(); void NotifyComplete(SkBitmap bitmap);
void OnError(); void OnError();
int64_t size_; int64_t size_;
...@@ -89,6 +105,8 @@ class DownloadMediaParser : public MediaParserProvider, public media::MediaLog { ...@@ -89,6 +105,8 @@ class DownloadMediaParser : public MediaParserProvider, public media::MediaLog {
ParseCompleteCB parse_complete_cb_; ParseCompleteCB parse_complete_cb_;
chrome::mojom::MediaMetadataPtr metadata_; chrome::mojom::MediaMetadataPtr metadata_;
// Poster images obtained with |metadata_|.
std::vector<metadata::AttachedImage> attached_images_; std::vector<metadata::AttachedImage> attached_images_;
std::unique_ptr<chrome::mojom::MediaDataSource> media_data_source_; std::unique_ptr<chrome::mojom::MediaDataSource> media_data_source_;
...@@ -96,9 +114,8 @@ class DownloadMediaParser : public MediaParserProvider, public media::MediaLog { ...@@ -96,9 +114,8 @@ class DownloadMediaParser : public MediaParserProvider, public media::MediaLog {
// The task runner to do blocking disk IO. // The task runner to do blocking disk IO.
scoped_refptr<base::SequencedTaskRunner> file_task_runner_; scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
// Encoded frame to be decoded. The data comes from a safe sandboxed process. // Encoded video frame to be decoded. This data can be large for high
// This data can be large for high resolution video, should be std::move or // resolution video, should be std::move or cleared whenever possible.
// cleared whenever possible.
std::vector<uint8_t> encoded_data_; std::vector<uint8_t> encoded_data_;
// Objects used to decode the video into media::VideoFrame. // Objects used to decode the video into media::VideoFrame.
......
...@@ -8,13 +8,35 @@ ...@@ -8,13 +8,35 @@
#include "base/android/jni_string.h" #include "base/android/jni_string.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/task/post_task.h" #include "base/task/post_task.h"
#include "jni/DownloadMediaData_jni.h"
#include "jni/DownloadMediaParserBridge_jni.h" #include "jni/DownloadMediaParserBridge_jni.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/android/java_bitmap.h"
using base::android::ConvertUTF8ToJavaString;
namespace { namespace {
void OnMediaParsed(const base::android::ScopedJavaGlobalRef<jobject> jcallback, void OnMediaParsed(const base::android::ScopedJavaGlobalRef<jobject> jcallback,
bool success) { bool success,
base::android::RunBooleanCallbackAndroid(jcallback, success); chrome::mojom::MediaMetadataPtr metadata,
SkBitmap thumbnail_bitmap) {
JNIEnv* env = base::android::AttachCurrentThread();
DCHECK(metadata);
// Copy the thumbnail bitmap to a Java Bitmap object.
base::android::ScopedJavaLocalRef<jobject> java_bitmap;
if (!thumbnail_bitmap.isNull())
java_bitmap = gfx::ConvertToJavaBitmap(&thumbnail_bitmap);
base::android::ScopedJavaLocalRef<jobject> media_data;
if (success) {
media_data = Java_DownloadMediaData_Constructor(
env, metadata->duration, ConvertUTF8ToJavaString(env, metadata->title),
ConvertUTF8ToJavaString(env, metadata->artist), std::move(java_bitmap));
}
base::android::RunObjectCallbackAndroid(jcallback, std::move(media_data));
} }
} // namespace } // namespace
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/android/download/video_frame_thumbnail_converter.h"
#include "base/macros.h"
#include "cc/paint/skia_paint_canvas.h"
#include "components/viz/common/gl_helper.h"
#include "media/base/video_frame.h"
#include "media/renderers/paint_canvas_video_renderer.h"
#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
namespace {
// Class to generate bitmap based on video frame backed by texture in remote
// process.
class TextureFrameThumbnailConverter : public VideoFrameThumbnailConverter {
public:
TextureFrameThumbnailConverter(
scoped_refptr<ws::ContextProviderCommandBuffer> context_provider)
: context_provider_(std::move(context_provider)) {}
TextureFrameThumbnailConverter() = default;
~TextureFrameThumbnailConverter() override = default;
private:
// VideoFrameThumbnailConverter implementation.
void ConvertToBitmap(const scoped_refptr<media::VideoFrame>& frame,
BitmapCallback pixel_callback) override {
DCHECK(frame->HasTextures())
<< "This implementation only do texture read backs.";
// Read back the texture data contained in the video frame.
media::PaintCanvasVideoRenderer renderer;
SkBitmap skbitmap;
skbitmap.allocN32Pixels(frame->visible_rect().width(),
frame->visible_rect().height());
cc::SkiaPaintCanvas canvas(skbitmap);
renderer.Copy(frame, &canvas,
media::Context3D(context_provider_->ContextGL(),
context_provider_->GrContext()));
std::move(pixel_callback).Run(true, std::move(skbitmap));
}
// Command buffer channel used to read back the pixel data from texture in
// remote process.
scoped_refptr<ws::ContextProviderCommandBuffer> context_provider_;
DISALLOW_COPY_AND_ASSIGN(TextureFrameThumbnailConverter);
};
} // namespace
// static
std::unique_ptr<VideoFrameThumbnailConverter>
VideoFrameThumbnailConverter::Create(
media::VideoCodec codec,
scoped_refptr<ws::ContextProviderCommandBuffer> context_provider) {
// TODO(xingliu): Implement vpx decode and render pipeline.
DCHECK_NE(codec, media::VideoCodec::kCodecVP8);
DCHECK_NE(codec, media::VideoCodec::kCodecVP9);
return std::make_unique<TextureFrameThumbnailConverter>(
std::move(context_provider));
}
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ANDROID_DOWNLOAD_VIDEO_FRAME_THUMBNAIL_CONVERTER_H_
#define CHROME_BROWSER_ANDROID_DOWNLOAD_VIDEO_FRAME_THUMBNAIL_CONVERTER_H_
#include <memory>
#include <vector>
#include "base/callback.h"
#include "base/memory/scoped_refptr.h"
#include "media/base/video_codecs.h"
namespace media {
class VideoFrame;
} // namespace media
namespace ws {
class ContextProviderCommandBuffer;
} // namespace ws
class SkBitmap;
// Generates video thumbnail from a video frame. For most video format such as
// H264, the input video frame contains a texture created in GPU process, we do
// a readback and generate the bitmap. For vp8, vp9 format, the video frame
// contains in-memory YUV data.
class VideoFrameThumbnailConverter {
public:
using BitmapCallback = base::OnceCallback<void(bool, SkBitmap)>;
// Create the video thumbnail renderer for video type with |codec|. The
// decoder to generate video frame may yields video frames backed by texture
// in remote process or raw YUV data.
static std::unique_ptr<VideoFrameThumbnailConverter> Create(
media::VideoCodec codec,
scoped_refptr<ws::ContextProviderCommandBuffer> context_provider);
virtual void ConvertToBitmap(const scoped_refptr<media::VideoFrame>& frame,
BitmapCallback pixel_callback) = 0;
virtual ~VideoFrameThumbnailConverter() = default;
};
#endif // CHROME_BROWSER_ANDROID_DOWNLOAD_VIDEO_FRAME_THUMBNAIL_CONVERTER_H_
...@@ -41,7 +41,7 @@ void OnGpuChannelEstablished( ...@@ -41,7 +41,7 @@ void OnGpuChannelEstablished(
constexpr bool automatic_flushes = false; constexpr bool automatic_flushes = false;
constexpr bool support_locking = false; constexpr bool support_locking = false;
constexpr bool support_grcontext = false; constexpr bool support_grcontext = true;
auto context_provider = auto context_provider =
base::MakeRefCounted<ws::ContextProviderCommandBuffer>( base::MakeRefCounted<ws::ContextProviderCommandBuffer>(
...@@ -187,7 +187,7 @@ BrowserGpuVideoAcceleratorFactories:: ...@@ -187,7 +187,7 @@ BrowserGpuVideoAcceleratorFactories::
scoped_refptr<ws::ContextProviderCommandBuffer> scoped_refptr<ws::ContextProviderCommandBuffer>
BrowserGpuVideoAcceleratorFactories::GetMediaContextProvider() { BrowserGpuVideoAcceleratorFactories::GetMediaContextProvider() {
return nullptr; return context_provider_;
} }
void BrowserGpuVideoAcceleratorFactories::SetRenderingColorSpace( void BrowserGpuVideoAcceleratorFactories::SetRenderingColorSpace(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment