OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |