NS_IMETHODIMP
nsBinaryOutputStream::WriteCompoundObject(nsISupports* aObject,
                                          const nsIID& aIID,
                                          PRBool aIsStrongRef)
{
    // Can't deal with weak refs
    NS_ENSURE_TRUE(aIsStrongRef, NS_ERROR_UNEXPECTED);
    
    nsCOMPtr<nsIClassInfo> classInfo = do_QueryInterface(aObject);
    NS_ENSURE_TRUE(classInfo, NS_ERROR_NOT_AVAILABLE);

    nsCOMPtr<nsISerializable> serializable = do_QueryInterface(aObject);
    NS_ENSURE_TRUE(serializable, NS_ERROR_NOT_AVAILABLE);

    nsCID cid;
    classInfo->GetClassIDNoAlloc(&cid);

    nsresult rv = WriteID(cid);
    NS_ENSURE_SUCCESS(rv, rv);
    
    rv = WriteID(aIID);
    NS_ENSURE_SUCCESS(rv, rv);

    return serializable->Write(this);
}
uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
    if (!writer)
        return false;

    // Subtract one for the void ID and the coded size.
    uint64 void_entry_size = size - 1 - GetCodedUIntSize(size-1);
    uint64 void_size = EbmlMasterElementSize(kMkvVoid, void_entry_size) +
                       void_entry_size;

    if (void_size != size)
        return 0;

    const int64 payload_position = writer->Position();
    if (payload_position < 0)
        return 0;

    if (WriteID(writer, kMkvVoid))
        return 0;

    if (WriteUInt(writer, void_entry_size))
        return 0;

    const uint8 value = 0;
    for (int32 i = 0; i < static_cast<int32>(void_entry_size); ++i) {
        if (writer->Write(&value, 1))
            return 0;
    }

    const int64 stop_position = writer->Position();
    if (stop_position < 0 ||
            stop_position - payload_position != static_cast<int64>(void_size))
        return 0;

    return void_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))
        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;
}
Exemple #4
0
void GoBlock::Write(std::ostream& stream) const
{
    WriteID(stream);
    stream  <<  '\n'
            << SgWritePointSet(Stones(), "Stones: ")
            << "\nhealthy: " << Healthy().Length()
            << "\nisSafe: " << SgWriteBoolean(IsSafe())
            << "\nhas1Eye: " << SgWriteBoolean(Has1Eye())
            << "\n";
}
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;
}
bool WriteEbmlMasterElement(IMkvWriter* writer, uint64 type, uint64 size) {
    if (!writer)
        return false;

    if (WriteID(writer, type))
        return false;

    if (WriteUInt(writer, size))
        return false;

    return true;
}
Exemple #7
0
NS_IMETHODIMP
nsBinaryOutputStream::WriteCompoundObject(nsISupports* aObject,
                                          const nsIID& aIID,
                                          bool aIsStrongRef)
{
    nsCOMPtr<nsIClassInfo> classInfo = do_QueryInterface(aObject);
    nsCOMPtr<nsISerializable> serializable = do_QueryInterface(aObject);

    // Can't deal with weak refs
    if (NS_WARN_IF(!aIsStrongRef))
        return NS_ERROR_UNEXPECTED;
    if (NS_WARN_IF(!classInfo) || NS_WARN_IF(!serializable))
        return NS_ERROR_NOT_AVAILABLE;

    nsCID cid;
    nsresult rv = classInfo->GetClassIDNoAlloc(&cid);
    if (NS_SUCCEEDED(rv)) {
        rv = WriteID(cid);
    } else {
        nsCID *cidptr = nullptr;
        rv = classInfo->GetClassID(&cidptr);
        if (NS_WARN_IF(NS_FAILED(rv))) {
            return rv;
        }

        rv = WriteID(*cidptr);

        NS_Free(cidptr);
    }

    if (NS_WARN_IF(NS_FAILED(rv)))
        return rv;

    rv = WriteID(aIID);
    if (NS_WARN_IF(NS_FAILED(rv)))
        return rv;

    return serializable->Write(this);
}
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value) {
    if (!writer)
        return false;

    if (WriteID(writer, type))
        return false;

    if (WriteUInt(writer, 4))
        return false;

    if (SerializeFloat(writer, value))
        return false;

    return true;
}
bool WriteEbmlDateElement(IMkvWriter* writer, uint64 type, int64 value) {
  if (!writer)
    return false;

  if (WriteID(writer, type))
    return false;

  if (WriteUInt(writer, kDateElementSize))
    return false;

  if (SerializeInt(writer, value, kDateElementSize))
    return false;

  return true;
}
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value) {
    if (!writer || !value)
        return false;

    if (WriteID(writer, type))
        return false;

    const int32 length = strlen(value);
    if (WriteUInt(writer, length))
        return false;

    if (writer->Write(value, length))
        return false;

    return true;
}
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value) {
    if (!writer)
        return false;

    if (WriteID(writer, type))
        return false;

    const uint64 size = GetUIntSize(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, const uint8* value,
                      uint64 size) {
  if (!writer || !value || size < 1)
    return false;

  if (WriteID(writer, type))
    return false;

  if (WriteUInt(writer, size))
    return false;

  if (writer->Write(value, static_cast<uint32>(size)))
    return false;

  return true;
}
// 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;
}