Chromium Code Reviews| 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 |