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

Side by Side Diff: ppapi/examples/video_decode/video_decode.cc

Issue 311853005: Implement software fallback for PPB_VideoDecoder. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use WeakPtr to tie VideoDecoderProxy and Delegate. Created 6 years, 6 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stdio.h> 5 #include <stdio.h>
6 #include <string.h> 6 #include <string.h>
7 7
8 #include <iostream> 8 #include <iostream>
9 #include <queue> 9 #include <queue>
10 #include <sstream> 10 #include <sstream>
11 11
12 #include "ppapi/c/pp_errors.h" 12 #include "ppapi/c/pp_errors.h"
13 #include "ppapi/c/ppb_console.h" 13 #include "ppapi/c/ppb_console.h"
14 #include "ppapi/c/ppb_opengles2.h" 14 #include "ppapi/c/ppb_opengles2.h"
15 #include "ppapi/cpp/graphics_3d.h" 15 #include "ppapi/cpp/graphics_3d.h"
16 #include "ppapi/cpp/graphics_3d_client.h" 16 #include "ppapi/cpp/graphics_3d_client.h"
17 #include "ppapi/cpp/input_event.h" 17 #include "ppapi/cpp/input_event.h"
18 #include "ppapi/cpp/instance.h" 18 #include "ppapi/cpp/instance.h"
19 #include "ppapi/cpp/module.h" 19 #include "ppapi/cpp/module.h"
20 #include "ppapi/cpp/rect.h" 20 #include "ppapi/cpp/rect.h"
21 #include "ppapi/cpp/var.h" 21 #include "ppapi/cpp/var.h"
22 #include "ppapi/cpp/video_decoder.h" 22 #include "ppapi/cpp/video_decoder.h"
23
24 // One of these should be defined.
25 //#define TEST_H264
26 #define TEST_VP8
Ami GONE FROM CHROMIUM 2014/06/05 00:06:24 If you made these USE_VP8_TESTDATA_INSTEAD_OF_H264
bbudge 2014/06/06 02:03:45 I like it. Done.
23 #include "ppapi/examples/video_decode/testdata.h" 27 #include "ppapi/examples/video_decode/testdata.h"
28
24 #include "ppapi/lib/gl/include/GLES2/gl2.h" 29 #include "ppapi/lib/gl/include/GLES2/gl2.h"
25 #include "ppapi/lib/gl/include/GLES2/gl2ext.h" 30 #include "ppapi/lib/gl/include/GLES2/gl2ext.h"
26 #include "ppapi/utility/completion_callback_factory.h" 31 #include "ppapi/utility/completion_callback_factory.h"
27 32
28 // Use assert as a poor-man's CHECK, even in non-debug mode. 33 // Use assert as a poor-man's CHECK, even in non-debug mode.
29 // Since <assert.h> redefines assert on every inclusion (it doesn't use 34 // Since <assert.h> redefines assert on every inclusion (it doesn't use
30 // include-guards), make sure this is the last file #include'd in this file. 35 // include-guards), make sure this is the last file #include'd in this file.
31 #undef NDEBUG 36 #undef NDEBUG
32 #include <assert.h> 37 #include <assert.h>
33 38
(...skipping 15 matching lines...) Expand all
49 class MyInstance; 54 class MyInstance;
50 55
51 class MyInstance : public pp::Instance, public pp::Graphics3DClient { 56 class MyInstance : public pp::Instance, public pp::Graphics3DClient {
52 public: 57 public:
53 MyInstance(PP_Instance instance, pp::Module* module); 58 MyInstance(PP_Instance instance, pp::Module* module);
54 virtual ~MyInstance(); 59 virtual ~MyInstance();
55 60
56 // pp::Instance implementation. 61 // pp::Instance implementation.
57 virtual void DidChangeView(const pp::Rect& position, 62 virtual void DidChangeView(const pp::Rect& position,
58 const pp::Rect& clip_ignored); 63 const pp::Rect& clip_ignored);
64 virtual bool HandleInputEvent(const pp::InputEvent& event);
59 65
60 // pp::Graphics3DClient implementation. 66 // pp::Graphics3DClient implementation.
61 virtual void Graphics3DContextLost() { 67 virtual void Graphics3DContextLost() {
62 // TODO(vrk/fischman): Properly reset after a lost graphics context. In 68 // TODO(vrk/fischman): Properly reset after a lost graphics context. In
63 // particular need to delete context_ and re-create textures. 69 // particular need to delete context_ and re-create textures.
64 // Probably have to recreate the decoder from scratch, because old textures 70 // Probably have to recreate the decoder from scratch, because old textures
65 // can still be outstanding in the decoder! 71 // can still be outstanding in the decoder!
66 assert(false && "Unexpectedly lost graphics context"); 72 assert(false && "Unexpectedly lost graphics context");
67 } 73 }
68 74
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 }; 138 };
133 139
134 class Decoder { 140 class Decoder {
135 public: 141 public:
136 Decoder(MyInstance* instance, int id, const pp::Graphics3D& graphics_3d); 142 Decoder(MyInstance* instance, int id, const pp::Graphics3D& graphics_3d);
137 ~Decoder(); 143 ~Decoder();
138 144
139 int id() const { return id_; } 145 int id() const { return id_; }
140 bool decoding() const { return !flushing_ && !resetting_; } 146 bool decoding() const { return !flushing_ && !resetting_; }
141 147
142 void Seek(int frame); 148 void Reset();
143 void RecyclePicture(const PP_VideoPicture& picture); 149 void RecyclePicture(const PP_VideoPicture& picture);
144 150
145 private: 151 private:
146 void InitializeDone(int32_t result); 152 void InitializeDone(int32_t result);
147 void Start(int frame); 153 void Start();
148 void DecodeNextFrame(); 154 void DecodeNextFrame();
149 void DecodeDone(int32_t result); 155 void DecodeDone(int32_t result);
150 void PictureReady(int32_t result, PP_VideoPicture picture); 156 void PictureReady(int32_t result, PP_VideoPicture picture);
151 void FlushDone(int32_t result); 157 void FlushDone(int32_t result);
152 void ResetDone(int32_t result); 158 void ResetDone(int32_t result);
153 159
154 MyInstance* instance_; 160 MyInstance* instance_;
155 int id_; 161 int id_;
156 162
157 pp::VideoDecoder* decoder_; 163 pp::VideoDecoder* decoder_;
158 pp::CompletionCallbackFactory<Decoder> callback_factory_; 164 pp::CompletionCallbackFactory<Decoder> callback_factory_;
159 165
160 size_t encoded_data_next_pos_to_decode_; 166 size_t encoded_data_next_pos_to_decode_;
161 int next_picture_id_; 167 int next_picture_id_;
162 int seek_frame_;
163 bool flushing_; 168 bool flushing_;
164 bool resetting_; 169 bool resetting_;
165 }; 170 };
166 171
172 #if defined(TEST_H264)
173
167 // Returns true if the current position is at the start of a NAL unit. 174 // Returns true if the current position is at the start of a NAL unit.
168 static bool LookingAtNAL(const unsigned char* encoded, size_t pos) { 175 static bool LookingAtNAL(const unsigned char* encoded, size_t pos) {
169 // H264 frames start with 0, 0, 0, 1 in our test data. 176 // H264 frames start with 0, 0, 0, 1 in our test data.
170 return pos + 3 < kDataLen && encoded[pos] == 0 && encoded[pos + 1] == 0 && 177 return pos + 3 < kDataLen && encoded[pos] == 0 && encoded[pos + 1] == 0 &&
171 encoded[pos + 2] == 0 && encoded[pos + 3] == 1; 178 encoded[pos + 2] == 0 && encoded[pos + 3] == 1;
172 } 179 }
173 180
174 // Find the start and end of the next frame.
175 static void GetNextFrame(size_t* start_pos, size_t* end_pos) { 181 static void GetNextFrame(size_t* start_pos, size_t* end_pos) {
176 assert(LookingAtNAL(kData, *start_pos)); 182 assert(LookingAtNAL(kData, *start_pos));
177 *end_pos = *start_pos; 183 *end_pos = *start_pos;
178 *end_pos += 4; 184 *end_pos += 4;
179 while (*end_pos < kDataLen && !LookingAtNAL(kData, *end_pos)) { 185 while (*end_pos < kDataLen && !LookingAtNAL(kData, *end_pos)) {
180 ++*end_pos; 186 ++*end_pos;
181 } 187 }
182 } 188 }
183 189
190 #elif defined(TEST_VP8) // VP8
191
192 // VP8 is stored in an IVF container.
193 // Helpful description: http://wiki.multimedia.cx/index.php?title=IVF
194
195 static void GetNextFrame(size_t* start_pos, size_t* end_pos) {
196 size_t current_pos = *start_pos;
197 if (current_pos == 0)
198 current_pos = 32; // Skip stream header.
199 uint32_t frame_size = *reinterpret_cast<const uint32_t*>(&kData[current_pos]);
Ami GONE FROM CHROMIUM 2014/06/05 00:06:24 This is a type-punning violation; please see base/
bbudge 2014/06/06 02:03:45 Done.
200 current_pos += 12; // Skip frame header.
201 *start_pos = current_pos;
202 *end_pos = current_pos + frame_size;
203 }
204
205 #endif
Ami GONE FROM CHROMIUM 2014/06/05 00:06:24 #else #error Oops! unless you take my suggestion
bbudge 2014/06/06 02:03:45 Done.
206
184 Decoder::Decoder(MyInstance* instance, 207 Decoder::Decoder(MyInstance* instance,
185 int id, 208 int id,
186 const pp::Graphics3D& graphics_3d) 209 const pp::Graphics3D& graphics_3d)
187 : instance_(instance), 210 : instance_(instance),
188 id_(id), 211 id_(id),
189 decoder_(new pp::VideoDecoder(instance)), 212 decoder_(new pp::VideoDecoder(instance)),
190 callback_factory_(this), 213 callback_factory_(this),
191 encoded_data_next_pos_to_decode_(0), 214 encoded_data_next_pos_to_decode_(0),
192 next_picture_id_(0), 215 next_picture_id_(0),
193 seek_frame_(0),
194 flushing_(false), 216 flushing_(false),
195 resetting_(false) { 217 resetting_(false) {
196 assert(!decoder_->is_null()); 218 assert(!decoder_->is_null());
197 const PP_VideoProfile profile = PP_VIDEOPROFILE_H264MAIN; 219 const PP_VideoProfile profile =
220 #if defined(TEST_H264)
221 PP_VIDEOPROFILE_H264MAIN;
Ami GONE FROM CHROMIUM 2014/06/05 00:06:24 This should probably be part of the header file al
bbudge 2014/06/06 02:03:46 Done.
222 #elif defined(TEST_VP8)
223 PP_VIDEOPROFILE_VP8MAIN;
224 #endif
198 decoder_->Initialize(graphics_3d, 225 decoder_->Initialize(graphics_3d,
199 profile, 226 profile,
200 PP_FALSE /* allow_software_fallback */, 227 PP_TRUE /* allow_software_fallback */,
201 callback_factory_.NewCallback(&Decoder::InitializeDone)); 228 callback_factory_.NewCallback(&Decoder::InitializeDone));
202 } 229 }
203 230
204 Decoder::~Decoder() { 231 Decoder::~Decoder() {
205 delete decoder_; 232 delete decoder_;
206 } 233 }
207 234
208 void Decoder::InitializeDone(int32_t result) { 235 void Decoder::InitializeDone(int32_t result) {
209 assert(decoder_); 236 assert(decoder_);
210 assert(result == PP_OK); 237 assert(result == PP_OK);
211 assert(decoding()); 238 assert(decoding());
212 Start(0); 239 Start();
213 } 240 }
214 241
215 void Decoder::Start(int frame) { 242 void Decoder::Start() {
216 assert(decoder_); 243 assert(decoder_);
217 244
218 // Skip to |frame|. 245 encoded_data_next_pos_to_decode_ = 0;
219 size_t start_pos = 0;
220 size_t end_pos = 0;
221 for (int i = 0; i < frame; i++)
222 GetNextFrame(&start_pos, &end_pos);
223 encoded_data_next_pos_to_decode_ = end_pos;
224 246
225 // Register callback to get the first picture. We call GetPicture again in 247 // Register callback to get the first picture. We call GetPicture again in
226 // PictureReady to continuously receive pictures as they're decoded. 248 // PictureReady to continuously receive pictures as they're decoded.
227 decoder_->GetPicture( 249 decoder_->GetPicture(
228 callback_factory_.NewCallbackWithOutput(&Decoder::PictureReady)); 250 callback_factory_.NewCallbackWithOutput(&Decoder::PictureReady));
229 251
230 // Start the decode loop. 252 // Start the decode loop.
231 DecodeNextFrame(); 253 DecodeNextFrame();
232 } 254 }
233 255
234 void Decoder::Seek(int frame) { 256 void Decoder::Reset() {
235 assert(decoder_); 257 assert(decoder_);
236 seek_frame_ = frame;
237 resetting_ = true; 258 resetting_ = true;
238 decoder_->Reset(callback_factory_.NewCallback(&Decoder::ResetDone)); 259 decoder_->Reset(callback_factory_.NewCallback(&Decoder::ResetDone));
239 } 260 }
240 261
241 void Decoder::RecyclePicture(const PP_VideoPicture& picture) { 262 void Decoder::RecyclePicture(const PP_VideoPicture& picture) {
242 assert(decoder_); 263 assert(decoder_);
243 decoder_->RecyclePicture(picture); 264 decoder_->RecyclePicture(picture);
244 } 265 }
245 266
246 void Decoder::DecodeNextFrame() { 267 void Decoder::DecodeNextFrame() {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 void Decoder::FlushDone(int32_t result) { 313 void Decoder::FlushDone(int32_t result) {
293 assert(decoder_); 314 assert(decoder_);
294 assert(result == PP_OK || result == PP_ERROR_ABORTED); 315 assert(result == PP_OK || result == PP_ERROR_ABORTED);
295 flushing_ = false; 316 flushing_ = false;
296 } 317 }
297 318
298 void Decoder::ResetDone(int32_t result) { 319 void Decoder::ResetDone(int32_t result) {
299 assert(decoder_); 320 assert(decoder_);
300 assert(result == PP_OK); 321 assert(result == PP_OK);
301 resetting_ = false; 322 resetting_ = false;
323
324 Start();
302 } 325 }
303 326
304 MyInstance::MyInstance(PP_Instance instance, pp::Module* module) 327 MyInstance::MyInstance(PP_Instance instance, pp::Module* module)
305 : pp::Instance(instance), 328 : pp::Instance(instance),
306 pp::Graphics3DClient(this), 329 pp::Graphics3DClient(this),
307 is_painting_(false), 330 is_painting_(false),
308 num_frames_rendered_(0), 331 num_frames_rendered_(0),
309 first_frame_delivered_ticks_(-1), 332 first_frame_delivered_ticks_(-1),
310 last_swap_request_ticks_(-1), 333 last_swap_request_ticks_(-1),
311 swap_ticks_(0), 334 swap_ticks_(0),
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 assert(position.size() == plugin_size_); 369 assert(position.size() == plugin_size_);
347 return; 370 return;
348 } 371 }
349 plugin_size_ = position.size(); 372 plugin_size_ = position.size();
350 373
351 // Initialize graphics. 374 // Initialize graphics.
352 InitGL(); 375 InitGL();
353 InitializeDecoders(); 376 InitializeDecoders();
354 } 377 }
355 378
379 bool MyInstance::HandleInputEvent(const pp::InputEvent& event) {
380 switch (event.GetType()) {
381 case PP_INPUTEVENT_TYPE_MOUSEDOWN: {
382 pp::MouseInputEvent mouse_event(event);
383 // Reset all decoders on mouse down.
384 if (mouse_event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_LEFT) {
385 for (size_t i = 0; i < video_decoders_.size(); i++)
386 video_decoders_[i]->Reset();
Ami GONE FROM CHROMIUM 2014/06/05 00:06:24 I'm surprised you don't end up having to pause/can
bbudge 2014/06/06 02:03:46 The example won't call Decode after Reset, since a
387 }
388 return true;
389 }
390
391 default:
392 return false;
393 }
394 }
395
356 void MyInstance::InitializeDecoders() { 396 void MyInstance::InitializeDecoders() {
357 assert(video_decoders_.empty()); 397 assert(video_decoders_.empty());
358 // Create two decoders with ids 0 and 1. 398 // Create two decoders with ids 0 and 1.
359 video_decoders_.push_back(new Decoder(this, 0, *context_)); 399 video_decoders_.push_back(new Decoder(this, 0, *context_));
360 video_decoders_.push_back(new Decoder(this, 1, *context_)); 400 video_decoders_.push_back(new Decoder(this, 1, *context_));
361 } 401 }
362 402
363 void MyInstance::PaintPicture(Decoder* decoder, 403 void MyInstance::PaintPicture(Decoder* decoder,
364 const PP_VideoPicture& picture) { 404 const PP_VideoPicture& picture) {
365 if (first_frame_delivered_ticks_ == -1) 405 if (first_frame_delivered_ticks_ == -1)
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 }; 640 };
601 641
602 } // anonymous namespace 642 } // anonymous namespace
603 643
604 namespace pp { 644 namespace pp {
605 // Factory function for your specialization of the Module object. 645 // Factory function for your specialization of the Module object.
606 Module* CreateModule() { 646 Module* CreateModule() {
607 return new MyModule(); 647 return new MyModule();
608 } 648 }
609 } // namespace pp 649 } // namespace pp
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698