Merge "Add support for muxing to libwebm."
This commit is contained in:
37
Makefile
37
Makefile
@@ -1,20 +1,29 @@
|
|||||||
LIB = libmkvparser.a
|
CXX := g++
|
||||||
OBJECTS = mkvparser.o mkvreader.o sample.o
|
CXXFLAGS := -W -Wall -g
|
||||||
EXE = sample
|
LIBS := libmkvparser.a libmkvmuxer.a
|
||||||
CFLAGS = -W -Wall -g
|
PARSEOBJ := mkvparser.o mkvreader.o
|
||||||
|
MUXEROBJ := mkvmuxer.o mkvmuxerutil.o mkvwriter.o
|
||||||
|
OBJECTS1 := $(PARSEOBJ) sample.o
|
||||||
|
OBJECTS2 := $(PARSEOBJ) $(MUXEROBJ) sample_muxer/sample_muxer.o
|
||||||
|
INCLUDES := -I.
|
||||||
|
EXES := samplemuxer sample
|
||||||
|
|
||||||
$(EXE): $(OBJECTS)
|
all: $(EXES)
|
||||||
$(AR) rcs $(LIB) mkvparser.o mkvreader.o
|
|
||||||
$(CXX) $(OBJECTS) -L./ -lmkvparser -o $(EXE)
|
|
||||||
|
|
||||||
mkvparser.o: mkvparser.cpp
|
sample: sample.o libmkvparser.a
|
||||||
$(CXX) -c $(CFLAGS) mkvparser.cpp -o mkvparser.o
|
$(CXX) $^ -o $@
|
||||||
|
|
||||||
mkvreader.o: mkvreader.cpp
|
samplemuxer: sample_muxer/sample_muxer.o $(LIBS)
|
||||||
$(CXX) -c $(CFLAGS) mkvreader.cpp -o mkvreader.o
|
$(CXX) $^ -o $@
|
||||||
|
|
||||||
sample.o: sample.cpp
|
libmkvparser.a: $(PARSEOBJ)
|
||||||
$(CXX) -c $(CFLAGS) sample.cpp -o sample.o
|
$(AR) rcs $@ $^
|
||||||
|
|
||||||
|
libmkvmuxer.a: $(MUXEROBJ)
|
||||||
|
$(AR) rcs $@ $^
|
||||||
|
|
||||||
|
%.o: %.cpp
|
||||||
|
$(CXX) -c $(CXXFLAGS) $(INCLUDES) $< -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(OBJECTS) $(LIB) $(EXE) Makefile.bak
|
$(RM) -f $(OBJECTS1) $(OBJECTS2) $(LIBS) $(EXES) Makefile.bak
|
||||||
|
|||||||
1617
mkvmuxer.cpp
Normal file
1617
mkvmuxer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
689
mkvmuxer.hpp
Normal file
689
mkvmuxer.hpp
Normal file
@@ -0,0 +1,689 @@
|
|||||||
|
// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style license
|
||||||
|
// that can be found in the LICENSE file in the root of the source
|
||||||
|
// tree. An additional intellectual property rights grant can be found
|
||||||
|
// in the file PATENTS. All contributing project authors may
|
||||||
|
// be found in the AUTHORS file in the root of the source tree.
|
||||||
|
|
||||||
|
#ifndef MKVMUXER_HPP
|
||||||
|
#define MKVMUXER_HPP
|
||||||
|
|
||||||
|
#include "mkvmuxertypes.hpp"
|
||||||
|
|
||||||
|
// For a description of the WebM elements see
|
||||||
|
// http://www.webmproject.org/code/specs/container/.
|
||||||
|
|
||||||
|
namespace mkvmuxer {
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
|
// Interface used by the mkvmuxer to write out the Mkv data.
|
||||||
|
class IMkvWriter {
|
||||||
|
public:
|
||||||
|
// Writes out |len| bytes of |buf|. Returns 0 on success.
|
||||||
|
virtual int32 Write(const void* buf, uint32 len) = 0;
|
||||||
|
|
||||||
|
// Returns the offset of the output position from the beginning of the
|
||||||
|
// output.
|
||||||
|
virtual int64 Position() const = 0;
|
||||||
|
|
||||||
|
// Set the current File position. Returns 0 on success.
|
||||||
|
virtual int32 Position(int64 position) = 0;
|
||||||
|
|
||||||
|
// Returns true if the writer is seekable.
|
||||||
|
virtual bool Seekable() const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
IMkvWriter();
|
||||||
|
virtual ~IMkvWriter();
|
||||||
|
|
||||||
|
private:
|
||||||
|
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(IMkvWriter);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Writes out the EBML header for a WebM file. This function must be called
|
||||||
|
// before any other libwebm writing functions are called.
|
||||||
|
bool WriteEbmlHeader(IMkvWriter* writer);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
|
// Class to hold data the will be written to a block.
|
||||||
|
class Frame {
|
||||||
|
public:
|
||||||
|
Frame();
|
||||||
|
~Frame();
|
||||||
|
|
||||||
|
// Copies |frame| data into |frame_|. Returns true on success.
|
||||||
|
bool Init(const uint8* frame, uint64 length);
|
||||||
|
|
||||||
|
const uint8* frame() const { return frame_; }
|
||||||
|
uint64 length() const { return length_; }
|
||||||
|
void set_track_number(uint64 track_number) { track_number_ = track_number; }
|
||||||
|
uint64 track_number() const { return track_number_; }
|
||||||
|
void set_timestamp(uint64 timestamp) { timestamp_ = timestamp; }
|
||||||
|
uint64 timestamp() const { return timestamp_; }
|
||||||
|
void set_is_key(bool key) { is_key_ = key; }
|
||||||
|
bool is_key() const { return is_key_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Pointer to the data. Owned by this class.
|
||||||
|
uint8* frame_;
|
||||||
|
|
||||||
|
// Length of the data.
|
||||||
|
uint64 length_;
|
||||||
|
|
||||||
|
// Mkv track number the data is associated with.
|
||||||
|
uint64 track_number_;
|
||||||
|
|
||||||
|
// Timestamp of the data in nanoseconds.
|
||||||
|
uint64 timestamp_;
|
||||||
|
|
||||||
|
// Flag telling if the data should set the key flag of a block.
|
||||||
|
bool is_key_;
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
|
// Class to hold one cue point in a Cues element.
|
||||||
|
class CuePoint {
|
||||||
|
public:
|
||||||
|
CuePoint();
|
||||||
|
~CuePoint();
|
||||||
|
|
||||||
|
// Returns the size in bytes for the entire CuePoint element.
|
||||||
|
uint64 Size() const;
|
||||||
|
|
||||||
|
// Output the CuePoint element to the writer. Returns true on success.
|
||||||
|
bool Write(IMkvWriter* writer) const;
|
||||||
|
|
||||||
|
void set_time(uint64 time) { time_ = time; }
|
||||||
|
uint64 time() const { return time_; }
|
||||||
|
void set_track(uint64 track) { track_ = track; }
|
||||||
|
uint64 track() const { return track_; }
|
||||||
|
void set_cluster_pos(uint64 cluster_pos) { cluster_pos_ = cluster_pos; }
|
||||||
|
uint64 cluster_pos() const { return cluster_pos_; }
|
||||||
|
void set_block_number(uint64 block_number) { block_number_ = block_number; }
|
||||||
|
uint64 block_number() const { return block_number_; }
|
||||||
|
void set_output_block_number(bool output_block_number) {
|
||||||
|
output_block_number_ = output_block_number;
|
||||||
|
}
|
||||||
|
bool output_block_number() const { return output_block_number_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Returns the size in bytes for the payload of the CuePoint element.
|
||||||
|
uint64 PayloadSize() const;
|
||||||
|
|
||||||
|
// Absolute timecode according to the segment time base.
|
||||||
|
uint64 time_;
|
||||||
|
|
||||||
|
// The Track element associated with the CuePoint.
|
||||||
|
uint64 track_;
|
||||||
|
|
||||||
|
// The position of the Cluster containing the Block.
|
||||||
|
uint64 cluster_pos_;
|
||||||
|
|
||||||
|
// Number of the Block within the Cluster, starting from 1.
|
||||||
|
uint64 block_number_;
|
||||||
|
|
||||||
|
// If true the muxer will write out the block number for the cue if the
|
||||||
|
// block number is different than the default of 1. Default is set to true.
|
||||||
|
bool output_block_number_;
|
||||||
|
|
||||||
|
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(CuePoint);
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
|
// Cues element.
|
||||||
|
class Cues {
|
||||||
|
public:
|
||||||
|
Cues();
|
||||||
|
~Cues();
|
||||||
|
|
||||||
|
// Adds a cue point to the Cues element. Returns true on success.
|
||||||
|
bool AddCue(CuePoint* cue);
|
||||||
|
|
||||||
|
// Returns the cue point by index. Returns NULL if there is no cue point
|
||||||
|
// match.
|
||||||
|
const CuePoint* GetCueByIndex(int32 index) const;
|
||||||
|
|
||||||
|
// Output the Cues element to the writer. Returns true on success.
|
||||||
|
bool Write(IMkvWriter* writer) const;
|
||||||
|
|
||||||
|
int32 cue_entries_size() const { return cue_entries_size_; }
|
||||||
|
void set_output_block_number(bool output_block_number) {
|
||||||
|
output_block_number_ = output_block_number;
|
||||||
|
}
|
||||||
|
bool output_block_number() const { return output_block_number_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Number of allocated elements in |cue_entries_|.
|
||||||
|
int32 cue_entries_capacity_;
|
||||||
|
|
||||||
|
// Number of CuePoints in |cue_entries_|.
|
||||||
|
int32 cue_entries_size_;
|
||||||
|
|
||||||
|
// CuePoint list.
|
||||||
|
CuePoint** cue_entries_;
|
||||||
|
|
||||||
|
// If true the muxer will write out the block number for the cue if the
|
||||||
|
// block number is different than the default of 1. Default is set to true.
|
||||||
|
bool output_block_number_;
|
||||||
|
|
||||||
|
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Cues);
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
|
// Track element.
|
||||||
|
class Track {
|
||||||
|
public:
|
||||||
|
Track();
|
||||||
|
virtual ~Track();
|
||||||
|
|
||||||
|
// Returns the size in bytes for the payload of the Track element.
|
||||||
|
virtual uint64 PayloadSize() const;
|
||||||
|
|
||||||
|
// Returns the size in bytes of the Track element.
|
||||||
|
virtual uint64 Size() const;
|
||||||
|
|
||||||
|
// Output the Track element to the writer. Returns true on success.
|
||||||
|
virtual bool Write(IMkvWriter* writer) const;
|
||||||
|
|
||||||
|
// Sets the CodecPrivate element of the Track element. Copies |length|
|
||||||
|
// bytes from |codec_private| to |codec_private_|. Returns true on success.
|
||||||
|
bool SetCodecPrivate(const uint8* codec_private, uint64 length);
|
||||||
|
|
||||||
|
void set_codec_id(const char* codec_id);
|
||||||
|
const char* codec_id() const { return codec_id_; }
|
||||||
|
const uint8* codec_private() const { return codec_private_; }
|
||||||
|
void set_language(const char* language);
|
||||||
|
const char* language() const { return language_; }
|
||||||
|
void set_name(const char* name);
|
||||||
|
const char* name() const { return name_; }
|
||||||
|
void set_number(uint64 number) { number_ = number; }
|
||||||
|
uint64 number() const { return number_; }
|
||||||
|
void set_type(uint64 type) { type_ = type; }
|
||||||
|
uint64 type() const { return type_; }
|
||||||
|
uint64 uid() const { return uid_; }
|
||||||
|
|
||||||
|
uint64 codec_private_length() const { return codec_private_length_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Returns a random number to be used for the Track UID.
|
||||||
|
static uint64 MakeUID();
|
||||||
|
|
||||||
|
// Track element names
|
||||||
|
char* codec_id_;
|
||||||
|
uint8* codec_private_;
|
||||||
|
char* language_;
|
||||||
|
char* name_;
|
||||||
|
uint64 number_;
|
||||||
|
uint64 type_;
|
||||||
|
const uint64 uid_;
|
||||||
|
|
||||||
|
// Size of the CodecPrivate data in bytes.
|
||||||
|
uint64 codec_private_length_;
|
||||||
|
|
||||||
|
// Flag telling if the rand call was seeded.
|
||||||
|
static bool is_seeded_;
|
||||||
|
|
||||||
|
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Track);
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
|
// Track that has video specific elements.
|
||||||
|
class VideoTrack : public Track {
|
||||||
|
public:
|
||||||
|
// Supported modes for stereo 3D.
|
||||||
|
enum StereoMode {
|
||||||
|
kMono = 0,
|
||||||
|
kSideBySideLeftIsFirst = 1,
|
||||||
|
kTopBottomRightIsFirst = 2,
|
||||||
|
kTopBottomLeftIsFirst = 3,
|
||||||
|
kSideBySideRightIsFirst = 11
|
||||||
|
};
|
||||||
|
|
||||||
|
VideoTrack();
|
||||||
|
virtual ~VideoTrack();
|
||||||
|
|
||||||
|
// Returns the size in bytes for the payload of the Track element plus the
|
||||||
|
// video specific elements.
|
||||||
|
virtual uint64 PayloadSize() const;
|
||||||
|
|
||||||
|
// Returns the size in bytes of the Track element plus the video specific
|
||||||
|
// elements.
|
||||||
|
virtual uint64 Size() const;
|
||||||
|
|
||||||
|
// Output the VideoTrack element to the writer. Returns true on success.
|
||||||
|
virtual bool Write(IMkvWriter* writer) const;
|
||||||
|
|
||||||
|
// Sets the video's stereo mode. Returns true on success.
|
||||||
|
bool SetStereoMode(uint64 stereo_mode);
|
||||||
|
|
||||||
|
void set_display_height(uint64 height) { display_height_ = height; }
|
||||||
|
uint64 display_height() const { return display_height_; }
|
||||||
|
void set_display_width(uint64 width) { display_width_ = width; }
|
||||||
|
uint64 display_width() const { return display_width_; }
|
||||||
|
void set_frame_rate(double frame_rate) { frame_rate_ = frame_rate; }
|
||||||
|
double frame_rate() const { return frame_rate_; }
|
||||||
|
void set_height(uint64 height) { height_ = height; }
|
||||||
|
uint64 height() const { return height_; }
|
||||||
|
uint64 stereo_mode() { return stereo_mode_; }
|
||||||
|
void set_width(uint64 width) { width_ = width; }
|
||||||
|
uint64 width() const { return width_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Returns the size in bytes of the Video element.
|
||||||
|
uint64 VideoPayloadSize() const;
|
||||||
|
|
||||||
|
// Video track element names.
|
||||||
|
uint64 display_height_;
|
||||||
|
uint64 display_width_;
|
||||||
|
double frame_rate_;
|
||||||
|
uint64 height_;
|
||||||
|
uint64 stereo_mode_;
|
||||||
|
uint64 width_;
|
||||||
|
|
||||||
|
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(VideoTrack);
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
|
// Track that has audio specific elements.
|
||||||
|
class AudioTrack : public Track {
|
||||||
|
public:
|
||||||
|
AudioTrack();
|
||||||
|
virtual ~AudioTrack();
|
||||||
|
|
||||||
|
// Returns the size in bytes for the payload of the Track element plus the
|
||||||
|
// audio specific elements.
|
||||||
|
virtual uint64 PayloadSize() const;
|
||||||
|
|
||||||
|
// Returns the size in bytes of the Track element plus the audio specific
|
||||||
|
// elements.
|
||||||
|
virtual uint64 Size() const;
|
||||||
|
|
||||||
|
// Output the AudioTrack element to the writer. Returns true on success.
|
||||||
|
virtual bool Write(IMkvWriter* writer) const;
|
||||||
|
|
||||||
|
void set_bit_depth(uint64 bit_depth) { bit_depth_ = bit_depth; }
|
||||||
|
uint64 bit_depth() const { return bit_depth_; }
|
||||||
|
void set_channels(uint64 channels) { channels_ = channels; }
|
||||||
|
uint64 channels() const { return channels_; }
|
||||||
|
void set_sample_rate(double sample_rate) { sample_rate_ = sample_rate; }
|
||||||
|
double sample_rate() const { return sample_rate_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Audio track element names.
|
||||||
|
uint64 bit_depth_;
|
||||||
|
uint64 channels_;
|
||||||
|
double sample_rate_;
|
||||||
|
|
||||||
|
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(AudioTrack);
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
|
// Tracks element
|
||||||
|
class Tracks {
|
||||||
|
public:
|
||||||
|
// Audio and video type defined by the Matroska specs.
|
||||||
|
enum {
|
||||||
|
kVideo = 0x1,
|
||||||
|
kAudio = 0x2
|
||||||
|
};
|
||||||
|
// Vorbis and VP8 coded id defined by the Matroska specs.
|
||||||
|
static const char* const kVorbisCodecId;
|
||||||
|
static const char* const kVp8CodecId;
|
||||||
|
|
||||||
|
Tracks();
|
||||||
|
~Tracks();
|
||||||
|
|
||||||
|
// Adds a Track element to the Tracks object. |track| will be owned and
|
||||||
|
// deleted by the Tracks object. Returns true on success.
|
||||||
|
bool AddTrack(Track* track);
|
||||||
|
|
||||||
|
// Returns the track by index. Returns NULL if there is no track match.
|
||||||
|
const Track* GetTrackByIndex(uint32 idx) const;
|
||||||
|
|
||||||
|
// Search the Tracks and return the track that matches |tn|. Returns NULL
|
||||||
|
// if there is no track match.
|
||||||
|
Track* GetTrackByNumber(uint64 track_number) const;
|
||||||
|
|
||||||
|
// Returns true if the track number is an audio track.
|
||||||
|
bool TrackIsAudio(uint64 track_number) const;
|
||||||
|
|
||||||
|
// Returns true if the track number is a video track.
|
||||||
|
bool TrackIsVideo(uint64 track_number) const;
|
||||||
|
|
||||||
|
// Output the Tracks element to the writer. Returns true on success.
|
||||||
|
bool Write(IMkvWriter* writer) const;
|
||||||
|
|
||||||
|
uint32 track_entries_size() const { return track_entries_size_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Track element list.
|
||||||
|
Track** track_entries_;
|
||||||
|
|
||||||
|
// Number of Track elements added.
|
||||||
|
uint32 track_entries_size_;
|
||||||
|
|
||||||
|
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tracks);
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
|
// Cluster element
|
||||||
|
class Cluster {
|
||||||
|
public:
|
||||||
|
// |timecode| is the absolute timecode of the cluster.
|
||||||
|
Cluster(uint64 timecode, IMkvWriter* writer);
|
||||||
|
~Cluster();
|
||||||
|
|
||||||
|
// Adds a frame to be output in the file. The frame is written out through
|
||||||
|
// |writer_| if successful. Returns true on success.
|
||||||
|
// Inputs:
|
||||||
|
// frame: Pointer to the data
|
||||||
|
// length: Length of the data
|
||||||
|
// track_number: Track to add the data to. Value returned by Add track
|
||||||
|
// functions.
|
||||||
|
// timestamp: Timecode of the frame relative to the cluster timecode.
|
||||||
|
// is_key: Flag telling whether or not this frame is a key frame.
|
||||||
|
bool AddFrame(const uint8* frame,
|
||||||
|
uint64 length,
|
||||||
|
uint64 track_number,
|
||||||
|
short timecode,
|
||||||
|
bool is_key);
|
||||||
|
|
||||||
|
// Increments the size of the cluster's data in bytes.
|
||||||
|
void AddPayloadSize(uint64 size);
|
||||||
|
|
||||||
|
// Closes the cluster so no more data can be written to it. Will update the
|
||||||
|
// cluster's size if |writer_| is seekable. Returns true on success.
|
||||||
|
bool Finalize();
|
||||||
|
|
||||||
|
int32 blocks_added() const { return blocks_added_; }
|
||||||
|
uint64 payload_size() const { return payload_size_; }
|
||||||
|
int64 position_for_cues() const { return position_for_cues_; }
|
||||||
|
uint64 timecode() const { return timecode_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Outputs the Cluster header to |writer_|. Returns true on success.
|
||||||
|
bool WriteClusterHeader();
|
||||||
|
|
||||||
|
// Number of blocks added to the cluster.
|
||||||
|
int32 blocks_added_;
|
||||||
|
|
||||||
|
// Flag telling if the cluster has been closed.
|
||||||
|
bool finalized_;
|
||||||
|
|
||||||
|
// Flag telling if the cluster's header has been written.
|
||||||
|
bool header_written_;
|
||||||
|
|
||||||
|
// The size of the cluster elements in bytes.
|
||||||
|
uint64 payload_size_;
|
||||||
|
|
||||||
|
// The file position used for cue points.
|
||||||
|
int64 position_for_cues_;
|
||||||
|
|
||||||
|
// The file position of the cluster's size element.
|
||||||
|
int64 size_position_;
|
||||||
|
|
||||||
|
// The absolute timecode of the cluster.
|
||||||
|
const uint64 timecode_;
|
||||||
|
|
||||||
|
// Pointer to the writer object. Not owned by this class.
|
||||||
|
IMkvWriter* writer_;
|
||||||
|
|
||||||
|
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Cluster);
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
|
// SeekHead element
|
||||||
|
class SeekHead {
|
||||||
|
public:
|
||||||
|
SeekHead();
|
||||||
|
~SeekHead();
|
||||||
|
|
||||||
|
// TODO(fgalligan): Change this to reserve a certain size. Then check how
|
||||||
|
// big the seek entry to be added is as not every seek entry will be the
|
||||||
|
// maximum size it could be.
|
||||||
|
// Adds a seek entry to be written out when the element is finalized. |id|
|
||||||
|
// must be the coded mkv element id. |pos| is the file position of the
|
||||||
|
// element. Returns true on success.
|
||||||
|
bool AddSeekEntry(uint32 id, uint64 pos);
|
||||||
|
|
||||||
|
// Writes out SeekHead and SeekEntry elements. Returns true on success.
|
||||||
|
bool Finalize(IMkvWriter* writer) const;
|
||||||
|
|
||||||
|
// Reserves space by writing out a Void element which will be updated with
|
||||||
|
// a SeekHead element later. Returns true on success.
|
||||||
|
bool Write(IMkvWriter* writer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// We are going to put a cap on the number of Seek Entries.
|
||||||
|
const static int32 kSeekEntryCount = 4;
|
||||||
|
|
||||||
|
// Returns the maximum size in bytes of one seek entry.
|
||||||
|
uint64 MaxEntrySize() const;
|
||||||
|
|
||||||
|
// Seek entry id element list.
|
||||||
|
uint32 seek_entry_id_[kSeekEntryCount];
|
||||||
|
|
||||||
|
// Seek entry pos element list.
|
||||||
|
uint64 seek_entry_pos_[kSeekEntryCount];
|
||||||
|
|
||||||
|
// The file position of SeekHead element.
|
||||||
|
int64 start_pos_;
|
||||||
|
|
||||||
|
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(SeekHead);
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
|
// Segment Information element
|
||||||
|
class SegmentInfo {
|
||||||
|
public:
|
||||||
|
SegmentInfo();
|
||||||
|
~SegmentInfo();
|
||||||
|
|
||||||
|
// Will update the duration if |duration_| is > 0.0. Returns true on success.
|
||||||
|
bool Finalize(IMkvWriter* writer) const;
|
||||||
|
|
||||||
|
// Sets |muxing_app_| and |writing_app_|.
|
||||||
|
bool Init();
|
||||||
|
|
||||||
|
// Output the Segment Information element to the writer. Returns true on
|
||||||
|
// success.
|
||||||
|
bool Write(IMkvWriter* writer);
|
||||||
|
|
||||||
|
void set_duration(double duration) { duration_ = duration; }
|
||||||
|
double duration() const { return duration_; }
|
||||||
|
const char* muxing_app() const { return muxing_app_; }
|
||||||
|
void set_timecode_scale(uint64 scale) { timecode_scale_ = scale; }
|
||||||
|
uint64 timecode_scale() const { return timecode_scale_; }
|
||||||
|
void set_writing_app(const char* app);
|
||||||
|
const char* writing_app() const { return writing_app_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Segment Information element names.
|
||||||
|
// Initially set to -1 to signify that a duration has not been set and should
|
||||||
|
// not be written out.
|
||||||
|
double duration_;
|
||||||
|
// Set to libwebm-%d.%d.%d.%d, major, minor, build, revision.
|
||||||
|
char* muxing_app_;
|
||||||
|
uint64 timecode_scale_;
|
||||||
|
// Initially set to libwebm-%d.%d.%d.%d, major, minor, build, revision.
|
||||||
|
char* writing_app_;
|
||||||
|
|
||||||
|
// The file position of the duration element.
|
||||||
|
int64 duration_pos_;
|
||||||
|
|
||||||
|
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(SegmentInfo);
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
|
// This class represents the main segment in a WebM file. Currently only
|
||||||
|
// supports one Segment element.
|
||||||
|
class Segment {
|
||||||
|
public:
|
||||||
|
enum Mode {
|
||||||
|
kLive = 0x1,
|
||||||
|
kFile = 0x2
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit Segment(IMkvWriter* writer);
|
||||||
|
virtual ~Segment();
|
||||||
|
|
||||||
|
// Adds an audio track to the segment. Returns the number of the track on
|
||||||
|
// success, 0 on error.
|
||||||
|
uint64 AddAudioTrack(int32 sample_rate, int32 channels);
|
||||||
|
|
||||||
|
// Adds a frame to be output in the file. Returns true on success.
|
||||||
|
// Inputs:
|
||||||
|
// frame: Pointer to the data
|
||||||
|
// length: Length of the data
|
||||||
|
// track_number: Track to add the data to. Value returned by Add track
|
||||||
|
// functions.
|
||||||
|
// timestamp: Timestamp of the frame in nanoseconds from 0.
|
||||||
|
// is_key: Flag telling whether or not this frame is a key frame.
|
||||||
|
bool AddFrame(uint8* frame,
|
||||||
|
uint64 length,
|
||||||
|
uint64 track_number,
|
||||||
|
uint64 timestamp,
|
||||||
|
bool is_key);
|
||||||
|
|
||||||
|
// Adds a video track to the segment. Returns the number of the track on
|
||||||
|
// success, 0 on error.
|
||||||
|
uint64 AddVideoTrack(int32 width, int32 height);
|
||||||
|
|
||||||
|
// Sets which track to use for the Cues element. Must have added the track
|
||||||
|
// before calling this function. Returns true on success. |track_number| is
|
||||||
|
// returned by the Add track functions.
|
||||||
|
bool CuesTrack(uint64 track_number);
|
||||||
|
|
||||||
|
// Writes out any frames that have not been written out. Finalizes the last
|
||||||
|
// cluster. May update the size and duration of the segment. May output the
|
||||||
|
// Cues element. May finalize the SeekHead element. Returns true on success.
|
||||||
|
bool Finalize();
|
||||||
|
|
||||||
|
// Returns the Cues object.
|
||||||
|
Cues* GetCues() { return &cues_; }
|
||||||
|
|
||||||
|
// Returns the Segment Information object.
|
||||||
|
SegmentInfo* GetSegmentInfo() { return &segment_info_; }
|
||||||
|
|
||||||
|
// Search the Tracks and return the track that matches |track_number|.
|
||||||
|
// Returns NULL if there is no track match.
|
||||||
|
Track* GetTrackByNumber(uint64 track_number) const;
|
||||||
|
|
||||||
|
// Toggles whether to output a cues element.
|
||||||
|
void OutputCues(bool output_cues);
|
||||||
|
|
||||||
|
uint64 cues_track() const { return cues_track_; }
|
||||||
|
void set_max_cluster_duration(uint64 max_cluster_duration) {
|
||||||
|
max_cluster_duration_ = max_cluster_duration;
|
||||||
|
}
|
||||||
|
uint64 max_cluster_duration() const { return max_cluster_duration_; }
|
||||||
|
void set_max_cluster_size(uint64 max_cluster_size) {
|
||||||
|
max_cluster_size_ = max_cluster_size;
|
||||||
|
}
|
||||||
|
uint64 max_cluster_size() const { return max_cluster_size_; }
|
||||||
|
void set_mode(Mode mode) { mode_ = mode; }
|
||||||
|
Mode mode() const { return mode_; }
|
||||||
|
bool output_cues() const { return output_cues_; }
|
||||||
|
const SegmentInfo* segment_info() const { return &segment_info_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Adds a cue point to the Cues element. |timestamp| is the time in
|
||||||
|
// nanoseconds of the cue's time. Returns true on success.
|
||||||
|
bool AddCuePoint(uint64 timestamp);
|
||||||
|
|
||||||
|
// Adds the frame to our frame array.
|
||||||
|
bool QueueFrame(Frame* frame);
|
||||||
|
|
||||||
|
// Output all frames that are queued. Returns true on success and if there
|
||||||
|
// are no frames queued.
|
||||||
|
bool WriteFramesAll();
|
||||||
|
|
||||||
|
// Output all frames that are queued that have an end time that is less
|
||||||
|
// then |timestamp|. Returns true on success and if there are no frames
|
||||||
|
// queued.
|
||||||
|
bool WriteFramesLessThan(uint64 timestamp);
|
||||||
|
|
||||||
|
// Outputs the segment header, Segment Information element, SeekHead element,
|
||||||
|
// and Tracks element to |writer_|.
|
||||||
|
bool WriteSegmentHeader();
|
||||||
|
|
||||||
|
// WebM elements
|
||||||
|
Cues cues_;
|
||||||
|
SeekHead seek_head_;
|
||||||
|
SegmentInfo segment_info_;
|
||||||
|
Tracks tracks_;
|
||||||
|
|
||||||
|
// List of clusters.
|
||||||
|
Cluster** cluster_list_;
|
||||||
|
|
||||||
|
// Number of cluster pointers allocated in the cluster list.
|
||||||
|
int32 cluster_list_capacity_;
|
||||||
|
|
||||||
|
// Number of clusters in the cluster list.
|
||||||
|
int32 cluster_list_size_;
|
||||||
|
|
||||||
|
// Track number that is associated with the cues element for this segment.
|
||||||
|
uint64 cues_track_;
|
||||||
|
|
||||||
|
// List of stored audio frames. These variables are used to store frames so
|
||||||
|
// the muxer can follow the guideline "Audio blocks that contain the video
|
||||||
|
// key frame's timecode should be in the same cluster as the video key frame
|
||||||
|
// block."
|
||||||
|
Frame** frames_;
|
||||||
|
|
||||||
|
// Number of frame pointers allocated in the frame list.
|
||||||
|
int32 frames_capacity_;
|
||||||
|
|
||||||
|
// Number of frames in the frame list.
|
||||||
|
int32 frames_size_;
|
||||||
|
|
||||||
|
// Flag telling if a video track has been added to the segment.
|
||||||
|
bool has_video_;
|
||||||
|
|
||||||
|
// Flag telling if the segment's header has been written.
|
||||||
|
bool header_written_;
|
||||||
|
|
||||||
|
// Last timestamp in nanoseconds added to a cluster.
|
||||||
|
uint64 last_timestamp_;
|
||||||
|
|
||||||
|
// Maximum time in nanoseconds for a cluster duration. This variable is a
|
||||||
|
// guideline and some clusters may have a longer duration. Default is 0
|
||||||
|
// which signifies that the muxer will decide.
|
||||||
|
uint64 max_cluster_duration_;
|
||||||
|
|
||||||
|
// Maximum size in bytes for a cluster. This variable is a guideline and
|
||||||
|
// some clusters may have a larger size. Default is 0 which signifies that
|
||||||
|
// the muxer will decide the size.
|
||||||
|
uint64 max_cluster_size_;
|
||||||
|
|
||||||
|
// The mode that segment is in. If set to |kLive| the writer must not
|
||||||
|
// seek backwards.
|
||||||
|
Mode mode_;
|
||||||
|
|
||||||
|
// Flag telling the muxer that a new cluster should be started with the next
|
||||||
|
// frame.
|
||||||
|
bool new_cluster_;
|
||||||
|
|
||||||
|
// Flag telling the muxer that a new cue point should be added.
|
||||||
|
bool new_cuepoint_;
|
||||||
|
|
||||||
|
// TODO(fgalligan): Should we add support for more than one Cues element?
|
||||||
|
// Flag whether or not the muxer should output a Cues element.
|
||||||
|
bool output_cues_;
|
||||||
|
|
||||||
|
// The file position of the segment's payload.
|
||||||
|
int64 payload_pos_;
|
||||||
|
|
||||||
|
// The file position of the element's size.
|
||||||
|
int64 size_position_;
|
||||||
|
|
||||||
|
// Pointer to the writer object. Not owned by this class.
|
||||||
|
IMkvWriter* writer_;
|
||||||
|
|
||||||
|
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Segment);
|
||||||
|
};
|
||||||
|
|
||||||
|
} //end namespace mkvmuxer
|
||||||
|
|
||||||
|
#endif //MKVMUXER_HPP
|
||||||
199
mkvmuxer_2008.vcproj
Normal file
199
mkvmuxer_2008.vcproj
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="9.00"
|
||||||
|
Name="mkvmuxer"
|
||||||
|
ProjectGUID="{7B1F12CA-0724-430B-B61A-1D357C912CBA}"
|
||||||
|
RootNamespace="mkvmuxer"
|
||||||
|
Keyword="Win32Proj"
|
||||||
|
TargetFrameworkVersion="196613"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"
|
||||||
|
/>
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="4"
|
||||||
|
CharacterSet="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="4"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLibrarianTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="4"
|
||||||
|
CharacterSet="1"
|
||||||
|
WholeProgramOptimization="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="2"
|
||||||
|
EnableIntrinsicFunctions="true"
|
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
EnableFunctionLevelLinking="true"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="4"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLibrarianTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\mkvmuxer.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\mkvmuxerutil.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\mkvwriter.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Header Files"
|
||||||
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\mkvmuxer.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\mkvmuxertypes.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\mkvmuxerutil.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\mkvwriter.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\webmids.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Resource Files"
|
||||||
|
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||||
|
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||||
|
>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
||||||
29
mkvmuxertypes.hpp
Normal file
29
mkvmuxertypes.hpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style license
|
||||||
|
// that can be found in the LICENSE file in the root of the source
|
||||||
|
// tree. An additional intellectual property rights grant can be found
|
||||||
|
// in the file PATENTS. All contributing project authors may
|
||||||
|
// be found in the AUTHORS file in the root of the source tree.
|
||||||
|
|
||||||
|
#ifndef MKVMUXERTYPES_HPP
|
||||||
|
#define MKVMUXERTYPES_HPP
|
||||||
|
|
||||||
|
// Copied from Chromium basictypes.h
|
||||||
|
// A macro to disallow the copy constructor and operator= functions
|
||||||
|
// This should be used in the private: declarations for a class
|
||||||
|
#define LIBWEBM_DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||||
|
TypeName(const TypeName&); \
|
||||||
|
void operator=(const TypeName&)
|
||||||
|
|
||||||
|
namespace mkvmuxer {
|
||||||
|
|
||||||
|
typedef unsigned char uint8;
|
||||||
|
typedef int int32;
|
||||||
|
typedef unsigned int uint32;
|
||||||
|
typedef long long int64;
|
||||||
|
typedef unsigned long long uint64;
|
||||||
|
|
||||||
|
} //end namespace mkvmuxer
|
||||||
|
|
||||||
|
#endif // MKVMUXERTYPES_HPP
|
||||||
375
mkvmuxerutil.cpp
Normal file
375
mkvmuxerutil.cpp
Normal file
@@ -0,0 +1,375 @@
|
|||||||
|
// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style license
|
||||||
|
// that can be found in the LICENSE file in the root of the source
|
||||||
|
// tree. An additional intellectual property rights grant can be found
|
||||||
|
// in the file PATENTS. All contributing project authors may
|
||||||
|
// be found in the AUTHORS file in the root of the source tree.
|
||||||
|
|
||||||
|
#include "mkvmuxerutil.hpp"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include "mkvwriter.hpp"
|
||||||
|
#include "webmids.hpp"
|
||||||
|
|
||||||
|
namespace mkvmuxer {
|
||||||
|
|
||||||
|
int32 GetCodedUIntSize(uint64 value) {
|
||||||
|
|
||||||
|
if (value < 0x000000000000007FULL)
|
||||||
|
return 1;
|
||||||
|
else if (value < 0x0000000000003FFFULL)
|
||||||
|
return 2;
|
||||||
|
else if (value < 0x00000000001FFFFFULL)
|
||||||
|
return 3;
|
||||||
|
else if (value < 0x000000000FFFFFFFULL)
|
||||||
|
return 4;
|
||||||
|
else if (value < 0x00000007FFFFFFFFULL)
|
||||||
|
return 5;
|
||||||
|
else if (value < 0x000003FFFFFFFFFFULL)
|
||||||
|
return 6;
|
||||||
|
else if (value < 0x0001FFFFFFFFFFFFULL)
|
||||||
|
return 7;
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 GetUIntSize(uint64 value) {
|
||||||
|
|
||||||
|
if (value < 0x0000000000000100ULL)
|
||||||
|
return 1;
|
||||||
|
else if (value < 0x0000000000010000ULL)
|
||||||
|
return 2;
|
||||||
|
else if (value < 0x0000000001000000ULL)
|
||||||
|
return 3;
|
||||||
|
else if (value < 0x0000000100000000ULL)
|
||||||
|
return 4;
|
||||||
|
else if (value < 0x0000010000000000ULL)
|
||||||
|
return 5;
|
||||||
|
else if (value < 0x0001000000000000ULL)
|
||||||
|
return 6;
|
||||||
|
else if (value < 0x0100000000000000ULL)
|
||||||
|
return 7;
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 EbmlElementSize(uint64 type, uint64 value, bool master) {
|
||||||
|
// Size of EBML ID
|
||||||
|
int32 ebml_size = GetUIntSize(type);
|
||||||
|
|
||||||
|
// Datasize
|
||||||
|
ebml_size += GetUIntSize(value);
|
||||||
|
|
||||||
|
// Size of Datasize
|
||||||
|
if (!master)
|
||||||
|
ebml_size++;
|
||||||
|
|
||||||
|
return ebml_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 EbmlElementSize(uint64 type, float value, bool master) {
|
||||||
|
// Size of EBML ID
|
||||||
|
uint64 ebml_size = GetUIntSize(type);
|
||||||
|
|
||||||
|
// Datasize
|
||||||
|
ebml_size += sizeof(value);
|
||||||
|
|
||||||
|
// Size of Datasize
|
||||||
|
if (!master)
|
||||||
|
ebml_size++;
|
||||||
|
|
||||||
|
return ebml_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 EbmlElementSize(uint64 type, const char* value, bool master) {
|
||||||
|
assert(value != NULL);
|
||||||
|
|
||||||
|
// Size of EBML ID
|
||||||
|
uint64 ebml_size = GetUIntSize(type);
|
||||||
|
|
||||||
|
// Datasize
|
||||||
|
ebml_size += strlen(value);
|
||||||
|
|
||||||
|
// Size of Datasize
|
||||||
|
if (!master)
|
||||||
|
ebml_size++;
|
||||||
|
|
||||||
|
return ebml_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 EbmlElementSize(uint64 type,
|
||||||
|
const uint8* value,
|
||||||
|
uint64 size,
|
||||||
|
bool master) {
|
||||||
|
assert(value != NULL);
|
||||||
|
|
||||||
|
// Size of EBML ID
|
||||||
|
uint64 ebml_size = GetUIntSize(type);
|
||||||
|
|
||||||
|
// Datasize
|
||||||
|
ebml_size += size;
|
||||||
|
|
||||||
|
// Size of Datasize
|
||||||
|
if (!master)
|
||||||
|
ebml_size += GetCodedUIntSize(size);
|
||||||
|
|
||||||
|
return ebml_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 SerializeInt(
|
||||||
|
IMkvWriter* writer,
|
||||||
|
int64 value,
|
||||||
|
int32 size) {
|
||||||
|
assert(writer);
|
||||||
|
assert(size >= 0);
|
||||||
|
assert(size <= 8);
|
||||||
|
|
||||||
|
for (int32 i = 1; i <= size; ++i) {
|
||||||
|
const int32 byte_count = size - i;
|
||||||
|
const int32 bit_count = byte_count * 8;
|
||||||
|
|
||||||
|
const int64 bb = value >> bit_count;
|
||||||
|
const uint8 b = static_cast<uint8>(bb);
|
||||||
|
|
||||||
|
const int32 status = writer->Write(&b, 1);
|
||||||
|
|
||||||
|
if (status < 0)
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 SerializeFloat(IMkvWriter* writer, float f) {
|
||||||
|
assert(writer);
|
||||||
|
const uint32& val = reinterpret_cast<const uint32&>(f);
|
||||||
|
|
||||||
|
for (int32 i = 1; i <= 4; ++i) {
|
||||||
|
const int32 byte_count = 4 - i;
|
||||||
|
const int32 bit_count = byte_count * 8;
|
||||||
|
|
||||||
|
const uint32 bb = val >> bit_count;
|
||||||
|
const uint8 b = static_cast<uint8>(bb);
|
||||||
|
|
||||||
|
const int32 status = writer->Write(&b, 1);
|
||||||
|
|
||||||
|
if (status < 0)
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 WriteUInt(IMkvWriter* writer, uint64 value) {
|
||||||
|
assert(writer);
|
||||||
|
int32 size = GetCodedUIntSize(value);
|
||||||
|
|
||||||
|
return WriteUIntSize(writer, value, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 WriteUIntSize(IMkvWriter* writer, uint64 value, int32 size) {
|
||||||
|
assert(writer);
|
||||||
|
assert(size >= 0);
|
||||||
|
|
||||||
|
if (size > 0) {
|
||||||
|
assert(size <= 8);
|
||||||
|
|
||||||
|
const uint64 bit = 1LL << (size * 7);
|
||||||
|
assert(value <= (bit - 2));
|
||||||
|
|
||||||
|
value |= bit;
|
||||||
|
} else {
|
||||||
|
size = 1;
|
||||||
|
int64 bit;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
bit = 1LL << (size * 7);
|
||||||
|
const uint64 max = bit - 2;
|
||||||
|
|
||||||
|
if (value <= max)
|
||||||
|
break;
|
||||||
|
|
||||||
|
++size;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(size <= 8);
|
||||||
|
value |= bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SerializeInt(writer, value, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 WriteID(IMkvWriter* writer, uint64 type) {
|
||||||
|
assert(writer);
|
||||||
|
const int32 size = GetUIntSize(type);
|
||||||
|
|
||||||
|
return SerializeInt(writer, type, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteEbmlMasterElement(IMkvWriter* writer, uint64 type, uint64 size) {
|
||||||
|
assert(writer);
|
||||||
|
|
||||||
|
if (WriteID(writer, type))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (WriteUInt(writer, size))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value) {
|
||||||
|
assert(writer);
|
||||||
|
|
||||||
|
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, float value) {
|
||||||
|
assert(writer);
|
||||||
|
|
||||||
|
if (WriteID(writer, type))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (WriteUInt(writer, 4))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (SerializeFloat(writer, value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value) {
|
||||||
|
assert(writer);
|
||||||
|
assert(value != NULL);
|
||||||
|
|
||||||
|
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,
|
||||||
|
const uint8* value,
|
||||||
|
uint64 size) {
|
||||||
|
assert(writer);
|
||||||
|
assert(value != NULL);
|
||||||
|
assert(size > 0);
|
||||||
|
|
||||||
|
if (WriteID(writer, type))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (WriteUInt(writer, size))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (writer->Write(value, static_cast<uint32>(size)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 WriteSimpleBlock(IMkvWriter* writer,
|
||||||
|
const uint8* data,
|
||||||
|
uint64 length,
|
||||||
|
char track_number,
|
||||||
|
short timecode,
|
||||||
|
bool is_key) {
|
||||||
|
assert(writer);
|
||||||
|
assert(data != NULL);
|
||||||
|
assert(length > 0);
|
||||||
|
assert(track_number > 0);
|
||||||
|
assert(timecode >= 0);
|
||||||
|
|
||||||
|
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, static_cast<uint64>(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
|
||||||
|
// Subtract one for the void ID and the coded size.
|
||||||
|
uint64 void_entry_size = size - 1 - GetCodedUIntSize(size-1);
|
||||||
|
uint64 void_size = EbmlElementSize(kMkvVoid, void_entry_size, true) +
|
||||||
|
void_entry_size;
|
||||||
|
assert(void_size == size);
|
||||||
|
|
||||||
|
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)
|
||||||
|
return 0;
|
||||||
|
assert(stop_position - payload_position == static_cast<int64>(void_size));
|
||||||
|
|
||||||
|
return void_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetVersion(int32& major, int32& minor, int32& build, int32& revision) {
|
||||||
|
major = 0;
|
||||||
|
minor = 0;
|
||||||
|
build = 0;
|
||||||
|
revision = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mkvmuxer
|
||||||
82
mkvmuxerutil.hpp
Normal file
82
mkvmuxerutil.hpp
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style license
|
||||||
|
// that can be found in the LICENSE file in the root of the source
|
||||||
|
// tree. An additional intellectual property rights grant can be found
|
||||||
|
// in the file PATENTS. All contributing project authors may
|
||||||
|
// be found in the AUTHORS file in the root of the source tree.
|
||||||
|
|
||||||
|
#ifndef MKVMUXERUTIL_HPP
|
||||||
|
#define MKVMUXERUTIL_HPP
|
||||||
|
|
||||||
|
#include "mkvmuxertypes.hpp"
|
||||||
|
|
||||||
|
namespace mkvmuxer {
|
||||||
|
|
||||||
|
class IMkvWriter;
|
||||||
|
|
||||||
|
const uint64 kEbmlUnknownValue = 0x01FFFFFFFFFFFFFFULL;
|
||||||
|
|
||||||
|
// Writes out |value| in Big Endian order. Returns 0 on success.
|
||||||
|
int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size);
|
||||||
|
|
||||||
|
// Returns the size in bytes of the element. |master| must be set to true if
|
||||||
|
// the element is an Mkv master element.
|
||||||
|
// TODO(fgalligan): Change these functions so they are master element aware.
|
||||||
|
uint64 EbmlElementSize(uint64 type, uint64 value, bool master);
|
||||||
|
uint64 EbmlElementSize(uint64 type, float value, bool master);
|
||||||
|
uint64 EbmlElementSize(uint64 type, const char* value, bool master);
|
||||||
|
uint64 EbmlElementSize(uint64 type,
|
||||||
|
const uint8* value,
|
||||||
|
uint64 size,
|
||||||
|
bool master);
|
||||||
|
|
||||||
|
// Creates an EBML coded number from |value| and writes it out. The size of
|
||||||
|
// the coded number is determined by the value of |value|. |value| must not
|
||||||
|
// be in a coded form. Returns 0 on success.
|
||||||
|
int32 WriteUInt(IMkvWriter* writer, uint64 value);
|
||||||
|
|
||||||
|
// Creates an EBML coded number from |value| and writes it out. The size of
|
||||||
|
// the coded number is determined by the value of |size|. |value| must not
|
||||||
|
// be in a coded form. Returns 0 on success.
|
||||||
|
int32 WriteUIntSize(IMkvWriter* writer, uint64 value, int32 size);
|
||||||
|
|
||||||
|
// Output an Mkv master element. Returns true if the element was written.
|
||||||
|
bool WriteEbmlMasterElement(IMkvWriter* writer, uint64 value, uint64 size);
|
||||||
|
|
||||||
|
// Output an Mkv non-master element. Returns true if the element was written.
|
||||||
|
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value);
|
||||||
|
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value);
|
||||||
|
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value);
|
||||||
|
bool WriteEbmlElement(IMkvWriter* writer,
|
||||||
|
uint64 type,
|
||||||
|
const uint8* value,
|
||||||
|
uint64 size);
|
||||||
|
|
||||||
|
// Output an Mkv Simple Block.
|
||||||
|
// Inputs:
|
||||||
|
// data: Pointer to the data.
|
||||||
|
// length: Length of the data.
|
||||||
|
// track_number: Track to add the data to. Value returned by Add track
|
||||||
|
// functions.
|
||||||
|
// timecode: Relative timecode of the Block.
|
||||||
|
// is_key: Flag telling whether or not this frame is a key frame.
|
||||||
|
uint64 WriteSimpleBlock(IMkvWriter* writer,
|
||||||
|
const uint8* data,
|
||||||
|
uint64 length,
|
||||||
|
char track_number,
|
||||||
|
short timecode,
|
||||||
|
bool is_key);
|
||||||
|
|
||||||
|
// Output a void element. |size| must be the entire size in bytes that will be
|
||||||
|
// void. The function will calculate the size of the void header and subtract
|
||||||
|
// it from |size|.
|
||||||
|
uint64 WriteVoidElement(IMkvWriter* writer, uint64 size);
|
||||||
|
|
||||||
|
// Returns the version number of the muxer in |major|, |minor|, |build|,
|
||||||
|
// and |revision|.
|
||||||
|
void GetVersion(int32& major, int32& minor, int32& build, int32& revision);
|
||||||
|
|
||||||
|
} //end namespace mkvmuxer
|
||||||
|
|
||||||
|
#endif // MKVMUXERUTIL_HPP
|
||||||
@@ -8,6 +8,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample", "sample_2008.vcpro
|
|||||||
{F9128EC6-C008-41AD-B38F-0E70D549D9F4} = {F9128EC6-C008-41AD-B38F-0E70D549D9F4}
|
{F9128EC6-C008-41AD-B38F-0E70D549D9F4} = {F9128EC6-C008-41AD-B38F-0E70D549D9F4}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mkvmuxer", "mkvmuxer_2008.vcproj", "{7B1F12CA-0724-430B-B61A-1D357C912CBA}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_muxer", "sample_muxer\sample_muxer.vcproj", "{B407561F-1F5E-4798-B9C2-81AB09CFBC16}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{F9128EC6-C008-41AD-B38F-0E70D549D9F4} = {F9128EC6-C008-41AD-B38F-0E70D549D9F4}
|
||||||
|
{7B1F12CA-0724-430B-B61A-1D357C912CBA} = {7B1F12CA-0724-430B-B61A-1D357C912CBA}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Win32 = Debug|Win32
|
Debug|Win32 = Debug|Win32
|
||||||
@@ -22,6 +30,14 @@ Global
|
|||||||
{0CB5681F-6065-490C-98C8-05531732ED7E}.Debug|Win32.Build.0 = Debug|Win32
|
{0CB5681F-6065-490C-98C8-05531732ED7E}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
{0CB5681F-6065-490C-98C8-05531732ED7E}.Release|Win32.ActiveCfg = Release|Win32
|
{0CB5681F-6065-490C-98C8-05531732ED7E}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
{0CB5681F-6065-490C-98C8-05531732ED7E}.Release|Win32.Build.0 = Release|Win32
|
{0CB5681F-6065-490C-98C8-05531732ED7E}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{7B1F12CA-0724-430B-B61A-1D357C912CBA}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{B407561F-1F5E-4798-B9C2-81AB09CFBC16}.Release|Win32.Build.0 = Release|Win32
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
87
mkvwriter.cpp
Normal file
87
mkvwriter.cpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style license
|
||||||
|
// that can be found in the LICENSE file in the root of the source
|
||||||
|
// tree. An additional intellectual property rights grant can be found
|
||||||
|
// in the file PATENTS. All contributing project authors may
|
||||||
|
// be found in the AUTHORS file in the root of the source tree.
|
||||||
|
|
||||||
|
#include "mkvwriter.hpp"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#include <share.h> // for _SH_DENYWR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
namespace mkvmuxer {
|
||||||
|
|
||||||
|
MkvWriter::MkvWriter() : file_(NULL) {
|
||||||
|
}
|
||||||
|
|
||||||
|
MkvWriter::~MkvWriter() {
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 MkvWriter::Write(const void* buffer, uint32 length) {
|
||||||
|
assert(file_);
|
||||||
|
|
||||||
|
if (length == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (buffer == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
const size_t bytes_written = fwrite(buffer, 1, length, file_);
|
||||||
|
|
||||||
|
return (bytes_written == length) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MkvWriter::Open(const char* filename) {
|
||||||
|
if (filename == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (file_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
file_ = _fsopen(filename, "wb", _SH_DENYWR);
|
||||||
|
#else
|
||||||
|
file_ = fopen(filename, "wb");
|
||||||
|
#endif
|
||||||
|
if (file_ == NULL)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MkvWriter::Close() {
|
||||||
|
if (file_) {
|
||||||
|
fclose(file_);
|
||||||
|
file_ = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 MkvWriter::Position() const {
|
||||||
|
assert(file_);
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
return _ftelli64(file_);
|
||||||
|
#else
|
||||||
|
return ftell(file_);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 MkvWriter::Position(int64 position) {
|
||||||
|
assert(file_);
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
return _fseeki64(file_, position, SEEK_SET);
|
||||||
|
#else
|
||||||
|
return fseek(file_, position, SEEK_SET);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MkvWriter::Seekable() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mkvmuxer
|
||||||
48
mkvwriter.hpp
Normal file
48
mkvwriter.hpp
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style license
|
||||||
|
// that can be found in the LICENSE file in the root of the source
|
||||||
|
// tree. An additional intellectual property rights grant can be found
|
||||||
|
// in the file PATENTS. All contributing project authors may
|
||||||
|
// be found in the AUTHORS file in the root of the source tree.
|
||||||
|
|
||||||
|
#ifndef MKVWRITER_HPP
|
||||||
|
#define MKVWRITER_HPP
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "mkvmuxer.hpp"
|
||||||
|
#include "mkvmuxertypes.hpp"
|
||||||
|
|
||||||
|
namespace mkvmuxer {
|
||||||
|
|
||||||
|
// Default implementation of the IMkvWriter interface on Windows.
|
||||||
|
class MkvWriter : public IMkvWriter {
|
||||||
|
public:
|
||||||
|
MkvWriter();
|
||||||
|
virtual ~MkvWriter();
|
||||||
|
|
||||||
|
// IMkvWriter interface
|
||||||
|
virtual int64 Position() const;
|
||||||
|
virtual int32 Position(int64 position);
|
||||||
|
virtual bool Seekable() const;
|
||||||
|
virtual int32 Write(const void* buffer, uint32 length);
|
||||||
|
|
||||||
|
// Creates and opens a file for writing. |filename| is the name of the file
|
||||||
|
// to open. This function will overwrite the contents of |filename|. Returns
|
||||||
|
// true on success.
|
||||||
|
bool Open(const char* filename);
|
||||||
|
|
||||||
|
// Closes an opened file.
|
||||||
|
void Close();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// File handle to output file.
|
||||||
|
FILE* file_;
|
||||||
|
|
||||||
|
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(MkvWriter);
|
||||||
|
};
|
||||||
|
|
||||||
|
} //end namespace mkvmuxer
|
||||||
|
|
||||||
|
#endif // MKVWRITER_HPP
|
||||||
352
sample_muxer/sample_muxer.cpp
Normal file
352
sample_muxer/sample_muxer.cpp
Normal file
@@ -0,0 +1,352 @@
|
|||||||
|
// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style license
|
||||||
|
// that can be found in the LICENSE file in the root of the source
|
||||||
|
// tree. An additional intellectual property rights grant can be found
|
||||||
|
// in the file PATENTS. All contributing project authors may
|
||||||
|
// be found in the AUTHORS file in the root of the source tree.
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// libwebm parser includes
|
||||||
|
#include "mkvreader.hpp"
|
||||||
|
#include "mkvparser.hpp"
|
||||||
|
|
||||||
|
// libwebm muxer includes
|
||||||
|
#include "mkvmuxer.hpp"
|
||||||
|
#include "mkvwriter.hpp"
|
||||||
|
#include "mkvmuxerutil.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void Usage() {
|
||||||
|
printf("Usage: sample_muxer -i input -o output [options]\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("Main options:\n");
|
||||||
|
printf(" -h | -? show help\n");
|
||||||
|
printf(" -video <int> >0 outputs video\n");
|
||||||
|
printf(" -audio <int> >0 outputs audio\n");
|
||||||
|
printf(" -live <int> >0 puts the muxer into live mode\n");
|
||||||
|
printf(" 0 puts the muxer into file mode\n");
|
||||||
|
printf(" -output_cues <int> >0 outputs cues element\n");
|
||||||
|
printf(" -cues_on_video_track <int> >0 outputs cues on video track\n");
|
||||||
|
printf(" 0 outputs cues on audio track\n");
|
||||||
|
printf(" -max_cluster_duration <double> in seconds\n");
|
||||||
|
printf(" -max_cluster_size <int> in bytes\n");
|
||||||
|
printf(" -switch_tracks <int> >0 switches tracks in output\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("Video options:\n");
|
||||||
|
printf(" -display_width <int> Display width in pixels\n");
|
||||||
|
printf(" -display_height <int> Display height in pixels\n");
|
||||||
|
printf(" -stereo_mode <int> 3D video mode\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("Cues options:\n");
|
||||||
|
printf(" -output_cues_block_number <int> >0 outputs cue block number\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
} //end namespace
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
using mkvmuxer::uint64;
|
||||||
|
|
||||||
|
char* input = NULL;
|
||||||
|
char* output = NULL;
|
||||||
|
|
||||||
|
// Segment variables
|
||||||
|
bool output_video = true;
|
||||||
|
bool output_audio = true;
|
||||||
|
bool live_mode = false;
|
||||||
|
bool output_cues = true;
|
||||||
|
bool cues_on_video_track = true;
|
||||||
|
uint64 max_cluster_duration = 0;
|
||||||
|
uint64 max_cluster_size = 0;
|
||||||
|
bool switch_tracks = false;
|
||||||
|
|
||||||
|
bool output_cues_block_number = true;
|
||||||
|
|
||||||
|
uint64 display_width = 0;
|
||||||
|
uint64 display_height = 0;
|
||||||
|
uint64 stereo_mode = 0;
|
||||||
|
|
||||||
|
for (int i = 1; i < argc; ++i) {
|
||||||
|
char* end;
|
||||||
|
|
||||||
|
if (!strcmp("-h", argv[i]) || !strcmp("-?", argv[i])) {
|
||||||
|
Usage();
|
||||||
|
return 0;
|
||||||
|
} else if (!strcmp("-i", argv[i])) {
|
||||||
|
input = argv[++i];
|
||||||
|
} else if (!strcmp("-o", argv[i])) {
|
||||||
|
output = argv[++i];
|
||||||
|
} else if (!strcmp("-video", argv[i])) {
|
||||||
|
output_video = strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||||
|
} else if (!strcmp("-audio", argv[i])) {
|
||||||
|
output_audio = strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||||
|
} else if (!strcmp("-live", argv[i])) {
|
||||||
|
live_mode = strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||||
|
} else if (!strcmp("-output_cues", argv[i])) {
|
||||||
|
output_cues = strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||||
|
} else if (!strcmp("-cues_on_video_track", argv[i])) {
|
||||||
|
cues_on_video_track = strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||||
|
} else if (!strcmp("-max_cluster_duration", argv[i])) {
|
||||||
|
const double seconds = strtod(argv[++i], &end);
|
||||||
|
max_cluster_duration =
|
||||||
|
static_cast<uint64>(seconds * 1000000000.0);
|
||||||
|
} else if (!strcmp("-max_cluster_size", argv[i])) {
|
||||||
|
max_cluster_size = strtol(argv[++i], &end, 10);
|
||||||
|
} else if (!strcmp("-switch_tracks", argv[i])) {
|
||||||
|
switch_tracks = strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||||
|
} else if (!strcmp("-display_width", argv[i])) {
|
||||||
|
display_width = strtol(argv[++i], &end, 10);
|
||||||
|
} else if (!strcmp("-display_height", argv[i])) {
|
||||||
|
display_height = strtol(argv[++i], &end, 10);
|
||||||
|
} else if (!strcmp("-stereo_mode", argv[i])) {
|
||||||
|
stereo_mode = strtol(argv[++i], &end, 10);
|
||||||
|
} else if (!strcmp("-output_cues_block_number", argv[i])) {
|
||||||
|
output_cues_block_number =
|
||||||
|
strtol(argv[++i], &end, 10) == 0 ? false : true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input == NULL || output == NULL) {
|
||||||
|
Usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get parser header info
|
||||||
|
mkvparser::MkvReader reader;
|
||||||
|
|
||||||
|
if (reader.Open(input)) {
|
||||||
|
printf("\n Filename is invalid or error while opening.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long pos = 0;
|
||||||
|
mkvparser::EBMLHeader ebml_header;
|
||||||
|
ebml_header.Parse(&reader, pos);
|
||||||
|
|
||||||
|
mkvparser::Segment* parser_segment;
|
||||||
|
long long ret = mkvparser::Segment::CreateInstance(&reader,
|
||||||
|
pos,
|
||||||
|
parser_segment);
|
||||||
|
if (ret) {
|
||||||
|
printf("\n Segment::CreateInstance() failed.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = parser_segment->Load();
|
||||||
|
if (ret < 0) {
|
||||||
|
printf("\n Segment::Load() failed.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mkvparser::SegmentInfo* const segment_info = parser_segment->GetInfo();
|
||||||
|
const long long timeCodeScale = segment_info->GetTimeCodeScale();
|
||||||
|
|
||||||
|
// Set muxer header info
|
||||||
|
mkvmuxer::MkvWriter writer;
|
||||||
|
|
||||||
|
if (!writer.Open(output)) {
|
||||||
|
printf("\n Filename is invalid or error while opening.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Segment element attributes
|
||||||
|
mkvmuxer::Segment muxer_segment(&writer);
|
||||||
|
if (live_mode)
|
||||||
|
muxer_segment.set_mode(mkvmuxer::Segment::kLive);
|
||||||
|
else
|
||||||
|
muxer_segment.set_mode(mkvmuxer::Segment::kFile);
|
||||||
|
|
||||||
|
if (max_cluster_duration > 0)
|
||||||
|
muxer_segment.set_max_cluster_duration(max_cluster_duration);
|
||||||
|
if (max_cluster_size > 0)
|
||||||
|
muxer_segment.set_max_cluster_size(max_cluster_size);
|
||||||
|
muxer_segment.OutputCues(output_cues);
|
||||||
|
|
||||||
|
// Set SegmentInfo element attributes
|
||||||
|
mkvmuxer::SegmentInfo* info = muxer_segment.GetSegmentInfo();
|
||||||
|
info->set_timecode_scale(timeCodeScale);
|
||||||
|
info->set_writing_app("sample_muxer");
|
||||||
|
|
||||||
|
// Set Tracks element attributes
|
||||||
|
enum { kVideoTrack = 1, kAudioTrack = 2 };
|
||||||
|
const mkvparser::Tracks* parser_tracks = parser_segment->GetTracks();
|
||||||
|
unsigned long i = 0;
|
||||||
|
uint64 vid_track = 0; // no track added
|
||||||
|
uint64 aud_track = 0; // no track added
|
||||||
|
|
||||||
|
while (i != parser_tracks->GetTracksCount()) {
|
||||||
|
int track_num = i++;
|
||||||
|
if (switch_tracks)
|
||||||
|
track_num = i % parser_tracks->GetTracksCount();
|
||||||
|
|
||||||
|
const mkvparser::Track* const parser_track =
|
||||||
|
parser_tracks->GetTrackByIndex(track_num);
|
||||||
|
|
||||||
|
if (parser_track == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// TODO(fgalligan): Add support for language to parser.
|
||||||
|
const char* track_name = parser_track->GetNameAsUTF8();
|
||||||
|
|
||||||
|
const long long track_type = parser_track->GetType();
|
||||||
|
|
||||||
|
if (track_type == kVideoTrack && output_video) {
|
||||||
|
// Get the video track from the parser
|
||||||
|
const mkvparser::VideoTrack* const pVideoTrack =
|
||||||
|
static_cast<const mkvparser::VideoTrack*>(parser_track);
|
||||||
|
const long long width = pVideoTrack->GetWidth();
|
||||||
|
const long long height = pVideoTrack->GetHeight();
|
||||||
|
|
||||||
|
// Add the video track to the muxer
|
||||||
|
vid_track = muxer_segment.AddVideoTrack(static_cast<int>(width),
|
||||||
|
static_cast<int>(height));
|
||||||
|
if (!vid_track) {
|
||||||
|
printf("\n Could not add video track.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mkvmuxer::VideoTrack* video =
|
||||||
|
static_cast<mkvmuxer::VideoTrack*>(
|
||||||
|
muxer_segment.GetTrackByNumber(vid_track));
|
||||||
|
if (!video) {
|
||||||
|
printf("\n Could not get video track.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (track_name)
|
||||||
|
video->set_name(track_name);
|
||||||
|
|
||||||
|
if (display_width > 0)
|
||||||
|
video->set_display_width(display_width);
|
||||||
|
if (display_height > 0)
|
||||||
|
video->set_display_height(display_height);
|
||||||
|
if (stereo_mode > 0)
|
||||||
|
video->SetStereoMode(stereo_mode);
|
||||||
|
|
||||||
|
const double rate = pVideoTrack->GetFrameRate();
|
||||||
|
if (rate > 0.0) {
|
||||||
|
video->set_frame_rate(rate);
|
||||||
|
}
|
||||||
|
} else if (track_type == kAudioTrack && output_audio) {
|
||||||
|
// Get the audio track from the parser
|
||||||
|
const mkvparser::AudioTrack* const pAudioTrack =
|
||||||
|
static_cast<const mkvparser::AudioTrack*>(parser_track);
|
||||||
|
const long long channels = pAudioTrack->GetChannels();
|
||||||
|
const double sample_rate = pAudioTrack->GetSamplingRate();
|
||||||
|
|
||||||
|
// Add the audio track to the muxer
|
||||||
|
aud_track = muxer_segment.AddAudioTrack(static_cast<int>(sample_rate),
|
||||||
|
static_cast<int>(channels));
|
||||||
|
if (!aud_track) {
|
||||||
|
printf("\n Could not add audio track.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mkvmuxer::AudioTrack* audio =
|
||||||
|
static_cast<mkvmuxer::AudioTrack*>(
|
||||||
|
muxer_segment.GetTrackByNumber(aud_track));
|
||||||
|
if (!audio) {
|
||||||
|
printf("\n Could not get audio track.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (track_name)
|
||||||
|
audio->set_name(track_name);
|
||||||
|
|
||||||
|
size_t private_size;
|
||||||
|
const unsigned char* private_data =
|
||||||
|
pAudioTrack->GetCodecPrivate(private_size);
|
||||||
|
if (private_size > 0) {
|
||||||
|
if (!audio->SetCodecPrivate(private_data, private_size)) {
|
||||||
|
printf("\n Could not add audio private data.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const long long bit_depth = pAudioTrack->GetBitDepth();
|
||||||
|
if (bit_depth > 0)
|
||||||
|
audio->set_bit_depth(bit_depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Cues element attributes
|
||||||
|
mkvmuxer::Cues* cues = muxer_segment.GetCues();
|
||||||
|
cues->set_output_block_number(output_cues_block_number);
|
||||||
|
if (cues_on_video_track) {
|
||||||
|
if (vid_track)
|
||||||
|
muxer_segment.CuesTrack(vid_track);
|
||||||
|
} else {
|
||||||
|
if (aud_track)
|
||||||
|
muxer_segment.CuesTrack(aud_track);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write clusters
|
||||||
|
unsigned char* data = NULL;
|
||||||
|
int data_len = 0;
|
||||||
|
|
||||||
|
const mkvparser::Cluster* cluster = parser_segment->GetFirst();
|
||||||
|
|
||||||
|
while ((cluster != NULL) && !cluster->EOS()) {
|
||||||
|
const mkvparser::BlockEntry* block_entry = cluster->GetFirst();
|
||||||
|
|
||||||
|
while ((block_entry != NULL) && !block_entry->EOS()) {
|
||||||
|
const mkvparser::Block* const block = block_entry->GetBlock();
|
||||||
|
const long long trackNum = block->GetTrackNumber();
|
||||||
|
const mkvparser::Track* const parser_track =
|
||||||
|
parser_tracks->GetTrackByNumber(
|
||||||
|
static_cast<unsigned long>(trackNum));
|
||||||
|
const long long track_type = parser_track->GetType();
|
||||||
|
|
||||||
|
if ((track_type == kAudioTrack && output_audio) ||
|
||||||
|
(track_type == kVideoTrack && output_video)) {
|
||||||
|
const int frame_count = block->GetFrameCount();
|
||||||
|
const long long time_ns = block->GetTime(cluster);
|
||||||
|
const bool is_key = block->IsKey();
|
||||||
|
|
||||||
|
for (int i = 0; i < frame_count; ++i) {
|
||||||
|
const mkvparser::Block::Frame& frame = block->GetFrame(i);
|
||||||
|
|
||||||
|
if (frame.len > data_len) {
|
||||||
|
delete [] data;
|
||||||
|
data = new unsigned char[frame.len];
|
||||||
|
if (!data)
|
||||||
|
return -1;
|
||||||
|
data_len = frame.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame.Read(&reader, data))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
uint64 track_num = vid_track;
|
||||||
|
if (track_type == kAudioTrack)
|
||||||
|
track_num = aud_track;
|
||||||
|
|
||||||
|
if (!muxer_segment.AddFrame(data,
|
||||||
|
frame.len,
|
||||||
|
track_num,
|
||||||
|
time_ns,
|
||||||
|
is_key)) {
|
||||||
|
printf("\n Could not add frame.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
block_entry = cluster->GetNext(block_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
cluster = parser_segment->GetNext(cluster);
|
||||||
|
}
|
||||||
|
|
||||||
|
muxer_segment.Finalize();
|
||||||
|
|
||||||
|
delete [] data;
|
||||||
|
delete parser_segment;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
197
sample_muxer/sample_muxer.vcproj
Normal file
197
sample_muxer/sample_muxer.vcproj
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="9.00"
|
||||||
|
Name="sample_muxer"
|
||||||
|
ProjectGUID="{B407561F-1F5E-4798-B9C2-81AB09CFBC16}"
|
||||||
|
RootNamespace="sample_muxer"
|
||||||
|
Keyword="Win32Proj"
|
||||||
|
TargetFrameworkVersion="196613"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"
|
||||||
|
/>
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="../"
|
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="4"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="..\Debug\mkvparser.lib ..\Debug\mkvmuxer.lib"
|
||||||
|
LinkIncremental="2"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="1"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="1"
|
||||||
|
WholeProgramOptimization="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="2"
|
||||||
|
EnableIntrinsicFunctions="true"
|
||||||
|
AdditionalIncludeDirectories="../"
|
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
EnableFunctionLevelLinking="true"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="4"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="..\Release\mkvparser.lib ..\Release\mkvmuxer.lib"
|
||||||
|
LinkIncremental="1"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="1"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\sample_muxer.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Header Files"
|
||||||
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
|
>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Resource Files"
|
||||||
|
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||||
|
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||||
|
>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
||||||
107
webmids.hpp
Normal file
107
webmids.hpp
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style license
|
||||||
|
// that can be found in the LICENSE file in the root of the source
|
||||||
|
// tree. An additional intellectual property rights grant can be found
|
||||||
|
// in the file PATENTS. All contributing project authors may
|
||||||
|
// be found in the AUTHORS file in the root of the source tree.
|
||||||
|
|
||||||
|
#ifndef WEBMIDS_HPP
|
||||||
|
#define WEBMIDS_HPP
|
||||||
|
|
||||||
|
namespace mkvmuxer {
|
||||||
|
|
||||||
|
enum MkvId {
|
||||||
|
kMkvEBML = 0x1A45DFA3,
|
||||||
|
kMkvEBMLVersion = 0x4286,
|
||||||
|
kMkvEBMLReadVersion = 0x42F7,
|
||||||
|
kMkvEBMLMaxIDLength = 0x42F2,
|
||||||
|
kMkvEBMLMaxSizeLength = 0x42F3,
|
||||||
|
kMkvDocType = 0x4282,
|
||||||
|
kMkvDocTypeVersion = 0x4287,
|
||||||
|
kMkvDocTypeReadVersion = 0x4285,
|
||||||
|
kMkvVoid = 0xEC,
|
||||||
|
kMkvSignatureSlot = 0x1B538667,
|
||||||
|
kMkvSignatureAlgo = 0x7E8A,
|
||||||
|
kMkvSignatureHash = 0x7E9A,
|
||||||
|
kMkvSignaturePublicKey = 0x7EA5,
|
||||||
|
kMkvSignature = 0x7EB5,
|
||||||
|
kMkvSignatureElements = 0x7E5B,
|
||||||
|
kMkvSignatureElementList = 0x7E7B,
|
||||||
|
kMkvSignedElement = 0x6532,
|
||||||
|
//segment
|
||||||
|
kMkvSegment = 0x18538067,
|
||||||
|
//Meta Seek Information
|
||||||
|
kMkvSeekHead = 0x114D9B74,
|
||||||
|
kMkvSeek = 0x4DBB,
|
||||||
|
kMkvSeekID = 0x53AB,
|
||||||
|
kMkvSeekPosition = 0x53AC,
|
||||||
|
//Segment Information
|
||||||
|
kMkvInfo = 0x1549A966,
|
||||||
|
kMkvTimecodeScale = 0x2AD7B1,
|
||||||
|
kMkvDuration = 0x4489,
|
||||||
|
kMkvDateUTC = 0x4461,
|
||||||
|
kMkvMuxingApp = 0x4D80,
|
||||||
|
kMkvWritingApp = 0x5741,
|
||||||
|
//Cluster
|
||||||
|
kMkvCluster = 0x1F43B675,
|
||||||
|
kMkvTimecode = 0xE7,
|
||||||
|
kMkvPrevSize = 0xAB,
|
||||||
|
kMkvBlockGroup = 0xA0,
|
||||||
|
kMkvBlock = 0xA1,
|
||||||
|
kMkvBlockDuration = 0x9B,
|
||||||
|
kMkvReferenceBlock = 0xFB,
|
||||||
|
kMkvLaceNumber = 0xCC,
|
||||||
|
kMkvSimpleBlock = 0xA3,
|
||||||
|
//Track
|
||||||
|
kMkvTracks = 0x1654AE6B,
|
||||||
|
kMkvTrackEntry = 0xAE,
|
||||||
|
kMkvTrackNumber = 0xD7,
|
||||||
|
kMkvTrackUID = 0x73C5,
|
||||||
|
kMkvTrackType = 0x83,
|
||||||
|
kMkvFlagEnabled = 0xB9,
|
||||||
|
kMkvFlagDefault = 0x88,
|
||||||
|
kMkvFlagForced = 0x55AA,
|
||||||
|
kMkvFlagLacing = 0x9C,
|
||||||
|
kMkvDefaultDuration = 0x23E383,
|
||||||
|
kMkvName = 0x536E,
|
||||||
|
kMkvLanguage = 0x22B59C,
|
||||||
|
kMkvCodecID = 0x86,
|
||||||
|
kMkvCodecPrivate = 0x63A2,
|
||||||
|
kMkvCodecName = 0x258688,
|
||||||
|
//video
|
||||||
|
kMkvVideo = 0xE0,
|
||||||
|
kMkvFlagInterlaced = 0x9A,
|
||||||
|
kMkvStereoMode = 0x53B8,
|
||||||
|
kMkvPixelWidth = 0xB0,
|
||||||
|
kMkvPixelHeight = 0xBA,
|
||||||
|
kMkvPixelCropBottom = 0x54AA,
|
||||||
|
kMkvPixelCropTop = 0x54BB,
|
||||||
|
kMkvPixelCropLeft = 0x54CC,
|
||||||
|
kMkvPixelCropRight = 0x54DD,
|
||||||
|
kMkvDisplayWidth = 0x54B0,
|
||||||
|
kMkvDisplayHeight = 0x54BA,
|
||||||
|
kMkvDisplayUnit = 0x54B2,
|
||||||
|
kMkvAspectRatioType = 0x54B3,
|
||||||
|
kMkvFrameRate = 0x2383E3,
|
||||||
|
//end video
|
||||||
|
//audio
|
||||||
|
kMkvAudio = 0xE1,
|
||||||
|
kMkvSamplingFrequency = 0xB5,
|
||||||
|
kMkvOutputSamplingFrequency = 0x78B5,
|
||||||
|
kMkvChannels = 0x9F,
|
||||||
|
kMkvBitDepth = 0x6264,
|
||||||
|
//end audio
|
||||||
|
//Cueing Data
|
||||||
|
kMkvCues = 0x1C53BB6B,
|
||||||
|
kMkvCuePoint = 0xBB,
|
||||||
|
kMkvCueTime = 0xB3,
|
||||||
|
kMkvCueTrackPositions = 0xB7,
|
||||||
|
kMkvCueTrack = 0xF7,
|
||||||
|
kMkvCueClusterPosition = 0xF1,
|
||||||
|
kMkvCueBlockNumber = 0x5378,
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace mkvmuxer
|
||||||
|
|
||||||
|
#endif // WEBMIDS_HPP
|
||||||
Reference in New Issue
Block a user