15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/stream_parser.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/base/buffers.h" 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/base/stream_parser_buffer.h" 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuStreamParser::InitParameters::InitParameters(base::TimeDelta duration) 135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu : duration(duration), 145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu auto_update_timestamp_offset(false), 155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu liveness(Demuxer::LIVENESS_UNKNOWN) { 165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StreamParser::StreamParser() {} 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StreamParser::~StreamParser() {} 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static bool MergeBufferQueuesInternal( 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::vector<const StreamParser::BufferQueue*>& buffer_queues, 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) StreamParser::BufferQueue* merged_buffers) { 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Instead of std::merge usage, this method implements a custom merge because: 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // 1) |buffer_queues| may contain N queues, 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // 2) we must detect and return false if any of the queues in |buffer_queues| 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // is unsorted, and 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // 3) we must detect and return false if any of the buffers in |buffer_queues| 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // has a decode timestamp prior to the last, if any, buffer in 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // |merged_buffers|. 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(wolenetz/acolwell): Refactor stream parsers to eliminate need for 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // this large grain merge. See http://crbug.com/338484. 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Done if no inputs to merge. 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (buffer_queues.empty()) 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Build a vector of iterators, one for each input, to traverse inputs. 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The union of these iterators points to the set of candidate buffers 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // for being appended to |merged_buffers|. 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t num_itrs = buffer_queues.size(); 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<StreamParser::BufferQueue::const_iterator> itrs(num_itrs); 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t i = 0; i < num_itrs; ++i) 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) itrs[i] = buffer_queues[i]->begin(); 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // |last_decode_timestamp| tracks the lower bound, if any, that all candidate 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // buffers must not be less than. If |merged_buffers| already has buffers, 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // initialize |last_decode_timestamp| to the decode timestamp of the last 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // buffer in it. 516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DecodeTimestamp last_decode_timestamp = kNoDecodeTimestamp(); 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!merged_buffers->empty()) 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) last_decode_timestamp = merged_buffers->back()->GetDecodeTimestamp(); 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Repeatedly select and append the next buffer from the candidate buffers 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // until either: 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // 1) returning false, to indicate detection of decreasing DTS in some queue, 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // when a candidate buffer has decode timestamp below 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // |last_decode_timestamp|, which means either an input buffer wasn't 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // sorted correctly or had a buffer with decode timestamp below the last 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // buffer, if any, in |merged_buffers|, or 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // 2) returning true when all buffers have been merged successfully; 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // equivalently, when all of the iterators in |itrs| have reached the end 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // of their respective queue from |buffer_queues|. 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(wolenetz/acolwell): Ideally, we would use a heap to store the head of 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // all queues and pop the head with lowest decode timestamp in log(N) time. 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // However, N will typically be small and usage of this implementation is 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // meant to be short-term. See http://crbug.com/338484. 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while (true) { 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Tracks which queue's iterator is pointing to the candidate buffer to 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // append next, or -1 if no candidate buffers found. This indexes |itrs|. 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int index_of_queue_with_next_decode_timestamp = -1; 736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DecodeTimestamp next_decode_timestamp = kNoDecodeTimestamp(); 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Scan each of the iterators for |buffer_queues| to find the candidate 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // buffer, if any, that has the lowest decode timestamp. 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t i = 0; i < num_itrs; ++i) { 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (itrs[i] == buffer_queues[i]->end()) 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Extract the candidate buffer's decode timestamp. 826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DecodeTimestamp ts = (*itrs[i])->GetDecodeTimestamp(); 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (last_decode_timestamp != kNoDecodeTimestamp() && 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ts < last_decode_timestamp) 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (ts < next_decode_timestamp || 896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) next_decode_timestamp == kNoDecodeTimestamp()) { 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Remember the decode timestamp and queue iterator index for this 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // potentially winning candidate buffer. 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) next_decode_timestamp = ts; 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) index_of_queue_with_next_decode_timestamp = i; 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // All done if no further candidate buffers exist. 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (index_of_queue_with_next_decode_timestamp == -1) 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Otherwise, append the winning candidate buffer to |merged_buffers|, 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // remember its decode timestamp as |last_decode_timestamp| now that it is 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the last buffer in |merged_buffers|, advance the corresponding 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // input BufferQueue iterator, and continue. 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<StreamParserBuffer> buffer = 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *itrs[index_of_queue_with_next_decode_timestamp]; 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) last_decode_timestamp = buffer->GetDecodeTimestamp(); 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) merged_buffers->push_back(buffer); 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++itrs[index_of_queue_with_next_decode_timestamp]; 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool MergeBufferQueues(const StreamParser::BufferQueue& audio_buffers, 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const StreamParser::BufferQueue& video_buffers, 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const StreamParser::TextBufferQueueMap& text_buffers, 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) StreamParser::BufferQueue* merged_buffers) { 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(merged_buffers); 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Prepare vector containing pointers to any provided non-empty buffer queues. 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<const StreamParser::BufferQueue*> buffer_queues; 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!audio_buffers.empty()) 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) buffer_queues.push_back(&audio_buffers); 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!video_buffers.empty()) 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) buffer_queues.push_back(&video_buffers); 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (StreamParser::TextBufferQueueMap::const_iterator map_itr = 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) text_buffers.begin(); 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) map_itr != text_buffers.end(); 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) map_itr++) { 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!map_itr->second.empty()) 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) buffer_queues.push_back(&(map_itr->second)); 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Do the merge. 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return MergeBufferQueuesInternal(buffer_queues, merged_buffers); 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace media 138