Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1968)

Unified Diff: media/renderers/skcanvas_video_renderer.cc

Issue 2791813003: Fix broken draw/upload paths from videos to 2D canvas and WebGL. (Closed)
Patch Set: Rebased. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/renderers/skcanvas_video_renderer.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/renderers/skcanvas_video_renderer.cc
diff --git a/media/renderers/skcanvas_video_renderer.cc b/media/renderers/skcanvas_video_renderer.cc
index 1e2e9b21ab1a7e25977f25aeb0a8452a56a533ca..a35725e89e663adad54293bad17dba7ae672ab9c 100644
--- a/media/renderers/skcanvas_video_renderer.cc
+++ b/media/renderers/skcanvas_video_renderer.cc
@@ -160,6 +160,34 @@ sk_sp<SkImage> NewSkImageFromVideoFrameYUVTextures(
return img;
}
+gfx::Size MinVideoFrameSize(const VideoFrame* video_frame) {
+ // On some platforms, and in some situations, the video's texture might
+ // be larger than the natural size because the encoder might have had to
+ // round up to the size of a macroblock.
+ //
+ // In other situations, the natural size has been seen to be _larger_
+ // than the coded size -- despite the fact that this means that there are
+ // regions not actually covered by decoded video data! This appears to
+ // happen if the Sample Aspect Ratio in the video's metadata is slightly
+ // incorrect.
sandersd (OOO until July 31) 2017/04/03 18:56:21 This wording is misleading; it implies that normal
Ken Russell (switch to Gerrit) 2017/04/03 20:43:32 Thanks for these clarifications. Sorry for the mis
sandersd (OOO until July 31) 2017/04/03 21:19:10 Reading the WebGL spec, I'm not certain what it ac
Ken Russell (switch to Gerrit) 2017/04/07 07:16:00 Agreed that the spec needs to be clarified. There
+ //
+ // Callers of some of the APIs in this file are responsible for
+ // allocating the textures into which the video data goes. The only
+ // sizing information these callers have are the width and height of the
+ // video -- which are inevitably the natural width and height, since
+ // that's all that's reliably available in the PipelineMetadata. The
+ // destination textures are therefore allocated at this size.
+ //
+ // To avoid putting garbage into the bottom of the destination frame for
+ // the first case, and to avoid mismatches between the source and
+ // destination textures in CopySubTextureCHROMIUM operations for the
+ // second case, we report the minimum video frame size as the
+ // intersection of the coded size and the natural size.
+ gfx::Size result = video_frame->natural_size();
+ result.SetToMin(video_frame->coded_size());
+ return result;
+}
+
// Creates a SkImage from a |video_frame| backed by native resources.
// The SkImage will take ownership of the underlying resource.
sk_sp<SkImage> NewSkImageFromVideoFrameNative(VideoFrame* video_frame,
@@ -184,12 +212,9 @@ sk_sp<SkImage> NewSkImageFromVideoFrameNative(VideoFrame* video_frame,
gl->GenTextures(1, &source_texture);
DCHECK(source_texture);
gl->BindTexture(GL_TEXTURE_2D, source_texture);
- const gfx::Size& natural_size = video_frame->natural_size();
- gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, natural_size.width(),
- natural_size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
- nullptr);
SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture(
- gl, video_frame, source_texture, true, false);
+ gl, video_frame, SkCanvasVideoRenderer::SingleFrameCopyTexture,
+ source_texture, GL_RGBA, GL_UNSIGNED_BYTE, true, false);
} else {
gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData());
source_texture = gl->CreateAndConsumeTextureCHROMIUM(
@@ -753,7 +778,10 @@ void SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels(
void SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture(
gpu::gles2::GLES2Interface* gl,
VideoFrame* video_frame,
+ SingleFrameCopyMode mode,
unsigned int texture,
+ unsigned int internal_format,
+ unsigned int type,
bool premultiply_alpha,
bool flip_y) {
DCHECK(video_frame);
@@ -776,14 +804,29 @@ void SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture(
// "flip_y == true" means to reverse the video orientation while
// "flip_y == false" means to keep the intrinsic orientation.
- // The video's texture might be larger than the natural size because
- // the encoder might have had to round up to the size of a macroblock.
- // Make sure to only copy the natural size to avoid putting garbage
- // into the bottom of the destination texture.
- const gfx::Size& natural_size = video_frame->natural_size();
- gl->CopySubTextureCHROMIUM(source_texture, 0, GL_TEXTURE_2D, texture, 0, 0, 0,
- 0, 0, natural_size.width(), natural_size.height(),
- flip_y, premultiply_alpha, false);
+ switch (mode) {
+ case SingleFrameCopyTexture: {
+ // Assume that the caller is responsible for clipping the source
+ // texture during rendering to the video's natural width and
+ // height. This is done for example during rendering of the actual
+ // video element.
+ gl->CopyTextureCHROMIUM(source_texture, 0, GL_TEXTURE_2D, texture, 0,
+ internal_format, type, flip_y, premultiply_alpha,
+ false);
+ break;
+ }
+ case SingleFrameCopySubTexture: {
+ // Use the minimum of the coded size and natural size to copy only
+ // the good portion of the video frame.
+ gfx::Size copy_size = MinVideoFrameSize(video_frame);
+ gl->CopySubTextureCHROMIUM(source_texture, 0, GL_TEXTURE_2D, texture, 0,
+ 0, 0, 0, 0, copy_size.width(),
+ copy_size.height(), flip_y, premultiply_alpha,
+ false);
+ break;
+ }
+ }
+
gl->DeleteTextures(1, &source_texture);
gl->Flush();
@@ -832,14 +875,12 @@ bool SkCanvasVideoRenderer::CopyVideoFrameTexturesToGLTexture(
destination_gl->CreateAndConsumeTextureCHROMIUM(
mailbox_holder.texture_target, mailbox_holder.mailbox.name);
- // The video's texture might be larger than the natural size because
- // the encoder might have had to round up to the size of a macroblock.
- // Make sure to only copy the natural size to avoid putting garbage
- // into the bottom of the destination texture.
- const gfx::Size& natural_size = video_frame->natural_size();
+ // Use the minimum of the coded size and natural size to copy only the
+ // good portion of the video frame.
+ gfx::Size copy_size = MinVideoFrameSize(video_frame.get());
destination_gl->CopySubTextureCHROMIUM(
intermediate_texture, 0, GL_TEXTURE_2D, texture, 0, 0, 0, 0, 0,
- natural_size.width(), natural_size.height(), flip_y, premultiply_alpha,
+ copy_size.width(), copy_size.height(), flip_y, premultiply_alpha,
false);
destination_gl->DeleteTextures(1, &intermediate_texture);
@@ -855,8 +896,9 @@ bool SkCanvasVideoRenderer::CopyVideoFrameTexturesToGLTexture(
SyncTokenClientImpl client(canvas_gl);
video_frame->UpdateReleaseSyncToken(&client);
} else {
- CopyVideoFrameSingleTextureToGLTexture(destination_gl, video_frame.get(),
- texture, premultiply_alpha, flip_y);
+ CopyVideoFrameSingleTextureToGLTexture(
+ destination_gl, video_frame.get(), SingleFrameCopySubTexture, texture,
+ 0 /* internal_format */, 0 /* type */, premultiply_alpha, flip_y);
}
return true;
« no previous file with comments | « media/renderers/skcanvas_video_renderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698