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

Unified Diff: content/renderer/pepper/video_decoder_shim.cc

Issue 1111653004: Replace SW YUV conversion with higher quality Shader+FBO in pepper video path. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: updates to failure path in CreateShader Created 5 years, 8 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
Index: content/renderer/pepper/video_decoder_shim.cc
diff --git a/content/renderer/pepper/video_decoder_shim.cc b/content/renderer/pepper/video_decoder_shim.cc
index 35594a8e3a609ac7fbefd241b8aa3a8fe66a2b42..6d0156c15ff9fa5ec36c8480ed5678d341107060 100644
--- a/content/renderer/pepper/video_decoder_shim.cc
+++ b/content/renderer/pepper/video_decoder_shim.cc
@@ -9,6 +9,7 @@
#include <GLES2/gl2extchromium.h>
#include "base/bind.h"
+#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/single_thread_task_runner.h"
#include "cc/blink/context_provider_web_context.h"
@@ -28,6 +29,605 @@
namespace content {
+//
+// YUV->RGB converter class using a shader and FBO
+//
+class YUVConv {
+ public:
bbudge 2015/05/01 20:08:59 chromium indent of public/private is 1 space, then
+ YUVConv( const scoped_refptr<cc_blink::ContextProviderWebContext> & );
bbudge 2015/05/01 20:08:59 Chromium coding style: no space after '(', '>', an
+ ~YUVConv();
+ bool Initialize();
+ void Convert( const scoped_refptr<media::VideoFrame> & frame,
+ GLuint texOut );
bbudge 2015/05/01 20:08:59 Style: Chrome uses texture_out style rather than c
+
+ private:
+ GLuint CreateShader();
+ GLuint CompileShader( const char * name, GLuint type, const char * code );
bbudge 2015/05/01 20:08:58 s/char * name/char* name
+ GLuint CreateProgram( const char * name, GLuint vshader, GLuint fshader );
+ bool SetUniform( GLuint program, const char * name, int value );
+ bool SetUniform( GLuint program, const char * name, float value );
+ GLuint CreateTexture();
+
+ private:
bbudge 2015/05/01 20:08:59 duplicate private
+ scoped_refptr<cc_blink::ContextProviderWebContext> context_provider_;
+ gpu::gles2::GLES2Interface* gl_;
+ GLuint frame_buffer_;
+ GLuint vtx_buffer_;
+ GLuint program_;
+
+ GLuint y_texture_;
+ GLuint u_texture_;
+ GLuint v_texture_;
+
+ GLuint internal_format_;
+ GLuint format_;
+
+ GLuint y_width_;
+ GLuint y_height_;
+
+ GLuint uv_width_;
+ GLuint uv_height_;
+
+ GLfloat clamp_value_;
+ GLuint clamp_width_;
+ GLint clamp_width_loc_;
+
+ DISALLOW_COPY_AND_ASSIGN(YUVConv);
+};
+
+YUVConv::YUVConv(
+ const scoped_refptr<cc_blink::ContextProviderWebContext> & ctx_p )
bbudge 2015/05/01 20:08:59 s/ctx_p/context_provider You can use 'git cl form
+ : context_provider_( ctx_p )
+ , gl_( context_provider_->ContextGL() )
bbudge 2015/05/01 20:08:59 Chromium style puts the commas on the previous lin
+ , frame_buffer_(0)
+ , vtx_buffer_(0)
+ , program_(0)
+ , y_texture_(0)
+ , u_texture_(0)
+ , v_texture_(0)
+ , internal_format_(0)
+ , format_(0)
+ , y_width_(2)
+ , y_height_(2)
+ , uv_width_(2)
+ , uv_height_(2)
+ , clamp_value_(1.f)
+ , clamp_width_(0)
+ , clamp_width_loc_(0) {
+}
+
+YUVConv::~YUVConv() {
+ // delete textures
+ if( y_texture_ )
+ gl_->DeleteTextures( 1, &y_texture_ );
+
+ if( u_texture_ )
+ gl_->DeleteTextures( 1, &u_texture_ );
+
+ if( v_texture_ )
+ gl_->DeleteTextures( 1, &v_texture_ );
+
+ // delete framebuffer
+ if( frame_buffer_ )
+ gl_->DeleteFramebuffers( 1, &frame_buffer_ );
+
+ // delete vertex buffer
+ if( vtx_buffer_ )
+ gl_->DeleteBuffers( 1, &vtx_buffer_ );
+
+ // delete program
+ if( program_ )
+ gl_->DeleteProgram( program_ );
+}
+
+GLuint YUVConv::CreateTexture() {
+ GLuint tex = 0;
+
+ // create texture
+ gl_->GenTextures(1, &tex);
+ gl_->BindTexture(GL_TEXTURE_2D, tex);
+
+ // create texture with default size - will be resized upon first frame
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, internal_format_, 2, 2, 0, format_,
+ GL_UNSIGNED_BYTE, NULL);
+
+ // set params
+ gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ // unbind
+ gl_->BindTexture(GL_TEXTURE_2D, 0);
+
+ return tex;
+}
+
+GLuint YUVConv::CompileShader( const char * name, GLuint type,
+ const char * code ) {
+ GLuint shader = gl_->CreateShader( type );
+
+ gl_->ShaderSource(shader, 1, (const GLchar**) &code, NULL);
+ gl_->CompileShader(shader);
+
+ GLint status = 0;
+
+ gl_->GetShaderiv(shader, GL_COMPILE_STATUS, &status);
+ if(status != GL_TRUE)
+ {
+ GLint maxLength = 0;
+ gl_->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
+
+ // The maxLength includes the NULL character
+ std::string errorLog(0,maxLength);
+ gl_->GetShaderInfoLog(shader, maxLength, &maxLength, &errorLog[0]);
+
+ LOG(ERROR) << name << " shader compilation failed: "
+ << errorLog.c_str();
+ gl_->DeleteShader( shader );
+ return 0;
+ }
+
+ return shader;
+}
+
+GLuint YUVConv::CreateProgram( const char * name, GLuint vshader,
+ GLuint fshader ) {
+ GLuint program = gl_->CreateProgram();
+ gl_->AttachShader(program, vshader);
+ gl_->AttachShader(program, fshader);
+
+ // bind known vertex position
+ gl_->BindAttribLocation(program, 0, "aPosition");
+
+ gl_->LinkProgram(program);
+
+ GLint status = 0;
+
+ gl_->GetProgramiv(program, GL_LINK_STATUS, &status);
+ if(status != GL_TRUE)
+ {
+ GLint maxLength = 0;
+ gl_->GetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
+
+ // The maxLength includes the NULL character
+ std::string errorLog(0,maxLength);
+ gl_->GetProgramInfoLog(program, maxLength, &maxLength, &errorLog[0]);
+
+ LOG(ERROR) << name << " program linking failed: "
+ << errorLog.c_str();
+ return 0;
+ }
+
+ return program;
+}
+
+bool YUVConv::SetUniform( GLuint program, const char * name,
+ int value ) {
+ bool result = false;
+ GLint loc = gl_->GetUniformLocation( program, name );
+ if( loc != -1 )
+ {
+ gl_->UseProgram( program );
+ gl_->Uniform1i( loc, value );
+ gl_->UseProgram( 0 );
+ result = true;
+ }
+
+ return result;
+}
+
+bool YUVConv::SetUniform( GLuint program, const char * name,
+ float value ) {
+ bool result = false;
+ GLint loc = gl_->GetUniformLocation( program, name );
+ if( loc != -1 )
+ {
+ gl_->UseProgram( program );
+ gl_->Uniform1f( loc, value );
+ gl_->UseProgram( 0 );
+ result = true;
+ }
+
+ return result;
+}
+
+GLuint YUVConv::CreateShader() {
+ const char* vertShader =
+ "precision mediump float;\n"
+ "attribute vec2 aPosition;\n"
+ "varying vec2 vTexCoord;\n"
+ "uniform float clamp_width;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4( aPosition.xy, 0, 1 );\n"
+ // convert vertex positions to texcoords, clamp x
+ " vec2 tmp = aPosition*0.5+0.5;\n"
+ " vTexCoord = vec2(min(tmp.x, clamp_width), tmp.y);\n"
+ "}";
+
+ const char* fragShader =
+ "precision mediump float;\n"
+ "varying vec2 vTexCoord;\n"
+ "#define texSample texture2D\n"
+ "#define fragColor gl_FragColor\n"
+ "uniform sampler2D texY;\n"
+ "uniform sampler2D texU;\n"
+ "uniform sampler2D texV;\n"
+ "void main()\n"
+ "{\n"
+ // These values are magic numbers that are used in the transformation
+ // from YUV to RGB color values. They are taken from the following
+ // webpage: http://www.fourcc.org/fccyvrgb.php. In this case Rec. 601.
+ // yuv_2_rgb and yuv_adjust_constrained were taken from gl_renderer.cc
+ " const mat3 yuv_2_rgb = mat3( 1.164, 1.164, 1.164,\n"
+ " 0.0, -.391, 2.018,\n"
+ " 1.596, -.813, 0.0 );\n"
+ // These values map to 16, 128, and 128 respectively, and are computed
+ // as a fraction over 256 (e.g. 16 / 256 = 0.0625).
+ // They are used in the YUV to RGBA conversion formula:
+ // Y - 16 : Gives 16 values of head and footroom for overshooting
+ // U - 128 : Turns unsigned U into signed U [-128,127]
+ // V - 128 : Turns unsigned V into signed V [-128,127]
+ " const vec3 yuv_adjust_constrained = vec3( -0.0625, -0.5, -0.5 );\n"
+
+ " vec3 yuv = vec3( texSample(texY, vTexCoord).x,\n"
+ " texSample(texU, vTexCoord).x,\n"
+ " texSample(texV, vTexCoord).x ) +\n"
+ " yuv_adjust_constrained;\n"
+ " fragColor = vec4( yuv_2_rgb * yuv, 1.0 );\n"
+ "}";
+
+ //
+ // Compile vertex and fragment shaders.
+ //
+ GLuint vertexShader = CompileShader( "Vertex Shader", GL_VERTEX_SHADER,
+ vertShader );
+ if( !vertexShader )
+ {
+ return 0;
+ }
+
+ GLuint fragmentShader = CompileShader("Fragment Shader", GL_FRAGMENT_SHADER,
+ fragShader);
+ if( !fragmentShader )
+ {
+ gl_->DeleteShader( vertexShader );
+ return 0;
+ }
+
+ //
+ // Create the program
+ //
+ GLuint program = CreateProgram( "YUVConv Program", vertexShader,
+ fragmentShader );
+
+ // delete shaders since they are no longer needed
+ gl_->DeleteShader( vertexShader );
+ gl_->DeleteShader( fragmentShader );
+
+ if( !program )
+ {
+ return 0;
+ }
+
+ GLuint result = program;
+
+ //
+ // Bind samplers to texture units - which never change.
+ //
+ if( !SetUniform( program, "texY", 0 ) )
+ {
+ result = 0;
+ }
+ if( !SetUniform( program, "texU", 1 ) )
+ {
+ result = 0;
+ }
+ if( !SetUniform( program, "texV", 2 ) )
+ {
+ result = 0;
+ }
+
+ // set default clamp width
+ if( !SetUniform( program, "clamp_width", clamp_value_ ) )
+ {
+ result = 0;
+ }
+
+ // store clamp width loc for later
+ clamp_width_loc_ = gl_->GetUniformLocation( program, "clamp_width" );
+ if( clamp_width_loc_ < 0 )
+ {
+ result = 0;
+ }
+
+ if( !result )
+ {
+ gl_->DeleteProgram( program );
+ }
+
+ return result;
+}
+
+bool YUVConv::Initialize() {
+
+ //
+ // Determine formats to use based on whether GL_RED is available or
+ // whether we need to use GL_LUMINANCE.
+ //
+ DCHECK(gl_);
+ if( context_provider_->ContextCapabilities().gpu.texture_rg )
+ {
+ internal_format_ = GL_RED_EXT;
+ format_ = GL_RED_EXT;
+ }
+ else
+ {
+ internal_format_ = GL_LUMINANCE;
+ format_ = GL_LUMINANCE;
+ }
+
+ // set group marker
+ gl_->PushGroupMarkerEXT(0, "YUVConvContext");
+
+ //
+ // Create Framebuffer
+ //
+ gl_->GenFramebuffers(1, &frame_buffer_);
+
+ //
+ // Create some default textures to hold Y,U,V values
+ //
+ y_texture_ = CreateTexture();
+ u_texture_ = CreateTexture();
+ v_texture_ = CreateTexture();
+
+ //
+ // Create Vertex Buffer
+ //
+ // Vertex positions. Also converted to texcoords in vertex shader.
+ GLfloat vtxBuf[] = { -1.f, -1.f,
+ 1.f, -1.f,
+ -1.f, 1.f,
+ 1.f, 1.f };
+
+ // Create buffer
+ gl_->GenBuffers(1, &vtx_buffer_);
+ gl_->BindBuffer(GL_ARRAY_BUFFER, vtx_buffer_);
+ // Populate it
+ gl_->BufferData(GL_ARRAY_BUFFER, 2*sizeof( GLfloat ) * 4, vtxBuf,
+ GL_STATIC_DRAW );
+ // unbind
+ gl_->BindBuffer(GL_ARRAY_BUFFER, 0);
+
+ //
+ // Create Shader
+ //
+ program_ = CreateShader();
+
+ gl_->PopGroupMarkerEXT();
+
+ return true;
+}
+
+void YUVConv::Convert( const scoped_refptr<media::VideoFrame> & frame,
+ GLuint texOut ) {
+ int divisor_height;
+ bool supported_format = true;
+
+ // make sure we support this format
+ switch( frame->format() )
+ {
+ case media::VideoFrame::YV12: /* 420 */
+ case media::VideoFrame::I420: /* 420 */
+ divisor_height = 2;
+ break;
+
+ case media::VideoFrame::YV16: /* 422 */
+ divisor_height = 1;
+ break;
+
+ case media::VideoFrame::YV24: /* 444 */
+ divisor_height = 1;
+ break;
+
+ default:
+ // rest are not supported..
+ supported_format = false;
+ break;
+ }
+
+ // set group marker
+ gl_->PushGroupMarkerEXT(0, "YUVConvContext");
+
+ bool set_clamp = false;
+
+ uint32_t ywidth = frame->coded_size().width();
+ uint32_t yheight = frame->coded_size().height();
+
+ if( supported_format )
+ {
+ DCHECK_EQ(frame->stride(media::VideoFrame::kUPlane),
+ frame->stride(media::VideoFrame::kVPlane));
+
+ uint32_t ystride = frame->stride(media::VideoFrame::kYPlane);
+ uint32_t uvstride = frame->stride(media::VideoFrame::kUPlane);
+
+ // resize textures if necessary
+ if( ystride != y_width_ || yheight != y_height_ )
+ {
+ // choose width based on the stride
+ // then, clamp later
+ y_width_ = ystride;
+ y_height_ = yheight;
+
+ uv_width_ = uvstride;
+ uv_height_ = y_height_ / divisor_height;
+
+ if( (ystride != ywidth) || (clamp_width_ != ywidth) )
+ {
+ if( clamp_width_ != ywidth )
+ {
+ // clamp width to avoid sampling padding pixels
+ clamp_width_ = ywidth;
+ clamp_value_ = static_cast<float>( ywidth ) /
+ static_cast<float>( ystride );
+ // clamp to 1/2 pixel inside to avoid bilinear sampling errors
+ clamp_value_ -= (1.f /
+ (2.f * static_cast<float>( ystride ) ) );
+
+ set_clamp = true;
+ }
+ }
+
+ //
+ // Resize the textures and upload data
+ //
+ gl_->ActiveTexture( GL_TEXTURE0 );
+ gl_->BindTexture( GL_TEXTURE_2D, y_texture_ );
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, internal_format_, y_width_, y_height_,
+ 0, format_, GL_UNSIGNED_BYTE,
+ frame->data(media::VideoFrame::kYPlane));
+
+ gl_->ActiveTexture( GL_TEXTURE1 );
+ gl_->BindTexture( GL_TEXTURE_2D, u_texture_ );
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, internal_format_, uv_width_,
+ uv_height_, 0, format_, GL_UNSIGNED_BYTE,
+ frame->data(media::VideoFrame::kUPlane));
+
+ gl_->ActiveTexture( GL_TEXTURE2 );
+ gl_->BindTexture( GL_TEXTURE_2D, v_texture_ );
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, internal_format_, uv_width_,
+ uv_height_, 0, format_, GL_UNSIGNED_BYTE,
+ frame->data(media::VideoFrame::kVPlane));
+ }
+ else
+ {
+ //
+ // Bind textures and upload texture data
+ //
+ gl_->ActiveTexture( GL_TEXTURE0 );
+ gl_->BindTexture( GL_TEXTURE_2D, y_texture_ );
+ gl_->TexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, y_width_, y_height_,
+ format_, GL_UNSIGNED_BYTE,
+ frame->data(media::VideoFrame::kYPlane));
+
+ gl_->ActiveTexture( GL_TEXTURE1 );
+ gl_->BindTexture( GL_TEXTURE_2D, u_texture_ );
+ gl_->TexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, uv_width_, uv_height_,
+ format_, GL_UNSIGNED_BYTE,
+ frame->data(media::VideoFrame::kUPlane));
+
+ gl_->ActiveTexture( GL_TEXTURE2 );
+ gl_->BindTexture( GL_TEXTURE_2D, v_texture_ );
+ gl_->TexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, uv_width_, uv_height_,
+ format_, GL_UNSIGNED_BYTE,
+ frame->data(media::VideoFrame::kVPlane));
+ }
+ }
+ else
+ {
+ //
+ // Unsupported format - set textures to be 4x4 and produce a red output
+ // 2x2 texture didn't seem to work
+ //
+ uint8_t yudata[4*4];
+ memset( yudata, 0x5e, 4*4 );
+ gl_->ActiveTexture( GL_TEXTURE0 );
+ gl_->BindTexture( GL_TEXTURE_2D, y_texture_ );
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, internal_format_, 4, 4,
+ 0, format_, GL_UNSIGNED_BYTE, yudata );
+
+ gl_->ActiveTexture( GL_TEXTURE1 );
+ gl_->BindTexture( GL_TEXTURE_2D, u_texture_ );
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, internal_format_, 4, 4,
+ 0, format_, GL_UNSIGNED_BYTE, yudata );
+
+ uint8_t vdata[4*4];
+ memset( vdata, 0xe7, 4*4 );
+ gl_->ActiveTexture( GL_TEXTURE2 );
+ gl_->BindTexture( GL_TEXTURE_2D, v_texture_ );
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, internal_format_, 4, 4,
+ 0, format_, GL_UNSIGNED_BYTE, vdata );
+
+ if( clamp_value_ != 1.f )
+ {
+ set_clamp = true;
+ clamp_value_ = 1.f;
+ }
+ }
+
+ // since we modify the viewport, save it here
+ // MMM - is this necessary?
+ GLint viewport[4] = {0};
+ gl_->GetIntegerv( GL_VIEWPORT, viewport );
+
+ //
+ // bind framebuffer and output texture
+ //
+ gl_->BindFramebuffer(GL_FRAMEBUFFER, frame_buffer_);
+ gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, texOut, 0);
+
+#ifndef NDEBUG
+ // NOTE: we should probably check for framebuffer complete here, but that
+ // will slow this method down so check in debug mode
+ GLint status = gl_->CheckFramebufferStatus( GL_FRAMEBUFFER );
+ if( status != GL_FRAMEBUFFER_COMPLETE )
+ {
+ return;
+ }
+#endif
+
+ //
+ // Set viewport as dimensions of the video frame
+ //
+ gl_->Viewport( 0, 0, ywidth, yheight );
+
+ //
+ // Enable shader
+ //
+ gl_->UseProgram( program_ );
+
+ if( set_clamp )
+ {
+ gl_->Uniform1f( clamp_width_loc_, clamp_value_ );
+ }
+
+ //
+ // Render
+ //
+ gl_->BindBuffer(GL_ARRAY_BUFFER, vtx_buffer_);
+ gl_->EnableVertexAttribArray(0);
+ gl_->VertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat),
+ static_cast<const void *>(0));
+
+ // draw
+ gl_->DrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ // disable everything we enabled
+ gl_->BindBuffer(GL_ARRAY_BUFFER, 0);
+ gl_->DisableVertexAttribArray(0);
+ gl_->UseProgram(0);
+ gl_->BindFramebuffer( GL_FRAMEBUFFER, 0 );
+
+ // unbind textures
+ // active texture is still 2
+ gl_->BindTexture( GL_TEXTURE_2D, 0 );
+
+ gl_->ActiveTexture( GL_TEXTURE1 );
+ gl_->BindTexture( GL_TEXTURE_2D, 0 );
+
+ gl_->ActiveTexture( GL_TEXTURE0 );
+ gl_->BindTexture( GL_TEXTURE_2D, 0 );
+
+ // reset former viewport
+ gl_->Viewport( viewport[0], viewport[1], viewport[2], viewport[3] );
+
+ gl_->PopGroupMarkerEXT();
+}
+
struct VideoDecoderShim::PendingDecode {
PendingDecode(uint32_t decode_id,
const scoped_refptr<media::DecoderBuffer>& buffer);
@@ -49,14 +649,11 @@ VideoDecoderShim::PendingDecode::~PendingDecode() {
struct VideoDecoderShim::PendingFrame {
explicit PendingFrame(uint32_t decode_id);
PendingFrame(uint32_t decode_id,
- const gfx::Size& coded_size,
- const gfx::Rect& visible_rect);
+ const scoped_refptr<media::VideoFrame>& frame);
~PendingFrame();
const uint32_t decode_id;
- const gfx::Size coded_size;
- const gfx::Rect visible_rect;
- std::vector<uint8_t> argb_pixels;
+ scoped_refptr<media::VideoFrame> video_frame;
private:
// This could be expensive to copy, so guard against that.
@@ -68,12 +665,9 @@ VideoDecoderShim::PendingFrame::PendingFrame(uint32_t decode_id)
}
VideoDecoderShim::PendingFrame::PendingFrame(uint32_t decode_id,
- const gfx::Size& coded_size,
- const gfx::Rect& visible_rect)
+ const scoped_refptr<media::VideoFrame>& frame)
: decode_id(decode_id),
- coded_size(coded_size),
- visible_rect(visible_rect),
- argb_pixels(coded_size.width() * coded_size.height() * 4) {
+ video_frame(frame) {
}
VideoDecoderShim::PendingFrame::~PendingFrame() {
@@ -269,13 +863,7 @@ void VideoDecoderShim::DecoderImpl::OnOutputComplete(
scoped_ptr<PendingFrame> pending_frame;
if (!frame->end_of_stream()) {
- pending_frame.reset(new PendingFrame(
- decode_id_, frame->coded_size(), frame->visible_rect()));
- // Convert the VideoFrame pixels to ABGR to match VideoDecodeAccelerator.
- media::SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels(
- frame,
- &pending_frame->argb_pixels.front(),
- frame->coded_size().width() * 4);
+ pending_frame.reset(new PendingFrame( decode_id_, frame ) );
} else {
pending_frame.reset(new PendingFrame(decode_id_));
}
@@ -305,6 +893,7 @@ VideoDecoderShim::VideoDecoderShim(PepperVideoDecoderHost* host)
DCHECK(media_task_runner_.get());
DCHECK(context_provider_.get());
decoder_impl_.reset(new DecoderImpl(weak_ptr_factory_.GetWeakPtr()));
+ yuv_converter_.reset(new YUVConv( context_provider_ ));
}
VideoDecoderShim::~VideoDecoderShim() {
@@ -343,6 +932,12 @@ bool VideoDecoderShim::Initialize(
codec = media::kCodecVP9;
DCHECK_NE(codec, media::kUnknownVideoCodec);
+ // initialize yuv converter
+ if( !yuv_converter_->Initialize() )
+ {
+ return false;
+ }
+
media::VideoDecoderConfig config(
codec,
profile,
@@ -471,12 +1066,12 @@ void VideoDecoderShim::OnDecodeComplete(int32_t result, uint32_t decode_id) {
NotifyCompletedDecodes();
}
-void VideoDecoderShim::OnOutputComplete(scoped_ptr<PendingFrame> frame) {
+void VideoDecoderShim::OnOutputComplete(scoped_ptr<PendingFrame> pframe) {
DCHECK(RenderThreadImpl::current());
DCHECK(host_);
- if (!frame->argb_pixels.empty()) {
- if (texture_size_ != frame->coded_size) {
+ if ( pframe->video_frame ) {
+ if (texture_size_ != pframe->video_frame->coded_size()) {
// If the size has changed, all current textures must be dismissed. Add
// all textures to |textures_to_dismiss_| and dismiss any that aren't in
// use by the plugin. We will dismiss the rest as they are recycled.
@@ -498,13 +1093,13 @@ void VideoDecoderShim::OnOutputComplete(scoped_ptr<PendingFrame> frame) {
pending_texture_mailboxes_.push_back(gpu::Mailbox::Generate());
host_->RequestTextures(texture_pool_size_,
- frame->coded_size,
+ pframe->video_frame->coded_size(),
GL_TEXTURE_2D,
pending_texture_mailboxes_);
- texture_size_ = frame->coded_size;
+ texture_size_ = pframe->video_frame->coded_size();
}
- pending_frames_.push(linked_ptr<PendingFrame>(frame.release()));
+ pending_frames_.push(linked_ptr<PendingFrame>(pframe.release()));
SendPictures();
}
}
@@ -520,27 +1115,13 @@ void VideoDecoderShim::SendPictures() {
available_textures_.erase(it);
uint32_t local_texture_id = texture_id_map_[texture_id];
- gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
- gles2->ActiveTexture(GL_TEXTURE0);
- gles2->BindTexture(GL_TEXTURE_2D, local_texture_id);
-#if !defined(OS_ANDROID)
- // BGRA is the native texture format, except on Android, where textures
- // would be uploaded as GL_RGBA.
- gles2->TexImage2D(GL_TEXTURE_2D,
- 0,
- GL_BGRA_EXT,
- texture_size_.width(),
- texture_size_.height(),
- 0,
- GL_BGRA_EXT,
- GL_UNSIGNED_BYTE,
- &frame->argb_pixels.front());
-#else
-#error Not implemented.
-#endif
+
+ // run the yuv conversion renderer
+ yuv_converter_->Convert( frame->video_frame, local_texture_id );
host_->PictureReady(media::Picture(texture_id, frame->decode_id,
- frame->visible_rect, false));
+ frame->video_frame->visible_rect(),
+ false));
pending_frames_.pop();
}
« content/renderer/pepper/video_decoder_shim.h ('K') | « content/renderer/pepper/video_decoder_shim.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698