Commit 38b3db9f authored by fischman@chromium.org's avatar fischman@chromium.org

Strip IVF headers from VP8 streams before sending them to the OMX decoder.

BUG=136962
TEST=this runs through most of the input file displaying lots of pretty frames before segfaulting in the SEC-OMX library: DISPLAY=:0 ./Debug/omx_video_decode_accelerator_unittest  --gtest_filter=DecodeVariations/VideoDecodeAcceleratorTest.TestSimpleDecode/0 --test_video_data='test-25fps.vp8:320:240:250:250:50:175:11'


Review URL: https://chromiumcodereview.appspot.com/10828022

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148479 0039d316-1c4b-4281-b951-d872f2087c98
parent 79cea75c
...@@ -475,12 +475,10 @@ void OmxVideoDecodeAccelerator::Destroy() { ...@@ -475,12 +475,10 @@ void OmxVideoDecodeAccelerator::Destroy() {
void OmxVideoDecodeAccelerator::BeginTransitionToState( void OmxVideoDecodeAccelerator::BeginTransitionToState(
OMX_STATETYPE new_state) { OMX_STATETYPE new_state) {
DCHECK_EQ(message_loop_, MessageLoop::current()); DCHECK_EQ(message_loop_, MessageLoop::current());
DCHECK_NE(current_state_change_, NO_TRANSITION); if (new_state != OMX_StateInvalid)
DCHECK_NE(current_state_change_, ERRORING); DCHECK_NE(current_state_change_, NO_TRANSITION);
if (current_state_change_ == NO_TRANSITION || if (current_state_change_ == ERRORING)
current_state_change_ == ERRORING) {
return; return;
}
OMX_ERRORTYPE result = OMX_SendCommand( OMX_ERRORTYPE result = OMX_SendCommand(
component_handle_, OMX_CommandStateSet, new_state, 0); component_handle_, OMX_CommandStateSet, new_state, 0);
RETURN_ON_OMX_FAILURE(result, "SendCommand(OMX_CommandStateSet) failed", RETURN_ON_OMX_FAILURE(result, "SendCommand(OMX_CommandStateSet) failed",
...@@ -960,7 +958,8 @@ void OmxVideoDecodeAccelerator::EventHandlerCompleteTask(OMX_EVENTTYPE event, ...@@ -960,7 +958,8 @@ void OmxVideoDecodeAccelerator::EventHandlerCompleteTask(OMX_EVENTTYPE event,
} }
return; return;
case OMX_EventPortSettingsChanged: case OMX_EventPortSettingsChanged:
if (data2 == OMX_IndexParamPortDefinition) { if ((data2 == OMX_IndexParamPortDefinition) || // Tegra2/3
(data2 == 0)) { // Exynos SEC-OMX; http://crosbug.com/p/11665
DCHECK_EQ(data1, output_port_); DCHECK_EQ(data1, output_port_);
// This event is only used for output resize; kick off handling that by // This event is only used for output resize; kick off handling that by
// pausing the output port. // pausing the output port.
......
...@@ -239,13 +239,13 @@ class GLRenderingVDAClient : public VideoDecodeAccelerator::Client { ...@@ -239,13 +239,13 @@ class GLRenderingVDAClient : public VideoDecodeAccelerator::Client {
// Delete the associated OMX decoder helper. // Delete the associated OMX decoder helper.
void DeleteDecoder(); void DeleteDecoder();
// Compute & return in |*end_pos| the end position for the next batch of // Compute & return the next encoded bytes to send to the decoder (based on
// fragments to ship to the decoder (based on |start_pos| & // |start_pos| & |num_fragments_per_decode_|).
// |num_fragments_per_decode_|). std::string GetBytesForNextFragments(size_t start_pos, size_t* end_pos);
void GetRangeForNextFragments(size_t start_pos, size_t* end_pos);
// Helpers for GetRangeForNextFragments above. // Helpers for GetRangeForNextFragments above.
void GetRangeForNextNALUs(size_t start_pos, size_t* end_pos); // For h.264. void GetBytesForNextNALUs(size_t start_pos, size_t* end_pos); // For h.264.
void GetRangeForNextFrames(size_t start_pos, size_t* end_pos); // For VP8. std::string GetBytesForNextFrames(
size_t start_pos, size_t* end_pos); // For VP8.
// Request decode of the next batch of fragments in the encoded data. // Request decode of the next batch of fragments in the encoded data.
void DecodeNextFragments(); void DecodeNextFragments();
...@@ -392,11 +392,6 @@ void GLRenderingVDAClient::PictureReady(const media::Picture& picture) { ...@@ -392,11 +392,6 @@ void GLRenderingVDAClient::PictureReady(const media::Picture& picture) {
return; return;
last_frame_delivered_ticks_ = base::TimeTicks::Now(); last_frame_delivered_ticks_ = base::TimeTicks::Now();
// Because we feed the decoder a limited number of fragments at a time, we can
// be sure that the bitstream buffer from which a frame comes has a limited
// range. Assert that.
CHECK_GE((picture.bitstream_buffer_id() + 1) * num_fragments_per_decode_,
num_decoded_frames_);
CHECK_LE(picture.bitstream_buffer_id(), next_bitstream_buffer_id_); CHECK_LE(picture.bitstream_buffer_id(), next_bitstream_buffer_id_);
++num_decoded_frames_; ++num_decoded_frames_;
...@@ -505,17 +500,17 @@ void GLRenderingVDAClient::DeleteDecoder() { ...@@ -505,17 +500,17 @@ void GLRenderingVDAClient::DeleteDecoder() {
SetState(static_cast<ClientState>(i)); SetState(static_cast<ClientState>(i));
} }
void GLRenderingVDAClient::GetRangeForNextFragments( std::string GLRenderingVDAClient::GetBytesForNextFragments(
size_t start_pos, size_t* end_pos) { size_t start_pos, size_t* end_pos) {
if (profile_ < media::H264PROFILE_MAX) { if (profile_ < media::H264PROFILE_MAX) {
GetRangeForNextNALUs(start_pos, end_pos); GetBytesForNextNALUs(start_pos, end_pos);
return; return encoded_data_.substr(start_pos, *end_pos - start_pos);
} }
DCHECK_LE(profile_, media::VP8PROFILE_MAX); DCHECK_LE(profile_, media::VP8PROFILE_MAX);
GetRangeForNextFrames(start_pos, end_pos); return GetBytesForNextFrames(start_pos, end_pos);
} }
void GLRenderingVDAClient::GetRangeForNextNALUs( void GLRenderingVDAClient::GetBytesForNextNALUs(
size_t start_pos, size_t* end_pos) { size_t start_pos, size_t* end_pos) {
*end_pos = start_pos; *end_pos = start_pos;
CHECK(LookingAtNAL(encoded_data_, start_pos)); CHECK(LookingAtNAL(encoded_data_, start_pos));
...@@ -532,19 +527,22 @@ void GLRenderingVDAClient::GetRangeForNextNALUs( ...@@ -532,19 +527,22 @@ void GLRenderingVDAClient::GetRangeForNextNALUs(
} }
} }
void GLRenderingVDAClient::GetRangeForNextFrames( std::string GLRenderingVDAClient::GetBytesForNextFrames(
size_t start_pos, size_t* end_pos) { size_t start_pos, size_t* end_pos) {
// Helpful description: http://wiki.multimedia.cx/index.php?title=IVF // Helpful description: http://wiki.multimedia.cx/index.php?title=IVF
*end_pos = start_pos; std::string bytes;
if (start_pos == 0) if (start_pos == 0)
*end_pos = 32; start_pos = 32; // Skip IVF header.
*end_pos = start_pos;
for (int i = 0; i < num_fragments_per_decode_; ++i) { for (int i = 0; i < num_fragments_per_decode_; ++i) {
uint32 frame_size = *reinterpret_cast<uint32*>(&encoded_data_[*end_pos]); uint32 frame_size = *reinterpret_cast<uint32*>(&encoded_data_[*end_pos]);
*end_pos += 12; // Skip frame header. *end_pos += 12; // Skip frame header.
bytes.append(encoded_data_.substr(*end_pos, *end_pos + frame_size));
*end_pos += frame_size; *end_pos += frame_size;
if (*end_pos + 12 >= encoded_data_.size()) if (*end_pos + 12 >= encoded_data_.size())
return; return bytes;
} }
return bytes;
} }
void GLRenderingVDAClient::DecodeNextFragments() { void GLRenderingVDAClient::DecodeNextFragments() {
...@@ -557,20 +555,20 @@ void GLRenderingVDAClient::DecodeNextFragments() { ...@@ -557,20 +555,20 @@ void GLRenderingVDAClient::DecodeNextFragments() {
} }
return; return;
} }
size_t start_pos = encoded_data_next_pos_to_decode_;
size_t end_pos; size_t end_pos;
GetRangeForNextFragments(start_pos, &end_pos); std::string next_fragment_bytes =
GetBytesForNextFragments(encoded_data_next_pos_to_decode_, &end_pos);
size_t next_fragment_size = next_fragment_bytes.size();
// Populate the shared memory buffer w/ the fragments, duplicate its handle, // Populate the shared memory buffer w/ the fragments, duplicate its handle,
// and hand it off to the decoder. // and hand it off to the decoder.
base::SharedMemory shm; base::SharedMemory shm;
CHECK(shm.CreateAndMapAnonymous(end_pos - start_pos)) CHECK(shm.CreateAndMapAnonymous(next_fragment_size));
<< start_pos << ", " << end_pos; memcpy(shm.memory(), next_fragment_bytes.data(), next_fragment_size);
memcpy(shm.memory(), encoded_data_.data() + start_pos, end_pos - start_pos);
base::SharedMemoryHandle dup_handle; base::SharedMemoryHandle dup_handle;
CHECK(shm.ShareToProcess(base::Process::Current().handle(), &dup_handle)); CHECK(shm.ShareToProcess(base::Process::Current().handle(), &dup_handle));
media::BitstreamBuffer bitstream_buffer( media::BitstreamBuffer bitstream_buffer(
next_bitstream_buffer_id_++, dup_handle, end_pos - start_pos); next_bitstream_buffer_id_++, dup_handle, next_fragment_size);
decoder_->Decode(bitstream_buffer); decoder_->Decode(bitstream_buffer);
++outstanding_decodes_; ++outstanding_decodes_;
encoded_data_next_pos_to_decode_ = end_pos; encoded_data_next_pos_to_decode_ = end_pos;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment