Isolated OnMediaSample in Chunker

Change-Id: I3af45543a1da1d1cf0b0741dd732dc71b2c30abe
This commit is contained in:
Aaron Vaage 2018-02-12 14:49:03 -08:00 committed by KongQun Yang
parent f125a4e91a
commit f2f88c159e
2 changed files with 52 additions and 46 deletions

View File

@ -48,57 +48,14 @@ Status ChunkingHandler::Process(std::unique_ptr<StreamData> stream_data) {
case StreamDataType::kSegmentInfo: case StreamDataType::kSegmentInfo:
VLOG(3) << "Droppping existing segment info."; VLOG(3) << "Droppping existing segment info.";
return Status::OK; return Status::OK;
case StreamDataType::kMediaSample: { case StreamDataType::kMediaSample:
const size_t stream_index = stream_data->stream_index; return OnMediaSample(std::move(stream_data));
DCHECK_NE(time_scales_[stream_index], 0u)
<< "kStreamInfo should arrive before kMediaSample";
if (stream_index != main_stream_index_ &&
!stream_data->media_sample->is_key_frame()) {
return Status(error::CHUNKING_ERROR,
"All non video samples should be key frames.");
}
// The streams are expected to be roughly synchronized, so we don't expect
// to see a lot of samples from one stream but no samples from another
// stream.
// The value is kind of arbitrary here. For a 24fps video, it is ~40s.
const size_t kMaxCachedSamplesPerStream = 1000u;
if (num_cached_samples_[stream_index] >= kMaxCachedSamplesPerStream) {
LOG(ERROR) << "Streams are not synchronized:";
for (size_t i = 0; i < num_cached_samples_.size(); ++i)
LOG(ERROR) << " [Stream " << i << "] " << num_cached_samples_[i];
return Status(error::CHUNKING_ERROR, "Streams are not synchronized.");
}
cached_media_sample_stream_data_.push(std::move(stream_data));
++num_cached_samples_[stream_index];
// If we have cached samples from every stream, the first sample in
// |cached_media_samples_stream_data_| is guaranteed to be the earliest
// sample. Extract and process that sample.
if (std::all_of(num_cached_samples_.begin(), num_cached_samples_.end(),
[](size_t num_samples) { return num_samples > 0; })) {
while (true) {
const size_t top_stream_index =
cached_media_sample_stream_data_.top()->stream_index;
Status status = ProcessMediaSampleStreamData(
*cached_media_sample_stream_data_.top());
if (!status.ok())
return status;
cached_media_sample_stream_data_.pop();
if (--num_cached_samples_[top_stream_index] == 0)
break;
}
}
return Status::OK;
}
default: default:
VLOG(3) << "Stream data type " VLOG(3) << "Stream data type "
<< static_cast<int>(stream_data->stream_data_type) << " ignored."; << static_cast<int>(stream_data->stream_data_type) << " ignored.";
break;
}
return Dispatch(std::move(stream_data)); return Dispatch(std::move(stream_data));
} }
}
Status ChunkingHandler::OnFlushRequest(size_t input_stream_index) { Status ChunkingHandler::OnFlushRequest(size_t input_stream_index) {
// Process all cached samples. // Process all cached samples.
@ -172,6 +129,53 @@ Status ChunkingHandler::OnScte35Event(
return Status::OK; return Status::OK;
} }
Status ChunkingHandler::OnMediaSample(std::unique_ptr<StreamData> stream_data) {
DCHECK_EQ(StreamDataType::kMediaSample, stream_data->stream_data_type);
const size_t stream_index = stream_data->stream_index;
DCHECK_NE(time_scales_[stream_index], 0u)
<< "kStreamInfo should arrive before kMediaSample";
if (stream_index != main_stream_index_ &&
!stream_data->media_sample->is_key_frame()) {
return Status(error::CHUNKING_ERROR,
"All non video samples should be key frames.");
}
// The streams are expected to be roughly synchronized, so we don't expect
// to see a lot of samples from one stream but no samples from another
// stream.
// The value is kind of arbitrary here. For a 24fps video, it is ~40s.
const size_t kMaxCachedSamplesPerStream = 1000u;
if (num_cached_samples_[stream_index] >= kMaxCachedSamplesPerStream) {
LOG(ERROR) << "Streams are not synchronized:";
for (size_t i = 0; i < num_cached_samples_.size(); ++i)
LOG(ERROR) << " [Stream " << i << "] " << num_cached_samples_[i];
return Status(error::CHUNKING_ERROR, "Streams are not synchronized.");
}
cached_media_sample_stream_data_.push(std::move(stream_data));
++num_cached_samples_[stream_index];
// If we have cached samples from every stream, the first sample in
// |cached_media_samples_stream_data_| is guaranteed to be the earliest
// sample. Extract and process that sample.
if (std::all_of(num_cached_samples_.begin(), num_cached_samples_.end(),
[](size_t num_samples) { return num_samples > 0; })) {
while (true) {
const size_t top_stream_index =
cached_media_sample_stream_data_.top()->stream_index;
Status status =
ProcessMediaSampleStreamData(*cached_media_sample_stream_data_.top());
if (!status.ok())
return status;
cached_media_sample_stream_data_.pop();
if (--num_cached_samples_[top_stream_index] == 0)
break;
}
}
return Status::OK;
}
Status ChunkingHandler::ProcessMainMediaSample(const MediaSample* sample) { Status ChunkingHandler::ProcessMainMediaSample(const MediaSample* sample) {
const bool is_key_frame = sample->is_key_frame(); const bool is_key_frame = sample->is_key_frame();
const int64_t timestamp = sample->dts(); const int64_t timestamp = sample->dts();

View File

@ -67,6 +67,8 @@ class ChunkingHandler : public MediaHandler {
Status OnScte35Event(uint64_t stream_index, Status OnScte35Event(uint64_t stream_index,
std::shared_ptr<const Scte35Event> event); std::shared_ptr<const Scte35Event> event);
Status OnMediaSample(std::unique_ptr<StreamData> stream_data);
// Processes main media sample and apply chunking if needed. // Processes main media sample and apply chunking if needed.
Status ProcessMainMediaSample(const MediaSample* sample); Status ProcessMainMediaSample(const MediaSample* sample);