diff options
Diffstat (limited to 'ppapi/examples')
-rw-r--r-- | ppapi/examples/video_decode/video_decode.cc | 172 |
1 files changed, 125 insertions, 47 deletions
diff --git a/ppapi/examples/video_decode/video_decode.cc b/ppapi/examples/video_decode/video_decode.cc index 6e4f4e1..4e3354a 100644 --- a/ppapi/examples/video_decode/video_decode.cc +++ b/ppapi/examples/video_decode/video_decode.cc @@ -24,6 +24,7 @@ #include "ppapi/cpp/var.h" #include "ppapi/examples/video_decode/testdata.h" #include "ppapi/lib/gl/include/GLES2/gl2.h" +#include "ppapi/lib/gl/include/GLES2/gl2ext.h" #include "ppapi/utility/completion_callback_factory.h" // Use assert as a poor-man's CHECK, even in non-debug mode. @@ -39,6 +40,19 @@ namespace { +struct PictureBufferInfo { + PP_PictureBuffer_Dev buffer; + GLenum texture_target; +}; + +struct Shader { + Shader() : program(0), + texcoord_scale_location(0) {} + + GLuint program; + GLint texcoord_scale_location; +}; + class VideoDecodeDemoInstance : public pp::Instance, public pp::Graphics3DClient, public pp::VideoDecoderClient_Dev { @@ -90,7 +104,7 @@ class VideoDecodeDemoInstance : public pp::Instance, uint32_t texture_target); void DismissPictureBuffer(int32_t picture_buffer_id); - const PP_PictureBuffer_Dev& GetPictureBufferById(int id); + const PictureBufferInfo& GetPictureBufferInfoById(int id); pp::VideoDecoder_Dev* decoder() { return decoder_; } private: @@ -107,7 +121,7 @@ class VideoDecodeDemoInstance : public pp::Instance, size_t encoded_data_next_pos_to_decode_; std::set<int> bitstream_ids_at_decoder_; // Map of texture buffers indexed by buffer id. - typedef std::map<int, PP_PictureBuffer_Dev> PictureBufferMap; + typedef std::map<int, PictureBufferInfo> PictureBufferMap; PictureBufferMap picture_buffers_by_id_; // Map of bitstream buffers indexed by id. typedef std::map<int, pp::Buffer_Dev*> BitstreamBufferMap; @@ -119,8 +133,10 @@ class VideoDecodeDemoInstance : public pp::Instance, // GL-related functions. void InitGL(); - GLuint CreateTexture(int32_t width, int32_t height); + GLuint CreateTexture(int32_t width, int32_t height, GLenum texture_target); void CreateGLObjects(); + Shader CreateProgram(const char* vertex_shader, + const char* fragment_shader); void CreateShader(GLuint program, GLenum type, const char* source, int size); void DeleteTexture(GLuint id); void PaintFinished(int32_t result, PP_Resource decoder, @@ -168,6 +184,11 @@ class VideoDecodeDemoInstance : public pp::Instance, pp::Graphics3D* context_; typedef std::map<int, DecoderClient*> Decoders; Decoders video_decoders_; + + // Shader program to draw GL_TEXTURE_2D target. + Shader shader_2d_; + // Shader program to draw GL_TEXTURE_RECTANGLE_ARB target. + Shader shader_rectangle_arb_; }; VideoDecodeDemoInstance::DecoderClient::DecoderClient( @@ -189,7 +210,7 @@ VideoDecodeDemoInstance::DecoderClient::~DecoderClient() { for (PictureBufferMap::iterator it = picture_buffers_by_id_.begin(); it != picture_buffers_by_id_.end(); ++it) { - gles2_->DeleteTexture(it->second.texture_id); + gles2_->DeleteTexture(it->second.buffer.texture_id); } picture_buffers_by_id_.clear(); } @@ -212,6 +233,13 @@ VideoDecodeDemoInstance::VideoDecodeDemoInstance(PP_Instance instance, } VideoDecodeDemoInstance::~VideoDecodeDemoInstance() { + if (shader_2d_.program) + gles2_if_->DeleteProgram(context_->pp_resource(), shader_2d_.program); + if (shader_rectangle_arb_.program) { + gles2_if_->DeleteProgram( + context_->pp_resource(), shader_rectangle_arb_.program); + } + for (Decoders::iterator it = video_decoders_.begin(); it != video_decoders_.end(); ++it) { delete it->second; @@ -337,24 +365,23 @@ void VideoDecodeDemoInstance::DecoderClient::ProvidePictureBuffers( uint32_t req_num_of_bufs, PP_Size dimensions, uint32_t texture_target) { - // TODO(sail): Add support for GL_TEXTURE_RECTANGLE_ARB. - assert(texture_target == GL_TEXTURE_2D); std::vector<PP_PictureBuffer_Dev> buffers; for (uint32_t i = 0; i < req_num_of_bufs; ++i) { - PP_PictureBuffer_Dev buffer; - buffer.size = dimensions; - buffer.texture_id = - gles2_->CreateTexture(dimensions.width, dimensions.height); + PictureBufferInfo info; + info.buffer.size = dimensions; + info.texture_target = texture_target; + info.buffer.texture_id = gles2_->CreateTexture( + dimensions.width, dimensions.height, info.texture_target); int id = ++next_picture_buffer_id_; - buffer.id = id; - buffers.push_back(buffer); - assert(picture_buffers_by_id_.insert(std::make_pair(id, buffer)).second); + info.buffer.id = id; + buffers.push_back(info.buffer); + assert(picture_buffers_by_id_.insert(std::make_pair(id, info)).second); } decoder_->AssignPictureBuffers(buffers); } -const PP_PictureBuffer_Dev& -VideoDecodeDemoInstance::DecoderClient::GetPictureBufferById( +const PictureBufferInfo& +VideoDecodeDemoInstance::DecoderClient::GetPictureBufferInfoById( int id) { PictureBufferMap::iterator it = picture_buffers_by_id_.find(id); assert(it != picture_buffers_by_id_.end()); @@ -370,7 +397,8 @@ void VideoDecodeDemoInstance::DismissPictureBuffer(PP_Resource decoder, void VideoDecodeDemoInstance::DecoderClient::DismissPictureBuffer( int32_t picture_buffer_id) { - gles2_->DeleteTexture(GetPictureBufferById(picture_buffer_id).texture_id); + gles2_->DeleteTexture(GetPictureBufferInfoById( + picture_buffer_id).buffer.texture_id); picture_buffers_by_id_.erase(picture_buffer_id); } @@ -384,8 +412,8 @@ void VideoDecodeDemoInstance::PictureReady(PP_Resource decoder, } DecoderClient* client = video_decoders_[decoder]; assert(client); - const PP_PictureBuffer_Dev& buffer = - client->GetPictureBufferById(picture.picture_buffer_id); + const PictureBufferInfo& info = + client->GetPictureBufferInfoById(picture.picture_buffer_id); assert(!is_painting_); is_painting_ = true; int x = 0; @@ -395,16 +423,33 @@ void VideoDecodeDemoInstance::PictureReady(PP_Resource decoder, y = plugin_size_.height() / kNumDecoders; } + if (info.texture_target == GL_TEXTURE_2D) { + gles2_if_->UseProgram(context_->pp_resource(), shader_2d_.program); + gles2_if_->Uniform2f( + context_->pp_resource(), shader_2d_.texcoord_scale_location, 1.0, 1.0); + } else { + assert(info.texture_target == GL_TEXTURE_RECTANGLE_ARB); + gles2_if_->UseProgram( + context_->pp_resource(), shader_rectangle_arb_.program); + gles2_if_->Uniform2f(context_->pp_resource(), + shader_rectangle_arb_.texcoord_scale_location, + info.buffer.size.width, + info.buffer.size.height); + } + gles2_if_->Viewport(context_->pp_resource(), x, y, plugin_size_.width() / kNumDecoders, plugin_size_.height() / kNumDecoders); gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0); gles2_if_->BindTexture( - context_->pp_resource(), GL_TEXTURE_2D, buffer.texture_id); + context_->pp_resource(), info.texture_target, info.buffer.texture_id); gles2_if_->DrawArrays(context_->pp_resource(), GL_TRIANGLE_STRIP, 0, 4); + + gles2_if_->UseProgram(context_->pp_resource(), 0); + pp::CompletionCallback cb = callback_factory_.NewCallback( - &VideoDecodeDemoInstance::PaintFinished, decoder, buffer.id); + &VideoDecodeDemoInstance::PaintFinished, decoder, info.buffer.id); last_swap_request_ticks_ = core_if_->GetTimeTicks(); assert(context_->SwapBuffers(cb) == PP_OK_COMPLETIONPENDING); } @@ -483,29 +528,33 @@ void VideoDecodeDemoInstance::PaintFinished(int32_t result, PP_Resource decoder, } } -GLuint VideoDecodeDemoInstance::CreateTexture(int32_t width, int32_t height) { +GLuint VideoDecodeDemoInstance::CreateTexture(int32_t width, + int32_t height, + GLenum texture_target) { GLuint texture_id; gles2_if_->GenTextures(context_->pp_resource(), 1, &texture_id); assertNoGLError(); // Assign parameters. gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0); - gles2_if_->BindTexture(context_->pp_resource(), GL_TEXTURE_2D, texture_id); + gles2_if_->BindTexture(context_->pp_resource(), texture_target, texture_id); gles2_if_->TexParameteri( - context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + context_->pp_resource(), texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); gles2_if_->TexParameteri( - context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + context_->pp_resource(), texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); gles2_if_->TexParameterf( - context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + context_->pp_resource(), texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); gles2_if_->TexParameterf( - context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, + context_->pp_resource(), texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - gles2_if_->TexImage2D( - context_->pp_resource(), GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); + if (texture_target == GL_TEXTURE_2D) { + gles2_if_->TexImage2D( + context_->pp_resource(), texture_target, 0, GL_RGBA, width, height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + } assertNoGLError(); return texture_id; } @@ -520,13 +569,14 @@ void VideoDecodeDemoInstance::CreateGLObjects() { "varying vec2 v_texCoord; \n" "attribute vec4 a_position; \n" "attribute vec2 a_texCoord; \n" + "uniform vec2 v_scale; \n" "void main() \n" "{ \n" - " v_texCoord = a_texCoord; \n" + " v_texCoord = v_scale * a_texCoord; \n" " gl_Position = a_position; \n" "}"; - static const char kFragmentShader[] = + static const char kFragmentShader2D[] = "precision mediump float; \n" "varying vec2 v_texCoord; \n" "uniform sampler2D s_texture; \n" @@ -535,38 +585,63 @@ void VideoDecodeDemoInstance::CreateGLObjects() { " gl_FragColor = texture2D(s_texture, v_texCoord); \n" "}"; - // Create shader program. - GLuint program = gles2_if_->CreateProgram(context_->pp_resource()); - CreateShader(program, GL_VERTEX_SHADER, kVertexShader, sizeof(kVertexShader)); - CreateShader( - program, GL_FRAGMENT_SHADER, kFragmentShader, sizeof(kFragmentShader)); - gles2_if_->LinkProgram(context_->pp_resource(), program); - gles2_if_->UseProgram(context_->pp_resource(), program); - gles2_if_->DeleteProgram(context_->pp_resource(), program); - gles2_if_->Uniform1i( - context_->pp_resource(), - gles2_if_->GetUniformLocation( - context_->pp_resource(), program, "s_texture"), 0); - assertNoGLError(); + static const char kFragmentShaderRectangle[] = + "#extension GL_ARB_texture_rectangle : require\n" + "precision mediump float; \n" + "varying vec2 v_texCoord; \n" + "uniform sampler2DRect s_texture; \n" + "void main() \n" + "{" + " gl_FragColor = texture2DRect(s_texture, v_texCoord).rgba; \n" + "}"; // Assign vertex positions and texture coordinates to buffers for use in // shader program. static const float kVertices[] = { -1, 1, -1, -1, 1, 1, 1, -1, // Position coordinates. - 0, 1, 0, 0, 1, 1, 1, 0, // Texture coordinates. + 0, 1, 0, 0, 1, 1, 1, 0, // Texture coordinates. }; GLuint buffer; gles2_if_->GenBuffers(context_->pp_resource(), 1, &buffer); gles2_if_->BindBuffer(context_->pp_resource(), GL_ARRAY_BUFFER, buffer); + gles2_if_->BufferData(context_->pp_resource(), GL_ARRAY_BUFFER, sizeof(kVertices), kVertices, GL_STATIC_DRAW); assertNoGLError(); + + shader_2d_ = CreateProgram(kVertexShader, kFragmentShader2D); + shader_rectangle_arb_ = + CreateProgram(kVertexShader, kFragmentShaderRectangle); +} + +Shader VideoDecodeDemoInstance::CreateProgram(const char* vertex_shader, + const char* fragment_shader) { + Shader shader; + + // Create shader program. + shader.program = gles2_if_->CreateProgram(context_->pp_resource()); + CreateShader(shader.program, GL_VERTEX_SHADER, vertex_shader, + strlen(vertex_shader)); + CreateShader(shader.program, GL_FRAGMENT_SHADER, fragment_shader, + strlen(fragment_shader)); + gles2_if_->LinkProgram(context_->pp_resource(), shader.program); + gles2_if_->UseProgram(context_->pp_resource(), shader.program); + gles2_if_->Uniform1i( + context_->pp_resource(), + gles2_if_->GetUniformLocation( + context_->pp_resource(), shader.program, "s_texture"), 0); + assertNoGLError(); + + shader.texcoord_scale_location = gles2_if_->GetUniformLocation( + context_->pp_resource(), shader.program, "v_scale"); + GLint pos_location = gles2_if_->GetAttribLocation( - context_->pp_resource(), program, "a_position"); + context_->pp_resource(), shader.program, "a_position"); GLint tc_location = gles2_if_->GetAttribLocation( - context_->pp_resource(), program, "a_texCoord"); + context_->pp_resource(), shader.program, "a_texCoord"); assertNoGLError(); + gles2_if_->EnableVertexAttribArray(context_->pp_resource(), pos_location); gles2_if_->VertexAttribPointer(context_->pp_resource(), pos_location, 2, GL_FLOAT, GL_FALSE, 0, 0); @@ -574,7 +649,10 @@ void VideoDecodeDemoInstance::CreateGLObjects() { gles2_if_->VertexAttribPointer( context_->pp_resource(), tc_location, 2, GL_FLOAT, GL_FALSE, 0, static_cast<float*>(0) + 8); // Skip position coordinates. + + gles2_if_->UseProgram(context_->pp_resource(), 0); assertNoGLError(); + return shader; } void VideoDecodeDemoInstance::CreateShader( |