From e93b1fe8fd458b93ca0b1dc1264646b09c65020d Mon Sep 17 00:00:00 2001 From: Ilya Nikolaevskiy Date: Tue, 8 Oct 2019 13:17:09 +0200 Subject: [PATCH] Improve bitstream dumping logic to handle multiple SLs correctly Before this change all layers were glued together at the receive side into a single IVF frame. This confuses most bitstream parsers. Since this change all spatial layers would be written as separate frames on the receive side also (on the send side it's already done that way). Bug: none Change-Id: I68543e4d4b336f87699ec3b4a113b8c93af0b7e4 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/156082 Reviewed-by: Sergey Silkin Commit-Queue: Ilya Nikolaevskiy Cr-Commit-Position: refs/heads/master@{#29401} --- .../video_coding/utility/ivf_file_writer.cc | 36 ++++++++++++++++--- .../video_coding/utility/ivf_file_writer.h | 3 ++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/modules/video_coding/utility/ivf_file_writer.cc b/modules/video_coding/utility/ivf_file_writer.cc index c66809b87c..46b8e87ba3 100644 --- a/modules/video_coding/utility/ivf_file_writer.cc +++ b/modules/video_coding/utility/ivf_file_writer.cc @@ -158,25 +158,51 @@ bool IvfFileWriter::WriteFrame(const EncodedImage& encoded_image, } last_timestamp_ = timestamp; + bool written_frames = false; + size_t max_sl_index = encoded_image.SpatialIndex().value_or(0); + const uint8_t* data = encoded_image.data(); + for (size_t sl_idx = 0; sl_idx <= max_sl_index; ++sl_idx) { + size_t cur_size = encoded_image.SpatialLayerFrameSize(sl_idx).value_or(0); + if (cur_size > 0) { + written_frames = true; + if (!WriteOneSpatialLayer(timestamp, data, cur_size)) { + return false; + } + data += cur_size; + } + } + + // If frame has only one spatial layer it won't have any spatial layers' + // sizes. Therefore this case should be addressed separately. + if (!written_frames) { + return WriteOneSpatialLayer(timestamp, data, encoded_image.size()); + } else { + return true; + } +} + +bool IvfFileWriter::WriteOneSpatialLayer(int64_t timestamp, + const uint8_t* data, + size_t size) { const size_t kFrameHeaderSize = 12; if (byte_limit_ != 0 && - bytes_written_ + kFrameHeaderSize + encoded_image.size() > byte_limit_) { + bytes_written_ + kFrameHeaderSize + size > byte_limit_) { RTC_LOG(LS_WARNING) << "Closing IVF file due to reaching size limit: " << byte_limit_ << " bytes."; Close(); return false; } uint8_t frame_header[kFrameHeaderSize] = {}; - ByteWriter::WriteLittleEndian( - &frame_header[0], static_cast(encoded_image.size())); + ByteWriter::WriteLittleEndian(&frame_header[0], + static_cast(size)); ByteWriter::WriteLittleEndian(&frame_header[4], timestamp); if (!file_.Write(frame_header, kFrameHeaderSize) || - !file_.Write(encoded_image.data(), encoded_image.size())) { + !file_.Write(data, size)) { RTC_LOG(LS_ERROR) << "Unable to write frame to file."; return false; } - bytes_written_ += kFrameHeaderSize + encoded_image.size(); + bytes_written_ += kFrameHeaderSize + size; ++num_frames_; return true; diff --git a/modules/video_coding/utility/ivf_file_writer.h b/modules/video_coding/utility/ivf_file_writer.h index 7d0d6aa50c..5de67acdb2 100644 --- a/modules/video_coding/utility/ivf_file_writer.h +++ b/modules/video_coding/utility/ivf_file_writer.h @@ -42,6 +42,9 @@ class IvfFileWriter { bool WriteHeader(); bool InitFromFirstFrame(const EncodedImage& encoded_image, VideoCodecType codec_type); + bool WriteOneSpatialLayer(int64_t timestamp, + const uint8_t* data, + size_t size); VideoCodecType codec_type_; size_t bytes_written_;