Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(631)

Unified Diff: source/libvpx/third_party/libwebm/mkvmuxerutil.cpp

Issue 1302353004: libvpx: Pull from upstream (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/libvpx.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « source/libvpx/third_party/libwebm/mkvmuxerutil.hpp ('k') | source/libvpx/third_party/libwebm/mkvparser.hpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: source/libvpx/third_party/libwebm/mkvmuxerutil.cpp
diff --git a/source/libvpx/third_party/libwebm/mkvmuxerutil.cpp b/source/libvpx/third_party/libwebm/mkvmuxerutil.cpp
index 3fb9bc9dc776ca49c8495fcf47db35e6bdbba168..27ab15d51f1ed4b51e822fc07f9484ea0c32ce69 100644
--- a/source/libvpx/third_party/libwebm/mkvmuxerutil.cpp
+++ b/source/libvpx/third_party/libwebm/mkvmuxerutil.cpp
@@ -15,18 +15,19 @@
#include <cassert>
#include <cmath>
#include <cstdio>
-#ifdef _MSC_VER
-#define _CRT_RAND_S
-#endif
#include <cstdlib>
#include <cstring>
#include <ctime>
-
#include <new>
#include "mkvwriter.hpp"
#include "webmids.hpp"
+#ifdef _MSC_VER
+// Disable MSVC warnings that suggest making code non-portable.
+#pragma warning(disable : 4996)
+#endif
+
namespace mkvmuxer {
namespace {
@@ -34,6 +35,144 @@ namespace {
// Date elements are always 8 octets in size.
const int kDateElementSize = 8;
+uint64 WriteBlock(IMkvWriter* writer, const Frame* const frame, int64 timecode,
+ uint64 timecode_scale) {
+ uint64 block_additional_elem_size = 0;
+ uint64 block_addid_elem_size = 0;
+ uint64 block_more_payload_size = 0;
+ uint64 block_more_elem_size = 0;
+ uint64 block_additions_payload_size = 0;
+ uint64 block_additions_elem_size = 0;
+ if (frame->additional()) {
+ block_additional_elem_size = EbmlElementSize(
+ kMkvBlockAdditional, frame->additional(), frame->additional_length());
+ block_addid_elem_size = EbmlElementSize(kMkvBlockAddID, frame->add_id());
+
+ block_more_payload_size =
+ block_addid_elem_size + block_additional_elem_size;
+ block_more_elem_size =
+ EbmlMasterElementSize(kMkvBlockMore, block_more_payload_size) +
+ block_more_payload_size;
+ block_additions_payload_size = block_more_elem_size;
+ block_additions_elem_size =
+ EbmlMasterElementSize(kMkvBlockAdditions,
+ block_additions_payload_size) +
+ block_additions_payload_size;
+ }
+
+ uint64 discard_padding_elem_size = 0;
+ if (frame->discard_padding() != 0) {
+ discard_padding_elem_size =
+ EbmlElementSize(kMkvDiscardPadding, frame->discard_padding());
+ }
+
+ const uint64 reference_block_timestamp =
+ frame->reference_block_timestamp() / timecode_scale;
+ uint64 reference_block_elem_size = 0;
+ if (!frame->is_key()) {
+ reference_block_elem_size =
+ EbmlElementSize(kMkvReferenceBlock, reference_block_timestamp);
+ }
+
+ const uint64 duration = frame->duration() / timecode_scale;
+ uint64 block_duration_elem_size = 0;
+ if (duration > 0)
+ block_duration_elem_size = EbmlElementSize(kMkvBlockDuration, duration);
+
+ const uint64 block_payload_size = 4 + frame->length();
+ const uint64 block_elem_size =
+ EbmlMasterElementSize(kMkvBlock, block_payload_size) + block_payload_size;
+
+ const uint64 block_group_payload_size =
+ block_elem_size + block_additions_elem_size + block_duration_elem_size +
+ discard_padding_elem_size + reference_block_elem_size;
+
+ if (!WriteEbmlMasterElement(writer, kMkvBlockGroup,
+ block_group_payload_size)) {
+ return 0;
+ }
+
+ if (!WriteEbmlMasterElement(writer, kMkvBlock, block_payload_size))
+ return 0;
+
+ if (WriteUInt(writer, frame->track_number()))
+ return 0;
+
+ if (SerializeInt(writer, timecode, 2))
+ return 0;
+
+ // For a Block, flags is always 0.
+ if (SerializeInt(writer, 0, 1))
+ return 0;
+
+ if (writer->Write(frame->frame(), static_cast<uint32>(frame->length())))
+ return 0;
+
+ if (frame->additional()) {
+ if (!WriteEbmlMasterElement(writer, kMkvBlockAdditions,
+ block_additions_payload_size)) {
+ return 0;
+ }
+
+ if (!WriteEbmlMasterElement(writer, kMkvBlockMore, block_more_payload_size))
+ return 0;
+
+ if (!WriteEbmlElement(writer, kMkvBlockAddID, frame->add_id()))
+ return 0;
+
+ if (!WriteEbmlElement(writer, kMkvBlockAdditional, frame->additional(),
+ frame->additional_length())) {
+ return 0;
+ }
+ }
+
+ if (frame->discard_padding() != 0 &&
+ !WriteEbmlElement(writer, kMkvDiscardPadding, frame->discard_padding())) {
+ return false;
+ }
+
+ if (!frame->is_key() &&
+ !WriteEbmlElement(writer, kMkvReferenceBlock,
+ reference_block_timestamp)) {
+ return false;
+ }
+
+ if (duration > 0 && !WriteEbmlElement(writer, kMkvBlockDuration, duration)) {
+ return false;
+ }
+ return EbmlMasterElementSize(kMkvBlockGroup, block_group_payload_size) +
+ block_group_payload_size;
+}
+
+uint64 WriteSimpleBlock(IMkvWriter* writer, const Frame* const frame,
+ int64 timecode) {
+ if (WriteID(writer, kMkvSimpleBlock))
+ return 0;
+
+ const int32 size = static_cast<int32>(frame->length()) + 4;
+ if (WriteUInt(writer, size))
+ return 0;
+
+ if (WriteUInt(writer, static_cast<uint64>(frame->track_number())))
+ return 0;
+
+ if (SerializeInt(writer, timecode, 2))
+ return 0;
+
+ uint64 flags = 0;
+ if (frame->is_key())
+ flags |= 0x80;
+
+ if (SerializeInt(writer, flags, 1))
+ return 0;
+
+ if (writer->Write(frame->frame(), static_cast<uint32>(frame->length())))
+ return 0;
+
+ return GetUIntSize(kMkvSimpleBlock) + GetCodedUIntSize(size) + 4 +
+ frame->length();
+}
+
} // namespace
int32 GetCodedUIntSize(uint64 value) {
@@ -72,6 +211,13 @@ int32 GetUIntSize(uint64 value) {
return 8;
}
+int32 GetIntSize(int64 value) {
+ // Doubling the requested value ensures positive values with their high bit
+ // set are written with 0-padding to avoid flipping the signedness.
+ const uint64 v = (value < 0) ? value ^ -1LL : value;
+ return GetUIntSize(2 * v);
+}
+
uint64 EbmlMasterElementSize(uint64 type, uint64 value) {
// Size of EBML ID
int32 ebml_size = GetUIntSize(type);
@@ -83,7 +229,16 @@ uint64 EbmlMasterElementSize(uint64 type, uint64 value) {
}
uint64 EbmlElementSize(uint64 type, int64 value) {
- return EbmlElementSize(type, static_cast<uint64>(value));
+ // Size of EBML ID
+ int32 ebml_size = GetUIntSize(type);
+
+ // Datasize
+ ebml_size += GetIntSize(value);
+
+ // Size of Datasize
+ ebml_size++;
+
+ return ebml_size;
}
uint64 EbmlElementSize(uint64 type, uint64 value) {
@@ -144,7 +299,7 @@ uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size) {
return ebml_size;
}
-uint64 EbmlDateElementSize(uint64 type, int64 value) {
+uint64 EbmlDateElementSize(uint64 type) {
// Size of EBML ID
uint64 ebml_size = GetUIntSize(type);
@@ -289,6 +444,23 @@ bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value) {
return true;
}
+bool WriteEbmlElement(IMkvWriter* writer, uint64 type, int64 value) {
+ if (!writer)
+ return false;
+
+ if (WriteID(writer, type))
+ return 0;
+
+ const uint64 size = GetIntSize(value);
+ if (WriteUInt(writer, size))
+ return false;
+
+ if (SerializeInt(writer, value, static_cast<int32>(size)))
+ return false;
+
+ return true;
+}
+
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value) {
if (!writer)
return false;
@@ -355,289 +527,25 @@ bool WriteEbmlDateElement(IMkvWriter* writer, uint64 type, int64 value) {
return true;
}
-uint64 WriteSimpleBlock(IMkvWriter* writer, const uint8* data, uint64 length,
- uint64 track_number, int64 timecode, uint64 is_key) {
- if (!writer)
- return false;
-
- if (!data || length < 1)
- return false;
-
- // Here we only permit track number values to be no greater than
- // 126, which the largest value we can store having a Matroska
- // integer representation of only 1 byte.
-
- if (track_number < 1 || track_number > 126)
- return false;
-
- // Technically the timestamp for a block can be less than the
- // timestamp for the cluster itself (remember that block timestamp
- // is a signed, 16-bit integer). However, as a simplification we
- // only permit non-negative cluster-relative timestamps for blocks.
-
- if (timecode < 0 || timecode > kMaxBlockTimecode)
- return false;
-
- if (WriteID(writer, kMkvSimpleBlock))
- return 0;
-
- const int32 size = static_cast<int32>(length) + 4;
- if (WriteUInt(writer, size))
- return 0;
-
- if (WriteUInt(writer, static_cast<uint64>(track_number)))
- return 0;
-
- if (SerializeInt(writer, timecode, 2))
- return 0;
-
- uint64 flags = 0;
- if (is_key)
- flags |= 0x80;
-
- if (SerializeInt(writer, flags, 1))
- return 0;
-
- if (writer->Write(data, static_cast<uint32>(length)))
- return 0;
-
- const uint64 element_size =
- GetUIntSize(kMkvSimpleBlock) + GetCodedUIntSize(size) + 4 + length;
-
- return element_size;
-}
-
-// We must write the metadata (key)frame as a BlockGroup element,
-// because we need to specify a duration for the frame. The
-// BlockGroup element comprises the frame itself and its duration,
-// and is laid out as follows:
-//
-// BlockGroup tag
-// BlockGroup size
-// Block tag
-// Block size
-// (the frame is the block payload)
-// Duration tag
-// Duration size
-// (duration payload)
-//
-uint64 WriteMetadataBlock(IMkvWriter* writer, const uint8* data, uint64 length,
- uint64 track_number, int64 timecode,
- uint64 duration) {
- // We don't backtrack when writing to the stream, so we must
- // pre-compute the BlockGroup size, by summing the sizes of each
- // sub-element (the block and the duration).
-
- // We use a single byte for the track number of the block, which
- // means the block header is exactly 4 bytes.
-
- // TODO(matthewjheaney): use EbmlMasterElementSize and WriteEbmlMasterElement
-
- const uint64 block_payload_size = 4 + length;
- const int32 block_size = GetCodedUIntSize(block_payload_size);
- const uint64 block_elem_size = 1 + block_size + block_payload_size;
-
- const int32 duration_payload_size = GetUIntSize(duration);
- const int32 duration_size = GetCodedUIntSize(duration_payload_size);
- const uint64 duration_elem_size = 1 + duration_size + duration_payload_size;
-
- const uint64 blockg_payload_size = block_elem_size + duration_elem_size;
- const int32 blockg_size = GetCodedUIntSize(blockg_payload_size);
- const uint64 blockg_elem_size = 1 + blockg_size + blockg_payload_size;
-
- if (WriteID(writer, kMkvBlockGroup)) // 1-byte ID size
- return 0;
-
- if (WriteUInt(writer, blockg_payload_size))
- return 0;
-
- // Write Block element
-
- if (WriteID(writer, kMkvBlock)) // 1-byte ID size
- return 0;
-
- if (WriteUInt(writer, block_payload_size))
- return 0;
-
- // Byte 1 of 4
-
- if (WriteUInt(writer, track_number))
- return 0;
-
- // Bytes 2 & 3 of 4
-
- if (SerializeInt(writer, timecode, 2))
- return 0;
-
- // Byte 4 of 4
-
- const uint64 flags = 0;
-
- if (SerializeInt(writer, flags, 1))
- return 0;
-
- // Now write the actual frame (of metadata)
-
- if (writer->Write(data, static_cast<uint32>(length)))
- return 0;
-
- // Write Duration element
-
- if (WriteID(writer, kMkvBlockDuration)) // 1-byte ID size
- return 0;
-
- if (WriteUInt(writer, duration_payload_size))
- return 0;
-
- if (SerializeInt(writer, duration, duration_payload_size))
- return 0;
-
- // Note that we don't write a reference time as part of the block
- // group; no reference time(s) indicates that this block is a
- // keyframe. (Unlike the case for a SimpleBlock element, the header
- // bits of the Block sub-element of a BlockGroup element do not
- // indicate keyframe status. The keyframe status is inferred from
- // the absence of reference time sub-elements.)
-
- return blockg_elem_size;
-}
-
-// Writes a WebM BlockGroup with BlockAdditional data. The structure is as
-// follows:
-// Indentation shows sub-levels
-// BlockGroup
-// Block
-// Data
-// BlockAdditions
-// BlockMore
-// BlockAddID
-// 1 (Denotes Alpha)
-// BlockAdditional
-// Data
-uint64 WriteBlockWithAdditional(IMkvWriter* writer, const uint8* data,
- uint64 length, const uint8* additional,
- uint64 additional_length, uint64 add_id,
- uint64 track_number, int64 timecode,
- uint64 is_key) {
- if (!data || !additional || length < 1 || additional_length < 1)
+uint64 WriteFrame(IMkvWriter* writer, const Frame* const frame,
+ Cluster* cluster) {
+ if (!writer || !frame || !frame->IsValid() || !cluster ||
+ !cluster->timecode_scale())
return 0;
- const uint64 block_payload_size = 4 + length;
- const uint64 block_elem_size =
- EbmlMasterElementSize(kMkvBlock, block_payload_size) + block_payload_size;
- const uint64 block_additional_elem_size =
- EbmlElementSize(kMkvBlockAdditional, additional, additional_length);
- const uint64 block_addid_elem_size = EbmlElementSize(kMkvBlockAddID, add_id);
-
- const uint64 block_more_payload_size =
- block_addid_elem_size + block_additional_elem_size;
- const uint64 block_more_elem_size =
- EbmlMasterElementSize(kMkvBlockMore, block_more_payload_size) +
- block_more_payload_size;
- const uint64 block_additions_payload_size = block_more_elem_size;
- const uint64 block_additions_elem_size =
- EbmlMasterElementSize(kMkvBlockAdditions, block_additions_payload_size) +
- block_additions_payload_size;
- const uint64 block_group_payload_size =
- block_elem_size + block_additions_elem_size;
- const uint64 block_group_elem_size =
- EbmlMasterElementSize(kMkvBlockGroup, block_group_payload_size) +
- block_group_payload_size;
-
- if (!WriteEbmlMasterElement(writer, kMkvBlockGroup, block_group_payload_size))
- return 0;
-
- if (!WriteEbmlMasterElement(writer, kMkvBlock, block_payload_size))
- return 0;
-
- if (WriteUInt(writer, track_number))
- return 0;
-
- if (SerializeInt(writer, timecode, 2))
- return 0;
-
- uint64 flags = 0;
- if (is_key)
- flags |= 0x80;
- if (SerializeInt(writer, flags, 1))
- return 0;
-
- if (writer->Write(data, static_cast<uint32>(length)))
- return 0;
-
- if (!WriteEbmlMasterElement(writer, kMkvBlockAdditions,
- block_additions_payload_size))
- return 0;
-
- if (!WriteEbmlMasterElement(writer, kMkvBlockMore, block_more_payload_size))
- return 0;
-
- if (!WriteEbmlElement(writer, kMkvBlockAddID, add_id))
- return 0;
-
- if (!WriteEbmlElement(writer, kMkvBlockAdditional, additional,
- additional_length))
- return 0;
-
- return block_group_elem_size;
-}
-
-// Writes a WebM BlockGroup with DiscardPadding. The structure is as follows:
-// Indentation shows sub-levels
-// BlockGroup
-// Block
-// Data
-// DiscardPadding
-uint64 WriteBlockWithDiscardPadding(IMkvWriter* writer, const uint8* data,
- uint64 length, int64 discard_padding,
- uint64 track_number, int64 timecode,
- uint64 is_key) {
- if (!data || length < 1 || discard_padding <= 0)
- return 0;
-
- const uint64 block_payload_size = 4 + length;
- const uint64 block_elem_size =
- EbmlMasterElementSize(kMkvBlock, block_payload_size) + block_payload_size;
- const uint64 discard_padding_elem_size =
- EbmlElementSize(kMkvDiscardPadding, discard_padding);
- const uint64 block_group_payload_size =
- block_elem_size + discard_padding_elem_size;
- const uint64 block_group_elem_size =
- EbmlMasterElementSize(kMkvBlockGroup, block_group_payload_size) +
- block_group_payload_size;
-
- if (!WriteEbmlMasterElement(writer, kMkvBlockGroup, block_group_payload_size))
- return 0;
-
- if (!WriteEbmlMasterElement(writer, kMkvBlock, block_payload_size))
- return 0;
-
- if (WriteUInt(writer, track_number))
- return 0;
-
- if (SerializeInt(writer, timecode, 2))
- return 0;
-
- uint64 flags = 0;
- if (is_key)
- flags |= 0x80;
- if (SerializeInt(writer, flags, 1))
- return 0;
-
- if (writer->Write(data, static_cast<uint32>(length)))
- return 0;
-
- if (WriteID(writer, kMkvDiscardPadding))
+ // Technically the timecode for a block can be less than the
+ // timecode for the cluster itself (remember that block timecode
+ // is a signed, 16-bit integer). However, as a simplification we
+ // only permit non-negative cluster-relative timecodes for blocks.
+ const int64 relative_timecode = cluster->GetRelativeTimecode(
+ frame->timestamp() / cluster->timecode_scale());
+ if (relative_timecode < 0 || relative_timecode > kMaxBlockTimecode)
return 0;
- const uint64 size = GetUIntSize(discard_padding);
- if (WriteUInt(writer, size))
- return false;
-
- if (SerializeInt(writer, discard_padding, static_cast<int32>(size)))
- return false;
-
- return block_group_elem_size;
+ return frame->CanBeSimpleBlock() ?
+ WriteSimpleBlock(writer, frame, relative_timecode) :
+ WriteBlock(writer, frame, relative_timecode,
+ cluster->timecode_scale());
}
uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
@@ -698,10 +606,7 @@ mkvmuxer::uint64 mkvmuxer::MakeUID(unsigned int* seed) {
// TODO(fgalligan): Move random number generation to platform specific code.
#ifdef _MSC_VER
(void)seed;
- unsigned int random_value;
- const errno_t e = rand_s(&random_value);
- (void)e;
- const int32 nn = random_value;
+ const int32 nn = rand();
#elif __ANDROID__
int32 temp_num = 1;
int fd = open("/dev/urandom", O_RDONLY);
« no previous file with comments | « source/libvpx/third_party/libwebm/mkvmuxerutil.hpp ('k') | source/libvpx/third_party/libwebm/mkvparser.hpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698