LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/video_coding/utility - ivf_file_writer.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 116 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 7 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
       3             :  *
       4             :  *  Use of this source code is governed by a BSD-style license
       5             :  *  that can be found in the LICENSE file in the root of the source
       6             :  *  tree. An additional intellectual property rights grant can be found
       7             :  *  in the file PATENTS.  All contributing project authors may
       8             :  *  be found in the AUTHORS file in the root of the source tree.
       9             :  */
      10             : 
      11             : #include "webrtc/modules/video_coding/utility/ivf_file_writer.h"
      12             : 
      13             : #include <string>
      14             : #include <utility>
      15             : 
      16             : #include "webrtc/base/checks.h"
      17             : #include "webrtc/base/logging.h"
      18             : #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
      19             : 
      20             : // TODO(palmkvist): make logging more informative in the absence of a file name
      21             : // (or get one)
      22             : 
      23             : namespace webrtc {
      24             : 
      25             : const size_t kIvfHeaderSize = 32;
      26             : 
      27           0 : IvfFileWriter::IvfFileWriter(rtc::File file, size_t byte_limit)
      28             :     : codec_type_(kVideoCodecUnknown),
      29             :       bytes_written_(0),
      30             :       byte_limit_(byte_limit),
      31             :       num_frames_(0),
      32             :       width_(0),
      33             :       height_(0),
      34             :       last_timestamp_(-1),
      35             :       using_capture_timestamps_(false),
      36           0 :       file_(std::move(file)) {
      37           0 :   RTC_DCHECK(byte_limit == 0 || kIvfHeaderSize <= byte_limit)
      38           0 :       << "The byte_limit is too low, not even the header will fit.";
      39           0 : }
      40             : 
      41           0 : IvfFileWriter::~IvfFileWriter() {
      42           0 :   Close();
      43           0 : }
      44             : 
      45           0 : std::unique_ptr<IvfFileWriter> IvfFileWriter::Wrap(rtc::File file,
      46             :                                                    size_t byte_limit) {
      47             :   return std::unique_ptr<IvfFileWriter>(
      48           0 :       new IvfFileWriter(std::move(file), byte_limit));
      49             : }
      50             : 
      51           0 : bool IvfFileWriter::WriteHeader() {
      52           0 :   if (!file_.Seek(0)) {
      53           0 :     LOG(LS_WARNING) << "Unable to rewind ivf output file.";
      54           0 :     return false;
      55             :   }
      56             : 
      57           0 :   uint8_t ivf_header[kIvfHeaderSize] = {0};
      58           0 :   ivf_header[0] = 'D';
      59           0 :   ivf_header[1] = 'K';
      60           0 :   ivf_header[2] = 'I';
      61           0 :   ivf_header[3] = 'F';
      62           0 :   ByteWriter<uint16_t>::WriteLittleEndian(&ivf_header[4], 0);   // Version.
      63           0 :   ByteWriter<uint16_t>::WriteLittleEndian(&ivf_header[6], 32);  // Header size.
      64             : 
      65           0 :   switch (codec_type_) {
      66             :     case kVideoCodecVP8:
      67           0 :       ivf_header[8] = 'V';
      68           0 :       ivf_header[9] = 'P';
      69           0 :       ivf_header[10] = '8';
      70           0 :       ivf_header[11] = '0';
      71           0 :       break;
      72             :     case kVideoCodecVP9:
      73           0 :       ivf_header[8] = 'V';
      74           0 :       ivf_header[9] = 'P';
      75           0 :       ivf_header[10] = '9';
      76           0 :       ivf_header[11] = '0';
      77           0 :       break;
      78             :     case kVideoCodecH264:
      79           0 :       ivf_header[8] = 'H';
      80           0 :       ivf_header[9] = '2';
      81           0 :       ivf_header[10] = '6';
      82           0 :       ivf_header[11] = '4';
      83           0 :       break;
      84             :     default:
      85           0 :       LOG(LS_ERROR) << "Unknown CODEC type: " << codec_type_;
      86           0 :       return false;
      87             :   }
      88             : 
      89           0 :   ByteWriter<uint16_t>::WriteLittleEndian(&ivf_header[12], width_);
      90           0 :   ByteWriter<uint16_t>::WriteLittleEndian(&ivf_header[14], height_);
      91             :   // Render timestamps are in ms (1/1000 scale), while RTP timestamps use a
      92             :   // 90kHz clock.
      93           0 :   ByteWriter<uint32_t>::WriteLittleEndian(
      94           0 :       &ivf_header[16], using_capture_timestamps_ ? 1000 : 90000);
      95           0 :   ByteWriter<uint32_t>::WriteLittleEndian(&ivf_header[20], 1);
      96           0 :   ByteWriter<uint32_t>::WriteLittleEndian(&ivf_header[24],
      97           0 :                                           static_cast<uint32_t>(num_frames_));
      98           0 :   ByteWriter<uint32_t>::WriteLittleEndian(&ivf_header[28], 0);  // Reserved.
      99             : 
     100           0 :   if (file_.Write(ivf_header, kIvfHeaderSize) < kIvfHeaderSize) {
     101           0 :     LOG(LS_ERROR) << "Unable to write IVF header for ivf output file.";
     102           0 :     return false;
     103             :   }
     104             : 
     105           0 :   if (bytes_written_ < kIvfHeaderSize) {
     106           0 :     bytes_written_ = kIvfHeaderSize;
     107             :   }
     108             : 
     109           0 :   return true;
     110             : }
     111             : 
     112           0 : bool IvfFileWriter::InitFromFirstFrame(const EncodedImage& encoded_image,
     113             :                                        VideoCodecType codec_type) {
     114           0 :   width_ = encoded_image._encodedWidth;
     115           0 :   height_ = encoded_image._encodedHeight;
     116           0 :   RTC_CHECK_GT(width_, 0);
     117           0 :   RTC_CHECK_GT(height_, 0);
     118           0 :   using_capture_timestamps_ = encoded_image._timeStamp == 0;
     119             : 
     120           0 :   codec_type_ = codec_type;
     121             : 
     122           0 :   if (!WriteHeader())
     123           0 :     return false;
     124             : 
     125             :   const char* codec_name =
     126           0 :       CodecTypeToPayloadName(codec_type_).value_or("Unknown");
     127           0 :   LOG(LS_WARNING) << "Created IVF file for codec data of type " << codec_name
     128           0 :                   << " at resolution " << width_ << " x " << height_
     129           0 :                   << ", using " << (using_capture_timestamps_ ? "1" : "90")
     130           0 :                   << "kHz clock resolution.";
     131           0 :   return true;
     132             : }
     133             : 
     134           0 : bool IvfFileWriter::WriteFrame(const EncodedImage& encoded_image,
     135             :                                VideoCodecType codec_type) {
     136           0 :   if (!file_.IsOpen())
     137           0 :     return false;
     138             : 
     139           0 :   if (num_frames_ == 0 && !InitFromFirstFrame(encoded_image, codec_type))
     140           0 :     return false;
     141           0 :   RTC_DCHECK_EQ(codec_type_, codec_type);
     142             : 
     143           0 :   if ((encoded_image._encodedWidth > 0 || encoded_image._encodedHeight > 0) &&
     144           0 :       (encoded_image._encodedHeight != height_ ||
     145           0 :        encoded_image._encodedWidth != width_)) {
     146           0 :     LOG(LS_WARNING)
     147           0 :         << "Incomig frame has diffferent resolution then previous: (" << width_
     148           0 :         << "x" << height_ << ") -> (" << encoded_image._encodedWidth << "x"
     149           0 :         << encoded_image._encodedHeight << ")";
     150             :   }
     151             : 
     152           0 :   int64_t timestamp = using_capture_timestamps_
     153           0 :                           ? encoded_image.capture_time_ms_
     154           0 :                           : wrap_handler_.Unwrap(encoded_image._timeStamp);
     155           0 :   if (last_timestamp_ != -1 && timestamp <= last_timestamp_) {
     156           0 :     LOG(LS_WARNING) << "Timestamp no increasing: " << last_timestamp_ << " -> "
     157           0 :                     << timestamp;
     158             :   }
     159           0 :   last_timestamp_ = timestamp;
     160             : 
     161           0 :   const size_t kFrameHeaderSize = 12;
     162           0 :   if (byte_limit_ != 0 &&
     163           0 :       bytes_written_ + kFrameHeaderSize + encoded_image._length > byte_limit_) {
     164           0 :     LOG(LS_WARNING) << "Closing IVF file due to reaching size limit: "
     165           0 :                     << byte_limit_ << " bytes.";
     166           0 :     Close();
     167           0 :     return false;
     168             :   }
     169           0 :   uint8_t frame_header[kFrameHeaderSize] = {};
     170           0 :   ByteWriter<uint32_t>::WriteLittleEndian(
     171           0 :       &frame_header[0], static_cast<uint32_t>(encoded_image._length));
     172           0 :   ByteWriter<uint64_t>::WriteLittleEndian(&frame_header[4], timestamp);
     173           0 :   if (file_.Write(frame_header, kFrameHeaderSize) < kFrameHeaderSize ||
     174           0 :       file_.Write(encoded_image._buffer, encoded_image._length) <
     175           0 :           encoded_image._length) {
     176           0 :     LOG(LS_ERROR) << "Unable to write frame to file.";
     177           0 :     return false;
     178             :   }
     179             : 
     180           0 :   bytes_written_ += kFrameHeaderSize + encoded_image._length;
     181             : 
     182           0 :   ++num_frames_;
     183           0 :   return true;
     184             : }
     185             : 
     186           0 : bool IvfFileWriter::Close() {
     187           0 :   if (!file_.IsOpen())
     188           0 :     return false;
     189             : 
     190           0 :   if (num_frames_ == 0) {
     191           0 :     file_.Close();
     192           0 :     return true;
     193             :   }
     194             : 
     195           0 :   bool ret = WriteHeader();
     196           0 :   file_.Close();
     197           0 :   return ret;
     198             : }
     199             : 
     200             : }  // namespace webrtc

Generated by: LCOV version 1.13