OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 // The bulk of this file is support code; sorry about that. Here's an overview | 5 // The bulk of this file is support code; sorry about that. Here's an overview |
6 // to hopefully help readers of this code: | 6 // to hopefully help readers of this code: |
7 // - RenderingHelper is charged with interacting with X11/{EGL/GLES2,GLX/GL} or | 7 // - RenderingHelper is charged with interacting with X11/{EGL/GLES2,GLX/GL} or |
8 // Win/EGL. | 8 // Win/EGL. |
9 // - ClientState is an enum for the state of the decode client used by the test. | 9 // - ClientState is an enum for the state of the decode client used by the test. |
10 // - ClientStateNotification is a barrier abstraction that allows the test code | 10 // - ClientStateNotification is a barrier abstraction that allows the test code |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
53 #error The VideoAccelerator tests are not supported on this platform. | 53 #error The VideoAccelerator tests are not supported on this platform. |
54 #endif // defined(OS_WIN) | 54 #endif // defined(OS_WIN) |
55 | 55 |
56 using media::VideoDecodeAccelerator; | 56 using media::VideoDecodeAccelerator; |
57 using video_test_util::RenderingHelper; | 57 using video_test_util::RenderingHelper; |
58 | 58 |
59 namespace { | 59 namespace { |
60 | 60 |
61 // Values optionally filled in from flags; see main() below. | 61 // Values optionally filled in from flags; see main() below. |
62 // The syntax of this variable is: | 62 // The syntax of this variable is: |
63 // filename:width:height:numframes:numNALUs:minFPSwithRender:minFPSnoRender | 63 // filename:width:height:numframes:numfragments:minFPSwithRender:minFPSnoRender |
64 // where only the first field is required. Value details: | 64 // where only the first field is required. Value details: |
65 // - |filename| must be an h264 Annex B (NAL) stream. | 65 // - |filename| must be an h264 Annex B (NAL) stream or an IVF VP8 stream. |
66 // - |width| and |height| are in pixels. | 66 // - |width| and |height| are in pixels. |
67 // - |numframes| is the number of picture frames in the file. | 67 // - |numframes| is the number of picture frames in the file. |
68 // - |numNALUs| is the number of NAL units in the stream. | 68 // - |numfragments| NALU (h264) or frame (VP8) count in the stream. |
69 // - |minFPSwithRender| and |minFPSnoRender| are minimum frames/second speeds | 69 // - |minFPSwithRender| and |minFPSnoRender| are minimum frames/second speeds |
70 // expected to be achieved with and without rendering to the screen, resp. | 70 // expected to be achieved with and without rendering to the screen, resp. |
71 // (the latter tests just decode speed). | 71 // (the latter tests just decode speed). |
72 // - |profile| is the media::H264Profile set during Initialization. | 72 // - |profile| is the media::VideoCodecProfile set during Initialization. |
73 // An empty value for a numeric field means "ignore". | 73 // An empty value for a numeric field means "ignore". |
74 #if defined(OS_MACOSX) | 74 #if defined(OS_MACOSX) |
75 const FilePath::CharType* test_video_data = | 75 const FilePath::CharType* test_video_data = |
76 FILE_PATH_LITERAL("test-25fps_high.h264:1280:720:250:252:50:100:4"); | 76 FILE_PATH_LITERAL("test-25fps_high.h264:1280:720:250:252:50:100:4"); |
77 #else | 77 #else |
78 // TODO(fischman): figure out how to support multiple test videos per run (needs | |
79 // to refactor where ParseTestVideoData is called). For now just make it easy | |
80 // to replace which file is used by commenting/uncommenting these lines: | |
78 const FilePath::CharType* test_video_data = | 81 const FilePath::CharType* test_video_data = |
82 // FILE_PATH_LITERAL("test-25fps.vp8:320:240:250:250:50:175:11"); | |
79 FILE_PATH_LITERAL("test-25fps.h264:320:240:250:258:50:175:1"); | 83 FILE_PATH_LITERAL("test-25fps.h264:320:240:250:258:50:175:1"); |
80 #endif | 84 #endif |
81 | 85 |
82 // Parse |data| into its constituent parts and set the various output fields | 86 // Parse |data| into its constituent parts and set the various output fields |
83 // accordingly. CHECK-fails on unexpected or missing required data. | 87 // accordingly. CHECK-fails on unexpected or missing required data. |
84 // Unspecified optional fields are set to -1. | 88 // Unspecified optional fields are set to -1. |
85 void ParseTestVideoData(FilePath::StringType data, | 89 void ParseTestVideoData(FilePath::StringType data, |
86 FilePath::StringType* file_name, | 90 FilePath::StringType* file_name, |
87 int* width, int* height, | 91 int* width, int* height, |
88 int* num_frames, | 92 int* num_frames, |
89 int* num_NALUs, | 93 int* num_fragments, |
90 int* min_fps_render, | 94 int* min_fps_render, |
91 int* min_fps_no_render, | 95 int* min_fps_no_render, |
92 int* profile) { | 96 int* profile) { |
93 std::vector<FilePath::StringType> elements; | 97 std::vector<FilePath::StringType> elements; |
94 base::SplitString(data, ':', &elements); | 98 base::SplitString(data, ':', &elements); |
95 CHECK_GE(elements.size(), 1U) << data; | 99 CHECK_GE(elements.size(), 1U) << data; |
96 CHECK_LE(elements.size(), 8U) << data; | 100 CHECK_LE(elements.size(), 8U) << data; |
97 *file_name = elements[0]; | 101 *file_name = elements[0]; |
98 *width = *height = *num_frames = *num_NALUs = -1; | 102 *width = *height = *num_frames = *num_fragments = -1; |
99 *min_fps_render = *min_fps_no_render = -1; | 103 *min_fps_render = *min_fps_no_render = -1; |
100 *profile = -1; | 104 *profile = -1; |
101 if (!elements[1].empty()) | 105 if (!elements[1].empty()) |
102 CHECK(base::StringToInt(elements[1], width)); | 106 CHECK(base::StringToInt(elements[1], width)); |
103 if (!elements[2].empty()) | 107 if (!elements[2].empty()) |
104 CHECK(base::StringToInt(elements[2], height)); | 108 CHECK(base::StringToInt(elements[2], height)); |
105 if (!elements[3].empty()) | 109 if (!elements[3].empty()) |
106 CHECK(base::StringToInt(elements[3], num_frames)); | 110 CHECK(base::StringToInt(elements[3], num_frames)); |
107 if (!elements[4].empty()) | 111 if (!elements[4].empty()) |
108 CHECK(base::StringToInt(elements[4], num_NALUs)); | 112 CHECK(base::StringToInt(elements[4], num_fragments)); |
109 if (!elements[5].empty()) | 113 if (!elements[5].empty()) |
110 CHECK(base::StringToInt(elements[5], min_fps_render)); | 114 CHECK(base::StringToInt(elements[5], min_fps_render)); |
111 if (!elements[6].empty()) | 115 if (!elements[6].empty()) |
112 CHECK(base::StringToInt(elements[6], min_fps_no_render)); | 116 CHECK(base::StringToInt(elements[6], min_fps_no_render)); |
113 if (!elements[7].empty()) | 117 if (!elements[7].empty()) |
114 CHECK(base::StringToInt(elements[7], profile)); | 118 CHECK(base::StringToInt(elements[7], profile)); |
115 } | 119 } |
116 | 120 |
117 // State of the GLRenderingVDAClient below. Order matters here as the test | 121 // State of the GLRenderingVDAClient below. Order matters here as the test |
118 // makes assumptions about it. | 122 // makes assumptions about it. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
174 MID_STREAM_RESET = -2, | 178 MID_STREAM_RESET = -2, |
175 END_OF_STREAM_RESET = -1 | 179 END_OF_STREAM_RESET = -1 |
176 }; | 180 }; |
177 | 181 |
178 // Client that can accept callbacks from a VideoDecodeAccelerator and is used by | 182 // Client that can accept callbacks from a VideoDecodeAccelerator and is used by |
179 // the TESTs below. | 183 // the TESTs below. |
180 class GLRenderingVDAClient : public VideoDecodeAccelerator::Client { | 184 class GLRenderingVDAClient : public VideoDecodeAccelerator::Client { |
181 public: | 185 public: |
182 // Doesn't take ownership of |rendering_helper| or |note|, which must outlive | 186 // Doesn't take ownership of |rendering_helper| or |note|, which must outlive |
183 // |*this|. | 187 // |*this|. |
188 // |num_fragments_per_decode| counts NALUs for h264 and frames for VP8. | |
184 // |num_play_throughs| indicates how many times to play through the video. | 189 // |num_play_throughs| indicates how many times to play through the video. |
185 // |reset_after_frame_num| can be a frame number >=0 indicating a mid-stream | 190 // |reset_after_frame_num| can be a frame number >=0 indicating a mid-stream |
186 // Reset() should be done after that frame number is delivered, or | 191 // Reset() should be done after that frame number is delivered, or |
187 // END_OF_STREAM_RESET to indicate no mid-stream Reset(). | 192 // END_OF_STREAM_RESET to indicate no mid-stream Reset(). |
188 // |delete_decoder_state| indicates when the underlying decoder should be | 193 // |delete_decoder_state| indicates when the underlying decoder should be |
189 // Destroy()'d and deleted and can take values: N<0: delete after -N Decode() | 194 // Destroy()'d and deleted and can take values: N<0: delete after -N Decode() |
190 // calls have been made, N>=0 means interpret as ClientState. | 195 // calls have been made, N>=0 means interpret as ClientState. |
191 // Both |reset_after_frame_num| & |delete_decoder_state| apply only to the | 196 // Both |reset_after_frame_num| & |delete_decoder_state| apply only to the |
192 // last play-through (governed by |num_play_throughs|). | 197 // last play-through (governed by |num_play_throughs|). |
193 GLRenderingVDAClient(RenderingHelper* rendering_helper, | 198 GLRenderingVDAClient(RenderingHelper* rendering_helper, |
194 int rendering_window_id, | 199 int rendering_window_id, |
195 ClientStateNotification* note, | 200 ClientStateNotification* note, |
196 const std::string& encoded_data, | 201 const std::string& encoded_data, |
197 int num_NALUs_per_decode, | 202 int num_fragments_per_decode, |
198 int num_in_flight_decodes, | 203 int num_in_flight_decodes, |
199 int num_play_throughs, | 204 int num_play_throughs, |
200 int reset_after_frame_num, | 205 int reset_after_frame_num, |
201 int delete_decoder_state, | 206 int delete_decoder_state, |
202 int frame_width, | 207 int frame_width, |
203 int frame_height, | 208 int frame_height, |
204 int profile); | 209 int profile); |
205 virtual ~GLRenderingVDAClient(); | 210 virtual ~GLRenderingVDAClient(); |
206 void CreateDecoder(); | 211 void CreateDecoder(); |
207 | 212 |
(...skipping 19 matching lines...) Expand all Loading... | |
227 bool decoder_deleted() { return !decoder_.get(); } | 232 bool decoder_deleted() { return !decoder_.get(); } |
228 | 233 |
229 private: | 234 private: |
230 typedef std::map<int, media::PictureBuffer*> PictureBufferById; | 235 typedef std::map<int, media::PictureBuffer*> PictureBufferById; |
231 | 236 |
232 void SetState(ClientState new_state); | 237 void SetState(ClientState new_state); |
233 | 238 |
234 // Delete the associated OMX decoder helper. | 239 // Delete the associated OMX decoder helper. |
235 void DeleteDecoder(); | 240 void DeleteDecoder(); |
236 | 241 |
237 // Compute & return in |*end_pos| the end position for the next batch of NALUs | 242 // Compute & return in |*end_pos| the end position for the next batch of |
238 // to ship to the decoder (based on |start_pos| & |num_NALUs_per_decode_|). | 243 // fragments to ship to the decoder (based on |start_pos| & |
239 void GetRangeForNextNALUs(size_t start_pos, size_t* end_pos); | 244 // |num_fragments_per_decode_|). |
245 void GetRangeForNextFragments(size_t start_pos, size_t* end_pos); | |
246 // Helpers for GetRangeForNextFragments above. | |
247 void GetRangeForNextNALUs(size_t start_pos, size_t* end_pos); // For h.264. | |
248 void GetRangeForNextFrames(size_t start_pos, size_t* end_pos); // For VP8. | |
240 | 249 |
241 // Request decode of the next batch of NALUs in the encoded data. | 250 // Request decode of the next batch of fragments in the encoded data. |
242 void DecodeNextNALUs(); | 251 void DecodeNextFragments(); |
243 | 252 |
244 RenderingHelper* rendering_helper_; | 253 RenderingHelper* rendering_helper_; |
245 int rendering_window_id_; | 254 int rendering_window_id_; |
246 std::string encoded_data_; | 255 std::string encoded_data_; |
247 const int num_NALUs_per_decode_; | 256 const int num_fragments_per_decode_; |
248 const int num_in_flight_decodes_; | 257 const int num_in_flight_decodes_; |
249 int outstanding_decodes_; | 258 int outstanding_decodes_; |
250 size_t encoded_data_next_pos_to_decode_; | 259 size_t encoded_data_next_pos_to_decode_; |
251 int next_bitstream_buffer_id_; | 260 int next_bitstream_buffer_id_; |
252 ClientStateNotification* note_; | 261 ClientStateNotification* note_; |
253 scoped_ptr<VideoDecodeAccelerator> decoder_; | 262 scoped_ptr<VideoDecodeAccelerator> decoder_; |
254 std::set<int> outstanding_texture_ids_; | 263 std::set<int> outstanding_texture_ids_; |
255 int remaining_play_throughs_; | 264 int remaining_play_throughs_; |
256 int reset_after_frame_num_; | 265 int reset_after_frame_num_; |
257 int delete_decoder_state_; | 266 int delete_decoder_state_; |
258 ClientState state_; | 267 ClientState state_; |
259 int num_decoded_frames_; | 268 int num_decoded_frames_; |
260 int num_done_bitstream_buffers_; | 269 int num_done_bitstream_buffers_; |
261 PictureBufferById picture_buffers_by_id_; | 270 PictureBufferById picture_buffers_by_id_; |
262 base::TimeTicks initialize_done_ticks_; | 271 base::TimeTicks initialize_done_ticks_; |
263 base::TimeTicks last_frame_delivered_ticks_; | 272 base::TimeTicks last_frame_delivered_ticks_; |
264 int profile_; | 273 int profile_; |
265 }; | 274 }; |
266 | 275 |
267 GLRenderingVDAClient::GLRenderingVDAClient( | 276 GLRenderingVDAClient::GLRenderingVDAClient( |
268 RenderingHelper* rendering_helper, | 277 RenderingHelper* rendering_helper, |
269 int rendering_window_id, | 278 int rendering_window_id, |
270 ClientStateNotification* note, | 279 ClientStateNotification* note, |
271 const std::string& encoded_data, | 280 const std::string& encoded_data, |
272 int num_NALUs_per_decode, | 281 int num_fragments_per_decode, |
273 int num_in_flight_decodes, | 282 int num_in_flight_decodes, |
274 int num_play_throughs, | 283 int num_play_throughs, |
275 int reset_after_frame_num, | 284 int reset_after_frame_num, |
276 int delete_decoder_state, | 285 int delete_decoder_state, |
277 int frame_width, | 286 int frame_width, |
278 int frame_height, | 287 int frame_height, |
279 int profile) | 288 int profile) |
280 : rendering_helper_(rendering_helper), | 289 : rendering_helper_(rendering_helper), |
281 rendering_window_id_(rendering_window_id), | 290 rendering_window_id_(rendering_window_id), |
282 encoded_data_(encoded_data), num_NALUs_per_decode_(num_NALUs_per_decode), | 291 encoded_data_(encoded_data), |
292 num_fragments_per_decode_(num_fragments_per_decode), | |
283 num_in_flight_decodes_(num_in_flight_decodes), outstanding_decodes_(0), | 293 num_in_flight_decodes_(num_in_flight_decodes), outstanding_decodes_(0), |
284 encoded_data_next_pos_to_decode_(0), next_bitstream_buffer_id_(0), | 294 encoded_data_next_pos_to_decode_(0), next_bitstream_buffer_id_(0), |
285 note_(note), | 295 note_(note), |
286 remaining_play_throughs_(num_play_throughs), | 296 remaining_play_throughs_(num_play_throughs), |
287 reset_after_frame_num_(reset_after_frame_num), | 297 reset_after_frame_num_(reset_after_frame_num), |
288 delete_decoder_state_(delete_decoder_state), | 298 delete_decoder_state_(delete_decoder_state), |
289 state_(CS_CREATED), | 299 state_(CS_CREATED), |
290 num_decoded_frames_(0), num_done_bitstream_buffers_(0), | 300 num_decoded_frames_(0), num_done_bitstream_buffers_(0), |
291 profile_(profile) { | 301 profile_(profile) { |
292 CHECK_GT(num_NALUs_per_decode, 0); | 302 CHECK_GT(num_fragments_per_decode, 0); |
293 CHECK_GT(num_in_flight_decodes, 0); | 303 CHECK_GT(num_in_flight_decodes, 0); |
294 CHECK_GT(num_play_throughs, 0); | 304 CHECK_GT(num_play_throughs, 0); |
295 } | 305 } |
296 | 306 |
297 GLRenderingVDAClient::~GLRenderingVDAClient() { | 307 GLRenderingVDAClient::~GLRenderingVDAClient() { |
298 DeleteDecoder(); // Clean up in case of expected error. | 308 DeleteDecoder(); // Clean up in case of expected error. |
299 CHECK(decoder_deleted()); | 309 CHECK(decoder_deleted()); |
300 STLDeleteValues(&picture_buffers_by_id_); | 310 STLDeleteValues(&picture_buffers_by_id_); |
301 SetState(CS_DESTROYED); | 311 SetState(CS_DESTROYED); |
302 } | 312 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
375 } | 385 } |
376 | 386 |
377 void GLRenderingVDAClient::PictureReady(const media::Picture& picture) { | 387 void GLRenderingVDAClient::PictureReady(const media::Picture& picture) { |
378 // We shouldn't be getting pictures delivered after Reset has completed. | 388 // We shouldn't be getting pictures delivered after Reset has completed. |
379 CHECK_LT(state_, CS_RESET); | 389 CHECK_LT(state_, CS_RESET); |
380 | 390 |
381 if (decoder_deleted()) | 391 if (decoder_deleted()) |
382 return; | 392 return; |
383 last_frame_delivered_ticks_ = base::TimeTicks::Now(); | 393 last_frame_delivered_ticks_ = base::TimeTicks::Now(); |
384 | 394 |
385 // Because we feed the decoder a limited number of NALUs at a time, we can be | 395 // Because we feed the decoder a limited number of fragments at a time, we can |
386 // sure that the bitstream buffer from which a frame comes has a limited | 396 // be sure that the bitstream buffer from which a frame comes has a limited |
387 // range. Assert that. | 397 // range. Assert that. |
388 CHECK_GE((picture.bitstream_buffer_id() + 1) * num_NALUs_per_decode_, | 398 CHECK_GE((picture.bitstream_buffer_id() + 1) * num_fragments_per_decode_, |
389 num_decoded_frames_); | 399 num_decoded_frames_); |
390 CHECK_LE(picture.bitstream_buffer_id(), next_bitstream_buffer_id_); | 400 CHECK_LE(picture.bitstream_buffer_id(), next_bitstream_buffer_id_); |
391 ++num_decoded_frames_; | 401 ++num_decoded_frames_; |
392 | 402 |
393 // Mid-stream reset applies only to the last play-through per constructor | 403 // Mid-stream reset applies only to the last play-through per constructor |
394 // comment. | 404 // comment. |
395 if (remaining_play_throughs_ == 1 && | 405 if (remaining_play_throughs_ == 1 && |
396 reset_after_frame_num_ == num_decoded_frames_) { | 406 reset_after_frame_num_ == num_decoded_frames_) { |
397 reset_after_frame_num_ = MID_STREAM_RESET; | 407 reset_after_frame_num_ = MID_STREAM_RESET; |
398 decoder_->Reset(); | 408 decoder_->Reset(); |
399 // Re-start decoding from the beginning of the stream to avoid needing to | 409 // Re-start decoding from the beginning of the stream to avoid needing to |
400 // know how to find I-frames and so on in this test. | 410 // know how to find I-frames and so on in this test. |
401 encoded_data_next_pos_to_decode_ = 0; | 411 encoded_data_next_pos_to_decode_ = 0; |
402 } | 412 } |
403 | 413 |
404 media::PictureBuffer* picture_buffer = | 414 media::PictureBuffer* picture_buffer = |
405 picture_buffers_by_id_[picture.picture_buffer_id()]; | 415 picture_buffers_by_id_[picture.picture_buffer_id()]; |
406 CHECK(picture_buffer); | 416 CHECK(picture_buffer); |
407 rendering_helper_->RenderTexture(picture_buffer->texture_id()); | 417 rendering_helper_->RenderTexture(picture_buffer->texture_id()); |
408 | 418 |
409 decoder_->ReusePictureBuffer(picture.picture_buffer_id()); | 419 decoder_->ReusePictureBuffer(picture.picture_buffer_id()); |
410 } | 420 } |
411 | 421 |
412 void GLRenderingVDAClient::NotifyInitializeDone() { | 422 void GLRenderingVDAClient::NotifyInitializeDone() { |
413 SetState(CS_INITIALIZED); | 423 SetState(CS_INITIALIZED); |
414 initialize_done_ticks_ = base::TimeTicks::Now(); | 424 initialize_done_ticks_ = base::TimeTicks::Now(); |
415 for (int i = 0; i < num_in_flight_decodes_; ++i) | 425 for (int i = 0; i < num_in_flight_decodes_; ++i) |
416 DecodeNextNALUs(); | 426 DecodeNextFragments(); |
417 DCHECK_EQ(outstanding_decodes_, num_in_flight_decodes_); | 427 DCHECK_EQ(outstanding_decodes_, num_in_flight_decodes_); |
418 } | 428 } |
419 | 429 |
420 void GLRenderingVDAClient::NotifyEndOfBitstreamBuffer( | 430 void GLRenderingVDAClient::NotifyEndOfBitstreamBuffer( |
421 int32 bitstream_buffer_id) { | 431 int32 bitstream_buffer_id) { |
422 // TODO(fischman): this test currently relies on this notification to make | 432 // TODO(fischman): this test currently relies on this notification to make |
423 // forward progress during a Reset(). But the VDA::Reset() API doesn't | 433 // forward progress during a Reset(). But the VDA::Reset() API doesn't |
424 // guarantee this, so stop relying on it (and remove the notifications from | 434 // guarantee this, so stop relying on it (and remove the notifications from |
425 // VaapiVideoDecodeAccelerator::FinishReset()). | 435 // VaapiVideoDecodeAccelerator::FinishReset()). |
426 ++num_done_bitstream_buffers_; | 436 ++num_done_bitstream_buffers_; |
427 --outstanding_decodes_; | 437 --outstanding_decodes_; |
428 DecodeNextNALUs(); | 438 DecodeNextFragments(); |
429 } | 439 } |
430 | 440 |
431 void GLRenderingVDAClient::NotifyFlushDone() { | 441 void GLRenderingVDAClient::NotifyFlushDone() { |
432 if (decoder_deleted()) | 442 if (decoder_deleted()) |
433 return; | 443 return; |
434 SetState(CS_FLUSHED); | 444 SetState(CS_FLUSHED); |
435 --remaining_play_throughs_; | 445 --remaining_play_throughs_; |
436 DCHECK_GE(remaining_play_throughs_, 0); | 446 DCHECK_GE(remaining_play_throughs_, 0); |
437 if (decoder_deleted()) | 447 if (decoder_deleted()) |
438 return; | 448 return; |
439 decoder_->Reset(); | 449 decoder_->Reset(); |
440 SetState(CS_RESETTING); | 450 SetState(CS_RESETTING); |
441 } | 451 } |
442 | 452 |
443 void GLRenderingVDAClient::NotifyResetDone() { | 453 void GLRenderingVDAClient::NotifyResetDone() { |
444 if (decoder_deleted()) | 454 if (decoder_deleted()) |
445 return; | 455 return; |
446 | 456 |
447 if (reset_after_frame_num_ == MID_STREAM_RESET) { | 457 if (reset_after_frame_num_ == MID_STREAM_RESET) { |
448 reset_after_frame_num_ = END_OF_STREAM_RESET; | 458 reset_after_frame_num_ = END_OF_STREAM_RESET; |
449 DecodeNextNALUs(); | 459 DecodeNextFragments(); |
450 return; | 460 return; |
451 } | 461 } |
452 | 462 |
453 if (remaining_play_throughs_) { | 463 if (remaining_play_throughs_) { |
454 encoded_data_next_pos_to_decode_ = 0; | 464 encoded_data_next_pos_to_decode_ = 0; |
455 NotifyInitializeDone(); | 465 NotifyInitializeDone(); |
456 return; | 466 return; |
457 } | 467 } |
458 | 468 |
459 SetState(CS_RESET); | 469 SetState(CS_RESET); |
(...skipping 28 matching lines...) Expand all Loading... | |
488 for (std::set<int>::iterator it = outstanding_texture_ids_.begin(); | 498 for (std::set<int>::iterator it = outstanding_texture_ids_.begin(); |
489 it != outstanding_texture_ids_.end(); ++it) { | 499 it != outstanding_texture_ids_.end(); ++it) { |
490 rendering_helper_->DeleteTexture(*it); | 500 rendering_helper_->DeleteTexture(*it); |
491 } | 501 } |
492 outstanding_texture_ids_.clear(); | 502 outstanding_texture_ids_.clear(); |
493 // Cascade through the rest of the states to simplify test code below. | 503 // Cascade through the rest of the states to simplify test code below. |
494 for (int i = state_ + 1; i < CS_MAX; ++i) | 504 for (int i = state_ + 1; i < CS_MAX; ++i) |
495 SetState(static_cast<ClientState>(i)); | 505 SetState(static_cast<ClientState>(i)); |
496 } | 506 } |
497 | 507 |
508 void GLRenderingVDAClient::GetRangeForNextFragments( | |
509 size_t start_pos, size_t* end_pos) { | |
510 if (profile_ < media::H264PROFILE_MAX) { | |
511 GetRangeForNextNALUs(start_pos, end_pos); | |
512 return; | |
513 } | |
514 DCHECK_LE(profile_, media::VP8PROFILE_MAX); | |
515 GetRangeForNextFrames(start_pos, end_pos); | |
516 } | |
517 | |
498 void GLRenderingVDAClient::GetRangeForNextNALUs( | 518 void GLRenderingVDAClient::GetRangeForNextNALUs( |
499 size_t start_pos, size_t* end_pos) { | 519 size_t start_pos, size_t* end_pos) { |
500 *end_pos = start_pos; | 520 *end_pos = start_pos; |
501 CHECK(LookingAtNAL(encoded_data_, start_pos)); | 521 CHECK(LookingAtNAL(encoded_data_, start_pos)); |
502 for (int i = 0; i < num_NALUs_per_decode_; ++i) { | 522 for (int i = 0; i < num_fragments_per_decode_; ++i) { |
503 *end_pos += 4; | 523 *end_pos += 4; |
504 while (*end_pos + 3 < encoded_data_.size() && | 524 while (*end_pos + 3 < encoded_data_.size() && |
505 !LookingAtNAL(encoded_data_, *end_pos)) { | 525 !LookingAtNAL(encoded_data_, *end_pos)) { |
506 ++*end_pos; | 526 ++*end_pos; |
507 } | 527 } |
508 if (*end_pos + 3 >= encoded_data_.size()) { | 528 if (*end_pos + 3 >= encoded_data_.size()) { |
509 *end_pos = encoded_data_.size(); | 529 *end_pos = encoded_data_.size(); |
510 return; | 530 return; |
511 } | 531 } |
512 } | 532 } |
513 } | 533 } |
514 | 534 |
515 void GLRenderingVDAClient::DecodeNextNALUs() { | 535 void GLRenderingVDAClient::GetRangeForNextFrames( |
536 size_t start_pos, size_t* end_pos) { | |
537 if (1) { | |
scherkus (not reviewing)
2012/07/20 20:20:20
what who!?
Ami GONE FROM CHROMIUM
2012/07/20 20:25:19
Just making sure you're paying attention!
| |
538 CHECK_EQ(start_pos, 0U); | |
539 *end_pos = encoded_data_.size(); | |
540 return; | |
541 } | |
542 | |
543 // Helpful description: http://wiki.multimedia.cx/index.php?title=IVF | |
544 *end_pos = start_pos; | |
545 if (start_pos == 0) | |
546 *end_pos = 32; | |
547 for (int i = 0; i < num_fragments_per_decode_; ++i) { | |
548 uint32 frame_size = *reinterpret_cast<uint32*>(&encoded_data_[*end_pos]); | |
549 *end_pos += 12; // Skip frame header. | |
550 *end_pos += frame_size; | |
551 if (*end_pos + 12 >= encoded_data_.size()) | |
552 return; | |
553 } | |
554 } | |
555 | |
556 void GLRenderingVDAClient::DecodeNextFragments() { | |
516 if (decoder_deleted()) | 557 if (decoder_deleted()) |
517 return; | 558 return; |
518 if (encoded_data_next_pos_to_decode_ == encoded_data_.size()) { | 559 if (encoded_data_next_pos_to_decode_ == encoded_data_.size()) { |
519 if (outstanding_decodes_ == 0) { | 560 if (outstanding_decodes_ == 0) { |
520 decoder_->Flush(); | 561 decoder_->Flush(); |
521 SetState(CS_FLUSHING); | 562 SetState(CS_FLUSHING); |
522 } | 563 } |
523 return; | 564 return; |
524 } | 565 } |
525 size_t start_pos = encoded_data_next_pos_to_decode_; | 566 size_t start_pos = encoded_data_next_pos_to_decode_; |
526 size_t end_pos; | 567 size_t end_pos; |
527 GetRangeForNextNALUs(start_pos, &end_pos); | 568 GetRangeForNextFragments(start_pos, &end_pos); |
528 | 569 |
529 // Populate the shared memory buffer w/ the NALU, duplicate its handle, and | 570 // Populate the shared memory buffer w/ the fragments, duplicate its handle, |
530 // hand it off to the decoder. | 571 // and hand it off to the decoder. |
531 base::SharedMemory shm; | 572 base::SharedMemory shm; |
532 CHECK(shm.CreateAndMapAnonymous(end_pos - start_pos)) | 573 CHECK(shm.CreateAndMapAnonymous(end_pos - start_pos)) |
533 << start_pos << ", " << end_pos; | 574 << start_pos << ", " << end_pos; |
534 memcpy(shm.memory(), encoded_data_.data() + start_pos, end_pos - start_pos); | 575 memcpy(shm.memory(), encoded_data_.data() + start_pos, end_pos - start_pos); |
535 base::SharedMemoryHandle dup_handle; | 576 base::SharedMemoryHandle dup_handle; |
536 CHECK(shm.ShareToProcess(base::Process::Current().handle(), &dup_handle)); | 577 CHECK(shm.ShareToProcess(base::Process::Current().handle(), &dup_handle)); |
537 media::BitstreamBuffer bitstream_buffer( | 578 media::BitstreamBuffer bitstream_buffer( |
538 next_bitstream_buffer_id_++, dup_handle, end_pos - start_pos); | 579 next_bitstream_buffer_id_++, dup_handle, end_pos - start_pos); |
539 decoder_->Decode(bitstream_buffer); | 580 decoder_->Decode(bitstream_buffer); |
540 ++outstanding_decodes_; | 581 ++outstanding_decodes_; |
541 encoded_data_next_pos_to_decode_ = end_pos; | 582 encoded_data_next_pos_to_decode_ = end_pos; |
542 | 583 |
543 if (!remaining_play_throughs_ && | 584 if (!remaining_play_throughs_ && |
544 -delete_decoder_state_ == next_bitstream_buffer_id_) { | 585 -delete_decoder_state_ == next_bitstream_buffer_id_) { |
545 DeleteDecoder(); | 586 DeleteDecoder(); |
546 } | 587 } |
547 } | 588 } |
548 | 589 |
549 double GLRenderingVDAClient::frames_per_second() { | 590 double GLRenderingVDAClient::frames_per_second() { |
550 base::TimeDelta delta = last_frame_delivered_ticks_ - initialize_done_ticks_; | 591 base::TimeDelta delta = last_frame_delivered_ticks_ - initialize_done_ticks_; |
551 if (delta.InSecondsF() == 0) | 592 if (delta.InSecondsF() == 0) |
552 return 0; | 593 return 0; |
553 return num_decoded_frames_ / delta.InSecondsF(); | 594 return num_decoded_frames_ / delta.InSecondsF(); |
554 } | 595 } |
555 | 596 |
556 // Test parameters: | 597 // Test parameters: |
557 // - Number of NALUs per Decode() call. | 598 // - Number of fragments per Decode() call. |
558 // - Number of concurrent decoders. | 599 // - Number of concurrent decoders. |
559 // - Number of concurrent in-flight Decode() calls per decoder. | 600 // - Number of concurrent in-flight Decode() calls per decoder. |
560 // - Number of play-throughs. | 601 // - Number of play-throughs. |
561 // - reset_after_frame_num: see GLRenderingVDAClient ctor. | 602 // - reset_after_frame_num: see GLRenderingVDAClient ctor. |
562 // - delete_decoder_phase: see GLRenderingVDAClient ctor. | 603 // - delete_decoder_phase: see GLRenderingVDAClient ctor. |
563 class VideoDecodeAcceleratorTest | 604 class VideoDecodeAcceleratorTest |
564 : public ::testing::TestWithParam< | 605 : public ::testing::TestWithParam< |
565 Tuple6<int, int, int, int, ResetPoint, ClientState> > { | 606 Tuple6<int, int, int, int, ResetPoint, ClientState> > { |
566 }; | 607 }; |
567 | 608 |
(...skipping 29 matching lines...) Expand all Loading... | |
597 | 638 |
598 // Test the most straightforward case possible: data is decoded from a single | 639 // Test the most straightforward case possible: data is decoded from a single |
599 // chunk and rendered to the screen. | 640 // chunk and rendered to the screen. |
600 TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) { | 641 TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) { |
601 // Can be useful for debugging VLOGs from OVDA. | 642 // Can be useful for debugging VLOGs from OVDA. |
602 // logging::SetMinLogLevel(-1); | 643 // logging::SetMinLogLevel(-1); |
603 | 644 |
604 // Required for Thread to work. Not used otherwise. | 645 // Required for Thread to work. Not used otherwise. |
605 base::ShadowingAtExitManager at_exit_manager; | 646 base::ShadowingAtExitManager at_exit_manager; |
606 | 647 |
607 const int num_NALUs_per_decode = GetParam().a; | 648 const int num_fragments_per_decode = GetParam().a; |
608 const size_t num_concurrent_decoders = GetParam().b; | 649 const size_t num_concurrent_decoders = GetParam().b; |
609 const size_t num_in_flight_decodes = GetParam().c; | 650 const size_t num_in_flight_decodes = GetParam().c; |
610 const int num_play_throughs = GetParam().d; | 651 const int num_play_throughs = GetParam().d; |
611 const int reset_after_frame_num = GetParam().e; | 652 const int reset_after_frame_num = GetParam().e; |
612 const int delete_decoder_state = GetParam().f; | 653 const int delete_decoder_state = GetParam().f; |
613 | 654 |
614 FilePath::StringType test_video_file; | 655 FilePath::StringType test_video_file; |
615 int frame_width, frame_height; | 656 int frame_width, frame_height; |
616 int num_frames, num_NALUs, min_fps_render, min_fps_no_render, profile; | 657 int num_frames, num_fragments, min_fps_render, min_fps_no_render, profile; |
617 ParseTestVideoData(test_video_data, &test_video_file, &frame_width, | 658 ParseTestVideoData(test_video_data, &test_video_file, &frame_width, |
618 &frame_height, &num_frames, &num_NALUs, | 659 &frame_height, &num_frames, &num_fragments, |
619 &min_fps_render, &min_fps_no_render, &profile); | 660 &min_fps_render, &min_fps_no_render, &profile); |
620 min_fps_render /= num_concurrent_decoders; | 661 min_fps_render /= num_concurrent_decoders; |
621 min_fps_no_render /= num_concurrent_decoders; | 662 min_fps_no_render /= num_concurrent_decoders; |
622 | 663 |
623 // If we reset mid-stream and start playback over, account for frames that are | 664 // If we reset mid-stream and start playback over, account for frames that are |
624 // decoded twice in our expectations. | 665 // decoded twice in our expectations. |
625 if (num_frames > 0 && reset_after_frame_num >= 0) | 666 if (num_frames > 0 && reset_after_frame_num >= 0) |
626 num_frames += reset_after_frame_num; | 667 num_frames += reset_after_frame_num; |
627 | 668 |
628 // Suppress GL swapping in all but a few tests, to cut down overall test | 669 // Suppress GL swapping in all but a few tests, to cut down overall test |
629 // runtime. | 670 // runtime. |
630 const bool suppress_swap_to_display = num_NALUs_per_decode > 1; | 671 const bool suppress_swap_to_display = num_fragments_per_decode > 1; |
631 | 672 |
632 std::vector<ClientStateNotification*> notes(num_concurrent_decoders, NULL); | 673 std::vector<ClientStateNotification*> notes(num_concurrent_decoders, NULL); |
633 std::vector<GLRenderingVDAClient*> clients(num_concurrent_decoders, NULL); | 674 std::vector<GLRenderingVDAClient*> clients(num_concurrent_decoders, NULL); |
634 | 675 |
635 // Read in the video data. | 676 // Read in the video data. |
636 std::string data_str; | 677 std::string data_str; |
637 CHECK(file_util::ReadFileToString(FilePath(test_video_file), &data_str)) | 678 CHECK(file_util::ReadFileToString(FilePath(test_video_file), &data_str)) |
638 << "test_video_file: " << FilePath(test_video_file).MaybeAsASCII(); | 679 << "test_video_file: " << FilePath(test_video_file).MaybeAsASCII(); |
639 | 680 |
640 // Initialize the rendering helper. | 681 // Initialize the rendering helper. |
(...skipping 16 matching lines...) Expand all Loading... | |
657 base::Unretained(rendering_helper.get()), | 698 base::Unretained(rendering_helper.get()), |
658 suppress_swap_to_display, num_concurrent_decoders, | 699 suppress_swap_to_display, num_concurrent_decoders, |
659 frame_width, frame_height, &done)); | 700 frame_width, frame_height, &done)); |
660 done.Wait(); | 701 done.Wait(); |
661 | 702 |
662 // First kick off all the decoders. | 703 // First kick off all the decoders. |
663 for (size_t index = 0; index < num_concurrent_decoders; ++index) { | 704 for (size_t index = 0; index < num_concurrent_decoders; ++index) { |
664 ClientStateNotification* note = new ClientStateNotification(); | 705 ClientStateNotification* note = new ClientStateNotification(); |
665 notes[index] = note; | 706 notes[index] = note; |
666 GLRenderingVDAClient* client = new GLRenderingVDAClient( | 707 GLRenderingVDAClient* client = new GLRenderingVDAClient( |
667 rendering_helper.get(), index, note, data_str, num_NALUs_per_decode, | 708 rendering_helper.get(), index, note, data_str, num_fragments_per_decode, |
668 num_in_flight_decodes, num_play_throughs, reset_after_frame_num, | 709 num_in_flight_decodes, num_play_throughs, reset_after_frame_num, |
669 delete_decoder_state, frame_width, frame_height, profile); | 710 delete_decoder_state, frame_width, frame_height, profile); |
670 clients[index] = client; | 711 clients[index] = client; |
671 | 712 |
672 rendering_thread.message_loop()->PostTask( | 713 rendering_thread.message_loop()->PostTask( |
673 FROM_HERE, | 714 FROM_HERE, |
674 base::Bind(&GLRenderingVDAClient::CreateDecoder, | 715 base::Bind(&GLRenderingVDAClient::CreateDecoder, |
675 base::Unretained(client))); | 716 base::Unretained(client))); |
676 | 717 |
677 ASSERT_EQ(note->Wait(), CS_DECODER_SET); | 718 ASSERT_EQ(note->Wait(), CS_DECODER_SET); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
718 // Finally assert that decoding went as expected. | 759 // Finally assert that decoding went as expected. |
719 for (size_t i = 0; i < num_concurrent_decoders && | 760 for (size_t i = 0; i < num_concurrent_decoders && |
720 !skip_performance_and_correctness_checks; ++i) { | 761 !skip_performance_and_correctness_checks; ++i) { |
721 // We can only make performance/correctness assertions if the decoder was | 762 // We can only make performance/correctness assertions if the decoder was |
722 // allowed to finish. | 763 // allowed to finish. |
723 if (delete_decoder_state < CS_FLUSHED) | 764 if (delete_decoder_state < CS_FLUSHED) |
724 continue; | 765 continue; |
725 GLRenderingVDAClient* client = clients[i]; | 766 GLRenderingVDAClient* client = clients[i]; |
726 if (num_frames > 0) | 767 if (num_frames > 0) |
727 EXPECT_EQ(client->num_decoded_frames(), num_frames); | 768 EXPECT_EQ(client->num_decoded_frames(), num_frames); |
728 if (num_NALUs > 0 && reset_after_frame_num < 0) { | 769 if (num_fragments > 0 && reset_after_frame_num < 0) { |
729 EXPECT_EQ(client->num_done_bitstream_buffers(), | 770 EXPECT_EQ(client->num_done_bitstream_buffers(), |
730 ceil(static_cast<double>(num_NALUs) / num_NALUs_per_decode)); | 771 ceil(static_cast<double>(num_fragments) / |
772 num_fragments_per_decode)); | |
731 } | 773 } |
732 LOG(INFO) << "Decoder " << i << " fps: " << client->frames_per_second(); | 774 LOG(INFO) << "Decoder " << i << " fps: " << client->frames_per_second(); |
733 int min_fps = suppress_swap_to_display ? min_fps_no_render : min_fps_render; | 775 int min_fps = suppress_swap_to_display ? min_fps_no_render : min_fps_render; |
734 if (min_fps > 0) | 776 if (min_fps > 0) |
735 EXPECT_GT(client->frames_per_second(), min_fps); | 777 EXPECT_GT(client->frames_per_second(), min_fps); |
736 } | 778 } |
737 | 779 |
738 rendering_thread.message_loop()->PostTask( | 780 rendering_thread.message_loop()->PostTask( |
739 FROM_HERE, | 781 FROM_HERE, |
740 base::Bind(&STLDeleteElements<std::vector<GLRenderingVDAClient*> >, | 782 base::Bind(&STLDeleteElements<std::vector<GLRenderingVDAClient*> >, |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
777 MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESETTING), | 819 MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESETTING), |
778 MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET), | 820 MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET), |
779 MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, | 821 MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, |
780 static_cast<ClientState>(-1)), | 822 static_cast<ClientState>(-1)), |
781 MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, | 823 MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, |
782 static_cast<ClientState>(-10)), | 824 static_cast<ClientState>(-10)), |
783 MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, | 825 MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, |
784 static_cast<ClientState>(-100)))); | 826 static_cast<ClientState>(-100)))); |
785 | 827 |
786 // Test that decoding various variation works: multiple concurrent decoders and | 828 // Test that decoding various variation works: multiple concurrent decoders and |
787 // multiple NALUs per Decode() call. | 829 // multiple fragments per Decode() call. |
788 INSTANTIATE_TEST_CASE_P( | 830 INSTANTIATE_TEST_CASE_P( |
789 DecodeVariations, VideoDecodeAcceleratorTest, | 831 DecodeVariations, VideoDecodeAcceleratorTest, |
790 ::testing::Values( | 832 ::testing::Values( |
791 MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET), | 833 MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET), |
792 MakeTuple(1, 1, 10, 1, END_OF_STREAM_RESET, CS_RESET), | 834 MakeTuple(1, 1, 10, 1, END_OF_STREAM_RESET, CS_RESET), |
793 // Tests queuing. | 835 // Tests queuing. |
794 MakeTuple(1, 1, 15, 1, END_OF_STREAM_RESET, CS_RESET), | 836 MakeTuple(1, 1, 15, 1, END_OF_STREAM_RESET, CS_RESET), |
795 // +0 hack below to promote enum to int. | 837 // +0 hack below to promote enum to int. |
796 MakeTuple(1, kMinSupportedNumConcurrentDecoders + 0, 1, 1, | 838 MakeTuple(1, kMinSupportedNumConcurrentDecoders + 0, 1, 1, |
797 END_OF_STREAM_RESET, CS_RESET), | 839 END_OF_STREAM_RESET, CS_RESET), |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
855 | 897 |
856 base::ShadowingAtExitManager at_exit_manager; | 898 base::ShadowingAtExitManager at_exit_manager; |
857 RenderingHelper::InitializePlatform(); | 899 RenderingHelper::InitializePlatform(); |
858 | 900 |
859 #if defined(OS_WIN) | 901 #if defined(OS_WIN) |
860 DXVAVideoDecodeAccelerator::PreSandboxInitialization(); | 902 DXVAVideoDecodeAccelerator::PreSandboxInitialization(); |
861 #endif | 903 #endif |
862 | 904 |
863 return RUN_ALL_TESTS(); | 905 return RUN_ALL_TESTS(); |
864 } | 906 } |
OLD | NEW |