| 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 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 double fps, | 209 double fps, |
| 210 ReusePictureCB reuse_picture_cb); | 210 ReusePictureCB reuse_picture_cb); |
| 211 virtual ~ThrottlingVDAClient(); | 211 virtual ~ThrottlingVDAClient(); |
| 212 | 212 |
| 213 // VideoDecodeAccelerator::Client implementation | 213 // VideoDecodeAccelerator::Client implementation |
| 214 virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers, | 214 virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers, |
| 215 const gfx::Size& dimensions, | 215 const gfx::Size& dimensions, |
| 216 uint32 texture_target) OVERRIDE; | 216 uint32 texture_target) OVERRIDE; |
| 217 virtual void DismissPictureBuffer(int32 picture_buffer_id) OVERRIDE; | 217 virtual void DismissPictureBuffer(int32 picture_buffer_id) OVERRIDE; |
| 218 virtual void PictureReady(const media::Picture& picture) OVERRIDE; | 218 virtual void PictureReady(const media::Picture& picture) OVERRIDE; |
| 219 virtual void NotifyInitializeDone() OVERRIDE; | |
| 220 virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) OVERRIDE; | 219 virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) OVERRIDE; |
| 221 virtual void NotifyFlushDone() OVERRIDE; | 220 virtual void NotifyFlushDone() OVERRIDE; |
| 222 virtual void NotifyResetDone() OVERRIDE; | 221 virtual void NotifyResetDone() OVERRIDE; |
| 223 virtual void NotifyError(VideoDecodeAccelerator::Error error) OVERRIDE; | 222 virtual void NotifyError(VideoDecodeAccelerator::Error error) OVERRIDE; |
| 224 | 223 |
| 225 int num_decoded_frames() { return num_decoded_frames_; } | 224 int num_decoded_frames() { return num_decoded_frames_; } |
| 226 | 225 |
| 227 private: | 226 private: |
| 228 | 227 |
| 229 void CallClientPictureReady(int version); | 228 void CallClientPictureReady(int version); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 if (!pending_pictures_.empty()) { | 304 if (!pending_pictures_.empty()) { |
| 306 base::MessageLoop::current()->PostDelayedTask( | 305 base::MessageLoop::current()->PostDelayedTask( |
| 307 FROM_HERE, | 306 FROM_HERE, |
| 308 base::Bind(&ThrottlingVDAClient::CallClientPictureReady, | 307 base::Bind(&ThrottlingVDAClient::CallClientPictureReady, |
| 309 AsWeakPtr(), | 308 AsWeakPtr(), |
| 310 stream_version_), | 309 stream_version_), |
| 311 next_frame_delivered_time_ - base::TimeTicks::Now()); | 310 next_frame_delivered_time_ - base::TimeTicks::Now()); |
| 312 } | 311 } |
| 313 } | 312 } |
| 314 | 313 |
| 315 void ThrottlingVDAClient::NotifyInitializeDone() { | |
| 316 client_->NotifyInitializeDone(); | |
| 317 } | |
| 318 | |
| 319 void ThrottlingVDAClient::NotifyEndOfBitstreamBuffer( | 314 void ThrottlingVDAClient::NotifyEndOfBitstreamBuffer( |
| 320 int32 bitstream_buffer_id) { | 315 int32 bitstream_buffer_id) { |
| 321 client_->NotifyEndOfBitstreamBuffer(bitstream_buffer_id); | 316 client_->NotifyEndOfBitstreamBuffer(bitstream_buffer_id); |
| 322 } | 317 } |
| 323 | 318 |
| 324 void ThrottlingVDAClient::NotifyFlushDone() { | 319 void ThrottlingVDAClient::NotifyFlushDone() { |
| 325 if (!pending_pictures_.empty()) { | 320 if (!pending_pictures_.empty()) { |
| 326 base::MessageLoop::current()->PostDelayedTask( | 321 base::MessageLoop::current()->PostDelayedTask( |
| 327 FROM_HERE, | 322 FROM_HERE, |
| 328 base::Bind(&ThrottlingVDAClient::NotifyFlushDone, | 323 base::Bind(&ThrottlingVDAClient::NotifyFlushDone, |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 void CreateAndStartDecoder(); | 385 void CreateAndStartDecoder(); |
| 391 | 386 |
| 392 // VideoDecodeAccelerator::Client implementation. | 387 // VideoDecodeAccelerator::Client implementation. |
| 393 // The heart of the Client. | 388 // The heart of the Client. |
| 394 virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers, | 389 virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers, |
| 395 const gfx::Size& dimensions, | 390 const gfx::Size& dimensions, |
| 396 uint32 texture_target) OVERRIDE; | 391 uint32 texture_target) OVERRIDE; |
| 397 virtual void DismissPictureBuffer(int32 picture_buffer_id) OVERRIDE; | 392 virtual void DismissPictureBuffer(int32 picture_buffer_id) OVERRIDE; |
| 398 virtual void PictureReady(const media::Picture& picture) OVERRIDE; | 393 virtual void PictureReady(const media::Picture& picture) OVERRIDE; |
| 399 // Simple state changes. | 394 // Simple state changes. |
| 400 virtual void NotifyInitializeDone() OVERRIDE; | |
| 401 virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) OVERRIDE; | 395 virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) OVERRIDE; |
| 402 virtual void NotifyFlushDone() OVERRIDE; | 396 virtual void NotifyFlushDone() OVERRIDE; |
| 403 virtual void NotifyResetDone() OVERRIDE; | 397 virtual void NotifyResetDone() OVERRIDE; |
| 404 virtual void NotifyError(VideoDecodeAccelerator::Error error) OVERRIDE; | 398 virtual void NotifyError(VideoDecodeAccelerator::Error error) OVERRIDE; |
| 405 | 399 |
| 406 void OutputFrameDeliveryTimes(base::File* output); | 400 void OutputFrameDeliveryTimes(base::File* output); |
| 407 | 401 |
| 408 void NotifyFrameDropped(int32 picture_buffer_id); | 402 void NotifyFrameDropped(int32 picture_buffer_id); |
| 409 | 403 |
| 410 // Simple getters for inspecting the state of the Client. | 404 // Simple getters for inspecting the state of the Client. |
| 411 int num_done_bitstream_buffers() { return num_done_bitstream_buffers_; } | 405 int num_done_bitstream_buffers() { return num_done_bitstream_buffers_; } |
| 412 int num_skipped_fragments() { return num_skipped_fragments_; } | 406 int num_skipped_fragments() { return num_skipped_fragments_; } |
| 413 int num_queued_fragments() { return num_queued_fragments_; } | 407 int num_queued_fragments() { return num_queued_fragments_; } |
| 414 int num_decoded_frames(); | 408 int num_decoded_frames(); |
| 415 double frames_per_second(); | 409 double frames_per_second(); |
| 416 // Return the median of the decode time in milliseconds. | 410 // Return the median of the decode time in milliseconds. |
| 417 int decode_time_median(); | 411 int decode_time_median(); |
| 418 bool decoder_deleted() { return !decoder_.get(); } | 412 bool decoder_deleted() { return !decoder_.get(); } |
| 419 | 413 |
| 420 private: | 414 private: |
| 421 typedef std::map<int, media::PictureBuffer*> PictureBufferById; | 415 typedef std::map<int, media::PictureBuffer*> PictureBufferById; |
| 422 | 416 |
| 423 void SetState(ClientState new_state); | 417 void SetState(ClientState new_state); |
| 418 void FinishInitialization(); |
| 424 | 419 |
| 425 // Delete the associated decoder helper. | 420 // Delete the associated decoder helper. |
| 426 void DeleteDecoder(); | 421 void DeleteDecoder(); |
| 427 | 422 |
| 428 // Compute & return the first encoded bytes (including a start frame) to send | 423 // Compute & return the first encoded bytes (including a start frame) to send |
| 429 // to the decoder, starting at |start_pos| and returning one fragment. Skips | 424 // to the decoder, starting at |start_pos| and returning one fragment. Skips |
| 430 // to the first decodable position. | 425 // to the first decodable position. |
| 431 std::string GetBytesForFirstFragment(size_t start_pos, size_t* end_pos); | 426 std::string GetBytesForFirstFragment(size_t start_pos, size_t* end_pos); |
| 432 // Compute & return the encoded bytes of next fragment to send to the decoder | 427 // Compute & return the encoded bytes of next fragment to send to the decoder |
| 433 // (based on |start_pos|). | 428 // (based on |start_pos|). |
| 434 std::string GetBytesForNextFragment(size_t start_pos, size_t* end_pos); | 429 std::string GetBytesForNextFragment(size_t start_pos, size_t* end_pos); |
| 435 // Helpers for GetBytesForNextFragment above. | 430 // Helpers for GetBytesForNextFragment above. |
| 436 void GetBytesForNextNALU(size_t start_pos, size_t* end_pos); // For h.264. | 431 void GetBytesForNextNALU(size_t start_pos, size_t* end_pos); // For h.264. |
| 437 std::string GetBytesForNextFrame( | 432 std::string GetBytesForNextFrame( |
| 438 size_t start_pos, size_t* end_pos); // For VP8. | 433 size_t start_pos, size_t* end_pos); // For VP8. |
| 439 | 434 |
| 440 // Request decode of the next fragment in the encoded data. | 435 // Request decode of the next fragment in the encoded data. |
| 441 void DecodeNextFragment(); | 436 void DecodeNextFragment(); |
| 442 | 437 |
| 443 RenderingHelper* rendering_helper_; | 438 RenderingHelper* rendering_helper_; |
| 444 int rendering_window_id_; | 439 int rendering_window_id_; |
| 445 std::string encoded_data_; | 440 std::string encoded_data_; |
| 446 const int num_in_flight_decodes_; | 441 const int num_in_flight_decodes_; |
| 447 int outstanding_decodes_; | 442 int outstanding_decodes_; |
| 448 size_t encoded_data_next_pos_to_decode_; | 443 size_t encoded_data_next_pos_to_decode_; |
| 449 int next_bitstream_buffer_id_; | 444 int next_bitstream_buffer_id_; |
| 450 ClientStateNotification<ClientState>* note_; | 445 ClientStateNotification<ClientState>* note_; |
| 451 scoped_ptr<VideoDecodeAccelerator> decoder_; | 446 scoped_ptr<VideoDecodeAccelerator> decoder_; |
| 447 scoped_ptr<base::WeakPtrFactory<VideoDecodeAccelerator> > |
| 448 weak_decoder_factory_; |
| 452 std::set<int> outstanding_texture_ids_; | 449 std::set<int> outstanding_texture_ids_; |
| 453 int remaining_play_throughs_; | 450 int remaining_play_throughs_; |
| 454 int reset_after_frame_num_; | 451 int reset_after_frame_num_; |
| 455 int delete_decoder_state_; | 452 int delete_decoder_state_; |
| 456 ClientState state_; | 453 ClientState state_; |
| 457 int num_skipped_fragments_; | 454 int num_skipped_fragments_; |
| 458 int num_queued_fragments_; | 455 int num_queued_fragments_; |
| 459 int num_decoded_frames_; | 456 int num_decoded_frames_; |
| 460 int num_done_bitstream_buffers_; | 457 int num_done_bitstream_buffers_; |
| 461 PictureBufferById picture_buffers_by_id_; | 458 PictureBufferById picture_buffers_by_id_; |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 568 device.Pass(), | 565 device.Pass(), |
| 569 base::MessageLoopProxy::current())); | 566 base::MessageLoopProxy::current())); |
| 570 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) | 567 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) |
| 571 CHECK_EQ(gfx::kGLImplementationDesktopGL, gfx::GetGLImplementation()) | 568 CHECK_EQ(gfx::kGLImplementationDesktopGL, gfx::GetGLImplementation()) |
| 572 << "Hardware video decode does not work with OSMesa"; | 569 << "Hardware video decode does not work with OSMesa"; |
| 573 decoder_.reset(new VaapiVideoDecodeAccelerator( | 570 decoder_.reset(new VaapiVideoDecodeAccelerator( |
| 574 static_cast<Display*>(rendering_helper_->GetGLDisplay()), | 571 static_cast<Display*>(rendering_helper_->GetGLDisplay()), |
| 575 base::Bind(&DoNothingReturnTrue))); | 572 base::Bind(&DoNothingReturnTrue))); |
| 576 #endif // OS_WIN | 573 #endif // OS_WIN |
| 577 CHECK(decoder_.get()); | 574 CHECK(decoder_.get()); |
| 575 weak_decoder_factory_.reset( |
| 576 new base::WeakPtrFactory<VideoDecodeAccelerator>(decoder_.get())); |
| 578 SetState(CS_DECODER_SET); | 577 SetState(CS_DECODER_SET); |
| 579 if (decoder_deleted()) | 578 if (decoder_deleted()) |
| 580 return; | 579 return; |
| 581 | 580 |
| 582 CHECK(decoder_->Initialize(profile_, client)); | 581 CHECK(decoder_->Initialize(profile_, client)); |
| 582 FinishInitialization(); |
| 583 } | 583 } |
| 584 | 584 |
| 585 void GLRenderingVDAClient::ProvidePictureBuffers( | 585 void GLRenderingVDAClient::ProvidePictureBuffers( |
| 586 uint32 requested_num_of_buffers, | 586 uint32 requested_num_of_buffers, |
| 587 const gfx::Size& dimensions, | 587 const gfx::Size& dimensions, |
| 588 uint32 texture_target) { | 588 uint32 texture_target) { |
| 589 if (decoder_deleted()) | 589 if (decoder_deleted()) |
| 590 return; | 590 return; |
| 591 std::vector<media::PictureBuffer> buffers; | 591 std::vector<media::PictureBuffer> buffers; |
| 592 | 592 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 652 CHECK(picture_buffer); | 652 CHECK(picture_buffer); |
| 653 if (!suppress_rendering_) { | 653 if (!suppress_rendering_) { |
| 654 rendering_helper_->RenderTexture(texture_target_, | 654 rendering_helper_->RenderTexture(texture_target_, |
| 655 picture_buffer->texture_id()); | 655 picture_buffer->texture_id()); |
| 656 } | 656 } |
| 657 | 657 |
| 658 if (num_decoded_frames() > delay_reuse_after_frame_num_) { | 658 if (num_decoded_frames() > delay_reuse_after_frame_num_) { |
| 659 base::MessageLoop::current()->PostDelayedTask( | 659 base::MessageLoop::current()->PostDelayedTask( |
| 660 FROM_HERE, | 660 FROM_HERE, |
| 661 base::Bind(&VideoDecodeAccelerator::ReusePictureBuffer, | 661 base::Bind(&VideoDecodeAccelerator::ReusePictureBuffer, |
| 662 decoder_->AsWeakPtr(), | 662 weak_decoder_factory_->GetWeakPtr(), |
| 663 picture.picture_buffer_id()), | 663 picture.picture_buffer_id()), |
| 664 kReuseDelay); | 664 kReuseDelay); |
| 665 } else { | 665 } else { |
| 666 decoder_->ReusePictureBuffer(picture.picture_buffer_id()); | 666 decoder_->ReusePictureBuffer(picture.picture_buffer_id()); |
| 667 } | 667 } |
| 668 } | 668 } |
| 669 | 669 |
| 670 void GLRenderingVDAClient::NotifyInitializeDone() { | |
| 671 SetState(CS_INITIALIZED); | |
| 672 initialize_done_ticks_ = base::TimeTicks::Now(); | |
| 673 | |
| 674 if (reset_after_frame_num_ == START_OF_STREAM_RESET) { | |
| 675 reset_after_frame_num_ = MID_STREAM_RESET; | |
| 676 decoder_->Reset(); | |
| 677 return; | |
| 678 } | |
| 679 | |
| 680 for (int i = 0; i < num_in_flight_decodes_; ++i) | |
| 681 DecodeNextFragment(); | |
| 682 DCHECK_EQ(outstanding_decodes_, num_in_flight_decodes_); | |
| 683 } | |
| 684 | |
| 685 void GLRenderingVDAClient::NotifyEndOfBitstreamBuffer( | 670 void GLRenderingVDAClient::NotifyEndOfBitstreamBuffer( |
| 686 int32 bitstream_buffer_id) { | 671 int32 bitstream_buffer_id) { |
| 687 // TODO(fischman): this test currently relies on this notification to make | 672 // TODO(fischman): this test currently relies on this notification to make |
| 688 // forward progress during a Reset(). But the VDA::Reset() API doesn't | 673 // forward progress during a Reset(). But the VDA::Reset() API doesn't |
| 689 // guarantee this, so stop relying on it (and remove the notifications from | 674 // guarantee this, so stop relying on it (and remove the notifications from |
| 690 // VaapiVideoDecodeAccelerator::FinishReset()). | 675 // VaapiVideoDecodeAccelerator::FinishReset()). |
| 691 ++num_done_bitstream_buffers_; | 676 ++num_done_bitstream_buffers_; |
| 692 --outstanding_decodes_; | 677 --outstanding_decodes_; |
| 693 if (decode_calls_per_second_ == 0) | 678 if (decode_calls_per_second_ == 0) |
| 694 DecodeNextFragment(); | 679 DecodeNextFragment(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 716 return; | 701 return; |
| 717 } else if (reset_after_frame_num_ == START_OF_STREAM_RESET) { | 702 } else if (reset_after_frame_num_ == START_OF_STREAM_RESET) { |
| 718 reset_after_frame_num_ = END_OF_STREAM_RESET; | 703 reset_after_frame_num_ = END_OF_STREAM_RESET; |
| 719 for (int i = 0; i < num_in_flight_decodes_; ++i) | 704 for (int i = 0; i < num_in_flight_decodes_; ++i) |
| 720 DecodeNextFragment(); | 705 DecodeNextFragment(); |
| 721 return; | 706 return; |
| 722 } | 707 } |
| 723 | 708 |
| 724 if (remaining_play_throughs_) { | 709 if (remaining_play_throughs_) { |
| 725 encoded_data_next_pos_to_decode_ = 0; | 710 encoded_data_next_pos_to_decode_ = 0; |
| 726 NotifyInitializeDone(); | 711 FinishInitialization(); |
| 727 return; | 712 return; |
| 728 } | 713 } |
| 729 | 714 |
| 730 SetState(CS_RESET); | 715 SetState(CS_RESET); |
| 731 if (!decoder_deleted()) | 716 if (!decoder_deleted()) |
| 732 DeleteDecoder(); | 717 DeleteDecoder(); |
| 733 } | 718 } |
| 734 | 719 |
| 735 void GLRenderingVDAClient::NotifyError(VideoDecodeAccelerator::Error error) { | 720 void GLRenderingVDAClient::NotifyError(VideoDecodeAccelerator::Error error) { |
| 736 SetState(CS_ERROR); | 721 SetState(CS_ERROR); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 761 | 746 |
| 762 void GLRenderingVDAClient::SetState(ClientState new_state) { | 747 void GLRenderingVDAClient::SetState(ClientState new_state) { |
| 763 note_->Notify(new_state); | 748 note_->Notify(new_state); |
| 764 state_ = new_state; | 749 state_ = new_state; |
| 765 if (!remaining_play_throughs_ && new_state == delete_decoder_state_) { | 750 if (!remaining_play_throughs_ && new_state == delete_decoder_state_) { |
| 766 CHECK(!decoder_deleted()); | 751 CHECK(!decoder_deleted()); |
| 767 DeleteDecoder(); | 752 DeleteDecoder(); |
| 768 } | 753 } |
| 769 } | 754 } |
| 770 | 755 |
| 756 void GLRenderingVDAClient::FinishInitialization() { |
| 757 SetState(CS_INITIALIZED); |
| 758 initialize_done_ticks_ = base::TimeTicks::Now(); |
| 759 |
| 760 if (reset_after_frame_num_ == START_OF_STREAM_RESET) { |
| 761 reset_after_frame_num_ = MID_STREAM_RESET; |
| 762 decoder_->Reset(); |
| 763 return; |
| 764 } |
| 765 |
| 766 for (int i = 0; i < num_in_flight_decodes_; ++i) |
| 767 DecodeNextFragment(); |
| 768 DCHECK_EQ(outstanding_decodes_, num_in_flight_decodes_); |
| 769 } |
| 770 |
| 771 void GLRenderingVDAClient::DeleteDecoder() { | 771 void GLRenderingVDAClient::DeleteDecoder() { |
| 772 if (decoder_deleted()) | 772 if (decoder_deleted()) |
| 773 return; | 773 return; |
| 774 weak_decoder_factory_.reset(); |
| 774 decoder_.release()->Destroy(); | 775 decoder_.release()->Destroy(); |
| 775 STLClearObject(&encoded_data_); | 776 STLClearObject(&encoded_data_); |
| 776 for (std::set<int>::iterator it = outstanding_texture_ids_.begin(); | 777 for (std::set<int>::iterator it = outstanding_texture_ids_.begin(); |
| 777 it != outstanding_texture_ids_.end(); ++it) { | 778 it != outstanding_texture_ids_.end(); ++it) { |
| 778 rendering_helper_->DeleteTexture(*it); | 779 rendering_helper_->DeleteTexture(*it); |
| 779 } | 780 } |
| 780 outstanding_texture_ids_.clear(); | 781 outstanding_texture_ids_.clear(); |
| 781 // Cascade through the rest of the states to simplify test code below. | 782 // Cascade through the rest of the states to simplify test code below. |
| 782 for (int i = state_ + 1; i < CS_MAX; ++i) | 783 for (int i = state_ + 1; i < CS_MAX; ++i) |
| 783 SetState(static_cast<ClientState>(i)); | 784 SetState(static_cast<ClientState>(i)); |
| (...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1568 } | 1569 } |
| 1569 if (it->first == "v" || it->first == "vmodule") | 1570 if (it->first == "v" || it->first == "vmodule") |
| 1570 continue; | 1571 continue; |
| 1571 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; | 1572 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; |
| 1572 } | 1573 } |
| 1573 | 1574 |
| 1574 base::ShadowingAtExitManager at_exit_manager; | 1575 base::ShadowingAtExitManager at_exit_manager; |
| 1575 | 1576 |
| 1576 return RUN_ALL_TESTS(); | 1577 return RUN_ALL_TESTS(); |
| 1577 } | 1578 } |
| OLD | NEW |