Commit a39616ca authored by bbudge@chromium.org's avatar bbudge@chromium.org

Pepper: Add GL_TEXTURE_EXTERNAL_OES texture target to PPB_VideoDecoder docs and example.

GL_TEXTURE_2D is used by x86 non-OSX platforms and by software fallback.
GL_TEXTURE_RECTANGLE_ARB will be used on OSX hardware.
GL_TEXTURE_EXTERNAL_OES is used on ARM ChromeOS.

BUG=281689

Review URL: https://codereview.chromium.org/354763003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282674 0039d316-1c4b-4281-b951-d872f2087c98
parent 21829851
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#define USE_VP8_TESTDATA_INSTEAD_OF_H264 #define USE_VP8_TESTDATA_INSTEAD_OF_H264
#include "testdata.h" #include "testdata.h"
// Use assert as a poor-man's CHECK, even in non-debug mode. // Use assert as a poor-man's CHECK, even in non-debug mode.
// Since <assert.h> redefines assert on every inclusion (it doesn't use // Since <assert.h> redefines assert on every inclusion (it doesn't use
// include-guards), make sure this is the last file #include'd in this file. // include-guards), make sure this is the last file #include'd in this file.
...@@ -113,6 +112,7 @@ class MyInstance : public pp::Instance, public pp::Graphics3DClient { ...@@ -113,6 +112,7 @@ class MyInstance : public pp::Instance, public pp::Graphics3DClient {
void CreateGLObjects(); void CreateGLObjects();
void Create2DProgramOnce(); void Create2DProgramOnce();
void CreateRectangleARBProgramOnce(); void CreateRectangleARBProgramOnce();
void CreateExternalOESProgramOnce();
Shader CreateProgram(const char* vertex_shader, const char* fragment_shader); Shader CreateProgram(const char* vertex_shader, const char* fragment_shader);
void CreateShader(GLuint program, GLenum type, const char* source, int size); void CreateShader(GLuint program, GLenum type, const char* source, int size);
void PaintNextPicture(); void PaintNextPicture();
...@@ -145,6 +145,8 @@ class MyInstance : public pp::Instance, public pp::Graphics3DClient { ...@@ -145,6 +145,8 @@ class MyInstance : public pp::Instance, public pp::Graphics3DClient {
Shader shader_2d_; Shader shader_2d_;
// Shader program to draw GL_TEXTURE_RECTANGLE_ARB target. // Shader program to draw GL_TEXTURE_RECTANGLE_ARB target.
Shader shader_rectangle_arb_; Shader shader_rectangle_arb_;
// Shader program to draw GL_TEXTURE_EXTERNAL_OES target.
Shader shader_external_oes_;
}; };
class Decoder { class Decoder {
...@@ -159,6 +161,10 @@ class Decoder { ...@@ -159,6 +161,10 @@ class Decoder {
void Reset(); void Reset();
void RecyclePicture(const PP_VideoPicture& picture); void RecyclePicture(const PP_VideoPicture& picture);
PP_TimeTicks GetAverageLatency() {
return num_pictures_ ? total_latency_ / num_pictures_ : 0;
}
private: private:
void InitializeDone(int32_t result); void InitializeDone(int32_t result);
void Start(); void Start();
...@@ -178,6 +184,12 @@ class Decoder { ...@@ -178,6 +184,12 @@ class Decoder {
int next_picture_id_; int next_picture_id_;
bool flushing_; bool flushing_;
bool resetting_; bool resetting_;
const PPB_Core* core_if_;
static const int kMaxDecodeDelay = 128;
PP_TimeTicks decode_time_[kMaxDecodeDelay];
PP_TimeTicks total_latency_;
int num_pictures_;
}; };
#if defined USE_VP8_TESTDATA_INSTEAD_OF_H264 #if defined USE_VP8_TESTDATA_INSTEAD_OF_H264
...@@ -227,7 +239,12 @@ Decoder::Decoder(MyInstance* instance, ...@@ -227,7 +239,12 @@ Decoder::Decoder(MyInstance* instance,
encoded_data_next_pos_to_decode_(0), encoded_data_next_pos_to_decode_(0),
next_picture_id_(0), next_picture_id_(0),
flushing_(false), flushing_(false),
resetting_(false) { resetting_(false),
total_latency_(0.0),
num_pictures_(0) {
core_if_ = static_cast<const PPB_Core*>(
pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE));
#if defined USE_VP8_TESTDATA_INSTEAD_OF_H264 #if defined USE_VP8_TESTDATA_INSTEAD_OF_H264
const PP_VideoProfile kBitstreamProfile = PP_VIDEOPROFILE_VP8MAIN; const PP_VideoProfile kBitstreamProfile = PP_VIDEOPROFILE_VP8MAIN;
#else #else
...@@ -295,6 +312,7 @@ void Decoder::DecodeNextFrame() { ...@@ -295,6 +312,7 @@ void Decoder::DecodeNextFrame() {
// Decode the frame. On completion, DecodeDone will call DecodeNextFrame // Decode the frame. On completion, DecodeDone will call DecodeNextFrame
// to implement a decode loop. // to implement a decode loop.
uint32_t size = static_cast<uint32_t>(end_pos - start_pos); uint32_t size = static_cast<uint32_t>(end_pos - start_pos);
decode_time_[next_picture_id_ % kMaxDecodeDelay] = core_if_->GetTimeTicks();
decoder_->Decode(next_picture_id_++, decoder_->Decode(next_picture_id_++,
size, size,
kData + start_pos, kData + start_pos,
...@@ -318,6 +336,12 @@ void Decoder::PictureReady(int32_t result, PP_VideoPicture picture) { ...@@ -318,6 +336,12 @@ void Decoder::PictureReady(int32_t result, PP_VideoPicture picture) {
if (result == PP_ERROR_ABORTED) if (result == PP_ERROR_ABORTED)
return; return;
assert(result == PP_OK); assert(result == PP_OK);
num_pictures_++;
PP_TimeTicks latency = core_if_->GetTimeTicks() -
decode_time_[picture.decode_id % kMaxDecodeDelay];
total_latency_ += latency;
decoder_->GetPicture( decoder_->GetPicture(
callback_factory_.NewCallbackWithOutput(&Decoder::PictureReady)); callback_factory_.NewCallbackWithOutput(&Decoder::PictureReady));
instance_->PaintPicture(this, picture); instance_->PaintPicture(this, picture);
...@@ -349,12 +373,13 @@ MyInstance::MyInstance(PP_Instance instance, pp::Module* module) ...@@ -349,12 +373,13 @@ MyInstance::MyInstance(PP_Instance instance, pp::Module* module)
swap_ticks_(0), swap_ticks_(0),
callback_factory_(this), callback_factory_(this),
context_(NULL) { context_(NULL) {
assert((console_if_ = static_cast<const PPB_Console*>( console_if_ = static_cast<const PPB_Console*>(
module->GetBrowserInterface(PPB_CONSOLE_INTERFACE)))); pp::Module::Get()->GetBrowserInterface(PPB_CONSOLE_INTERFACE));
assert((core_if_ = static_cast<const PPB_Core*>( core_if_ = static_cast<const PPB_Core*>(
module->GetBrowserInterface(PPB_CORE_INTERFACE)))); pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE));
assert((gles2_if_ = static_cast<const PPB_OpenGLES2*>( gles2_if_ = static_cast<const PPB_OpenGLES2*>(
module->GetBrowserInterface(PPB_OPENGLES2_INTERFACE)))); pp::Module::Get()->GetBrowserInterface(PPB_OPENGLES2_INTERFACE));
RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE); RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE);
} }
...@@ -367,6 +392,8 @@ MyInstance::~MyInstance() { ...@@ -367,6 +392,8 @@ MyInstance::~MyInstance() {
gles2_if_->DeleteProgram(graphics_3d, shader_2d_.program); gles2_if_->DeleteProgram(graphics_3d, shader_2d_.program);
if (shader_rectangle_arb_.program) if (shader_rectangle_arb_.program)
gles2_if_->DeleteProgram(graphics_3d, shader_rectangle_arb_.program); gles2_if_->DeleteProgram(graphics_3d, shader_rectangle_arb_.program);
if (shader_external_oes_.program)
gles2_if_->DeleteProgram(graphics_3d, shader_external_oes_.program);
for (DecoderList::iterator it = video_decoders_.begin(); for (DecoderList::iterator it = video_decoders_.begin();
it != video_decoders_.end(); it != video_decoders_.end();
...@@ -455,14 +482,19 @@ void MyInstance::PaintNextPicture() { ...@@ -455,14 +482,19 @@ void MyInstance::PaintNextPicture() {
gles2_if_->UseProgram(graphics_3d, shader_2d_.program); gles2_if_->UseProgram(graphics_3d, shader_2d_.program);
gles2_if_->Uniform2f( gles2_if_->Uniform2f(
graphics_3d, shader_2d_.texcoord_scale_location, 1.0, 1.0); graphics_3d, shader_2d_.texcoord_scale_location, 1.0, 1.0);
} else { } else if (picture.texture_target == GL_TEXTURE_RECTANGLE_ARB) {
assert(picture.texture_target == GL_TEXTURE_RECTANGLE_ARB);
CreateRectangleARBProgramOnce(); CreateRectangleARBProgramOnce();
gles2_if_->UseProgram(graphics_3d, shader_rectangle_arb_.program); gles2_if_->UseProgram(graphics_3d, shader_rectangle_arb_.program);
gles2_if_->Uniform2f(graphics_3d, gles2_if_->Uniform2f(graphics_3d,
shader_rectangle_arb_.texcoord_scale_location, shader_rectangle_arb_.texcoord_scale_location,
picture.texture_size.width, picture.texture_size.width,
picture.texture_size.height); picture.texture_size.height);
} else {
assert(picture.texture_target == GL_TEXTURE_EXTERNAL_OES);
CreateExternalOESProgramOnce();
gles2_if_->UseProgram(graphics_3d, shader_external_oes_.program);
gles2_if_->Uniform2f(
graphics_3d, shader_external_oes_.texcoord_scale_location, 1.0, 1.0);
} }
gles2_if_->Viewport(graphics_3d, x, y, half_width, half_height); gles2_if_->Viewport(graphics_3d, x, y, half_width, half_height);
...@@ -487,9 +519,18 @@ void MyInstance::PaintFinished(int32_t result) { ...@@ -487,9 +519,18 @@ void MyInstance::PaintFinished(int32_t result) {
double elapsed = core_if_->GetTimeTicks() - first_frame_delivered_ticks_; double elapsed = core_if_->GetTimeTicks() - first_frame_delivered_ticks_;
double fps = (elapsed > 0) ? num_frames_rendered_ / elapsed : 1000; double fps = (elapsed > 0) ? num_frames_rendered_ / elapsed : 1000;
double ms_per_swap = (swap_ticks_ * 1e3) / num_frames_rendered_; double ms_per_swap = (swap_ticks_ * 1e3) / num_frames_rendered_;
double secs_average_latency = 0;
for (DecoderList::iterator it = video_decoders_.begin();
it != video_decoders_.end();
++it)
secs_average_latency += (*it)->GetAverageLatency();
secs_average_latency /= video_decoders_.size();
double ms_average_latency = 1000 * secs_average_latency;
LogError(this).s() << "Rendered frames: " << num_frames_rendered_ LogError(this).s() << "Rendered frames: " << num_frames_rendered_
<< ", fps: " << fps << ", fps: " << fps
<< ", with average ms/swap of: " << ms_per_swap; << ", with average ms/swap of: " << ms_per_swap
<< ", with average latency (ms) of: "
<< ms_average_latency;
} }
// If the decoders were reset, this will be empty. // If the decoders were reset, this will be empty.
...@@ -542,8 +583,8 @@ void MyInstance::CreateGLObjects() { ...@@ -542,8 +583,8 @@ void MyInstance::CreateGLObjects() {
// Assign vertex positions and texture coordinates to buffers for use in // Assign vertex positions and texture coordinates to buffers for use in
// shader program. // shader program.
static const float kVertices[] = { static const float kVertices[] = {
-1, 1, -1, -1, 1, 1, 1, -1, // Position coordinates. -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; GLuint buffer;
...@@ -598,6 +639,23 @@ void MyInstance::CreateRectangleARBProgramOnce() { ...@@ -598,6 +639,23 @@ void MyInstance::CreateRectangleARBProgramOnce() {
"}"; "}";
shader_rectangle_arb_ = shader_rectangle_arb_ =
CreateProgram(kVertexShader, kFragmentShaderRectangle); CreateProgram(kVertexShader, kFragmentShaderRectangle);
assertNoGLError();
}
void MyInstance::CreateExternalOESProgramOnce() {
if (shader_external_oes_.program)
return;
static const char kFragmentShaderExternal[] =
"#extension GL_OES_EGL_image_external : require\n"
"precision mediump float; \n"
"varying vec2 v_texCoord; \n"
"uniform samplerExternalOES s_texture; \n"
"void main() \n"
"{"
" gl_FragColor = texture2D(s_texture, v_texCoord); \n"
"}";
shader_external_oes_ = CreateProgram(kVertexShader, kFragmentShaderExternal);
assertNoGLError();
} }
Shader MyInstance::CreateProgram(const char* vertex_shader, Shader MyInstance::CreateProgram(const char* vertex_shader,
......
...@@ -43,8 +43,9 @@ struct PP_VideoPicture { ...@@ -43,8 +43,9 @@ struct PP_VideoPicture {
/** /**
* The GL texture target for the decoded picture. Possible values are: * The GL texture target for the decoded picture. Possible values are:
* GL_TEXTURE_2D (normalized texture coordinates) * GL_TEXTURE_2D
* GL_TEXTURE_RECTANGLE_ARB (dimension dependent texture coordinates) * GL_TEXTURE_RECTANGLE_ARB
* GL_TEXTURE_EXTERNAL_OES
* *
* The pixel format of the texture is GL_RGBA. * The pixel format of the texture is GL_RGBA.
*/ */
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
/* From pp_codecs.idl modified Tue Jun 10 13:32:45 2014. */ /* From pp_codecs.idl modified Mon Jun 30 14:36:36 2014. */
#ifndef PPAPI_C_PP_CODECS_H_ #ifndef PPAPI_C_PP_CODECS_H_
#define PPAPI_C_PP_CODECS_H_ #define PPAPI_C_PP_CODECS_H_
...@@ -64,8 +64,9 @@ struct PP_VideoPicture { ...@@ -64,8 +64,9 @@ struct PP_VideoPicture {
uint32_t texture_id; uint32_t texture_id;
/** /**
* The GL texture target for the decoded picture. Possible values are: * The GL texture target for the decoded picture. Possible values are:
* GL_TEXTURE_2D (normalized texture coordinates) * GL_TEXTURE_2D
* GL_TEXTURE_RECTANGLE_ARB (dimension dependent texture coordinates) * GL_TEXTURE_RECTANGLE_ARB
* GL_TEXTURE_EXTERNAL_OES
* *
* The pixel format of the texture is GL_RGBA. * The pixel format of the texture is GL_RGBA.
*/ */
......
...@@ -113,6 +113,7 @@ class MyInstance : public pp::Instance, public pp::Graphics3DClient { ...@@ -113,6 +113,7 @@ class MyInstance : public pp::Instance, public pp::Graphics3DClient {
void CreateGLObjects(); void CreateGLObjects();
void Create2DProgramOnce(); void Create2DProgramOnce();
void CreateRectangleARBProgramOnce(); void CreateRectangleARBProgramOnce();
void CreateExternalOESProgramOnce();
Shader CreateProgram(const char* vertex_shader, const char* fragment_shader); Shader CreateProgram(const char* vertex_shader, const char* fragment_shader);
void CreateShader(GLuint program, GLenum type, const char* source, int size); void CreateShader(GLuint program, GLenum type, const char* source, int size);
void PaintNextPicture(); void PaintNextPicture();
...@@ -145,6 +146,8 @@ class MyInstance : public pp::Instance, public pp::Graphics3DClient { ...@@ -145,6 +146,8 @@ class MyInstance : public pp::Instance, public pp::Graphics3DClient {
Shader shader_2d_; Shader shader_2d_;
// Shader program to draw GL_TEXTURE_RECTANGLE_ARB target. // Shader program to draw GL_TEXTURE_RECTANGLE_ARB target.
Shader shader_rectangle_arb_; Shader shader_rectangle_arb_;
// Shader program to draw GL_TEXTURE_EXTERNAL_OES target.
Shader shader_external_oes_;
}; };
class Decoder { class Decoder {
...@@ -390,6 +393,8 @@ MyInstance::~MyInstance() { ...@@ -390,6 +393,8 @@ MyInstance::~MyInstance() {
gles2_if_->DeleteProgram(graphics_3d, shader_2d_.program); gles2_if_->DeleteProgram(graphics_3d, shader_2d_.program);
if (shader_rectangle_arb_.program) if (shader_rectangle_arb_.program)
gles2_if_->DeleteProgram(graphics_3d, shader_rectangle_arb_.program); gles2_if_->DeleteProgram(graphics_3d, shader_rectangle_arb_.program);
if (shader_external_oes_.program)
gles2_if_->DeleteProgram(graphics_3d, shader_external_oes_.program);
for (DecoderList::iterator it = video_decoders_.begin(); for (DecoderList::iterator it = video_decoders_.begin();
it != video_decoders_.end(); it != video_decoders_.end();
...@@ -478,14 +483,19 @@ void MyInstance::PaintNextPicture() { ...@@ -478,14 +483,19 @@ void MyInstance::PaintNextPicture() {
gles2_if_->UseProgram(graphics_3d, shader_2d_.program); gles2_if_->UseProgram(graphics_3d, shader_2d_.program);
gles2_if_->Uniform2f( gles2_if_->Uniform2f(
graphics_3d, shader_2d_.texcoord_scale_location, 1.0, 1.0); graphics_3d, shader_2d_.texcoord_scale_location, 1.0, 1.0);
} else { } else if (picture.texture_target == GL_TEXTURE_RECTANGLE_ARB) {
assert(picture.texture_target == GL_TEXTURE_RECTANGLE_ARB);
CreateRectangleARBProgramOnce(); CreateRectangleARBProgramOnce();
gles2_if_->UseProgram(graphics_3d, shader_rectangle_arb_.program); gles2_if_->UseProgram(graphics_3d, shader_rectangle_arb_.program);
gles2_if_->Uniform2f(graphics_3d, gles2_if_->Uniform2f(graphics_3d,
shader_rectangle_arb_.texcoord_scale_location, shader_rectangle_arb_.texcoord_scale_location,
picture.texture_size.width, picture.texture_size.width,
picture.texture_size.height); picture.texture_size.height);
} else {
assert(picture.texture_target == GL_TEXTURE_EXTERNAL_OES);
CreateExternalOESProgramOnce();
gles2_if_->UseProgram(graphics_3d, shader_external_oes_.program);
gles2_if_->Uniform2f(
graphics_3d, shader_external_oes_.texcoord_scale_location, 1.0, 1.0);
} }
gles2_if_->Viewport(graphics_3d, x, y, half_width, half_height); gles2_if_->Viewport(graphics_3d, x, y, half_width, half_height);
...@@ -630,6 +640,23 @@ void MyInstance::CreateRectangleARBProgramOnce() { ...@@ -630,6 +640,23 @@ void MyInstance::CreateRectangleARBProgramOnce() {
"}"; "}";
shader_rectangle_arb_ = shader_rectangle_arb_ =
CreateProgram(kVertexShader, kFragmentShaderRectangle); CreateProgram(kVertexShader, kFragmentShaderRectangle);
assertNoGLError();
}
void MyInstance::CreateExternalOESProgramOnce() {
if (shader_external_oes_.program)
return;
static const char kFragmentShaderExternal[] =
"#extension GL_OES_EGL_image_external : require\n"
"precision mediump float; \n"
"varying vec2 v_texCoord; \n"
"uniform samplerExternalOES s_texture; \n"
"void main() \n"
"{"
" gl_FragColor = texture2D(s_texture, v_texCoord); \n"
"}";
shader_external_oes_ = CreateProgram(kVertexShader, kFragmentShaderExternal);
assertNoGLError();
} }
Shader MyInstance::CreateProgram(const char* vertex_shader, Shader MyInstance::CreateProgram(const char* vertex_shader,
......
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