Commit 2d77a6f5 by Błażej Szczygieł

Add libsimplewebm and libwebm thirdparty libraries

parent c4b7c7d8
......@@ -95,6 +95,12 @@ Files extracted from upstream source:
- `scripts/pnglibconf.h.prebuilt` as `pnglibconf.h`
## libsimplewebm
- Upstream: https://github.com/zaps166/libsimplewebm
- License: MIT, BSD-3-Clause
## libvorbis
- Upstream: https://www.xiph.org/vorbis
......
MIT License
Copyright (c) 2016 Błażej Szczygieł
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
/*
MIT License
Copyright (c) 2016 Błażej Szczygieł
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "OpusVorbisDecoder.hpp"
#include <vorbis/codec.h>
#include <opus/opus.h>
#include <string.h>
struct VorbisDecoder
{
vorbis_info info;
vorbis_dsp_state dspState;
vorbis_block block;
ogg_packet op;
bool hasDSPState, hasBlock;
};
/**/
OpusVorbisDecoder::OpusVorbisDecoder(const WebMDemuxer &demuxer) :
m_vorbis(NULL), m_opus(NULL),
m_numSamples(0),
m_channels(demuxer.getChannels())
{
switch (demuxer.getAudioCodec())
{
case WebMDemuxer::AUDIO_VORBIS:
if (openVorbis(demuxer))
return;
break;
case WebMDemuxer::AUDIO_OPUS:
if (openOpus(demuxer))
return;
break;
default:
return;
}
close();
}
OpusVorbisDecoder::~OpusVorbisDecoder()
{
close();
}
bool OpusVorbisDecoder::isOpen() const
{
return (m_vorbis || m_opus);
}
bool OpusVorbisDecoder::getPCMS16(WebMFrame &frame, short *buffer, int &numOutSamples)
{
if (m_vorbis)
{
m_vorbis->op.packet = frame.buffer;
m_vorbis->op.bytes = frame.bufferSize;
if (vorbis_synthesis(&m_vorbis->block, &m_vorbis->op))
return false;
if (vorbis_synthesis_blockin(&m_vorbis->dspState, &m_vorbis->block))
return false;
const int maxSamples = getBufferSamples();
int samplesCount, count = 0;
float **pcm;
while ((samplesCount = vorbis_synthesis_pcmout(&m_vorbis->dspState, &pcm)))
{
const int toConvert = samplesCount <= maxSamples ? samplesCount : maxSamples;
for (int c = 0; c < m_channels; ++c)
{
float *samples = pcm[c];
for (int i = 0, j = c; i < toConvert; ++i, j += m_channels)
{
int sample = samples[i] * 32767.0f;
if (sample > 32767)
sample = 32767;
else if (sample < -32768)
sample = -32768;
buffer[count + j] = sample;
}
}
vorbis_synthesis_read(&m_vorbis->dspState, toConvert);
count += toConvert;
}
numOutSamples = count;
return true;
}
else if (m_opus)
{
const int samples = opus_decode(m_opus, frame.buffer, frame.bufferSize, buffer, m_numSamples, 0);
if (samples >= 0)
{
numOutSamples = samples;
return true;
}
}
return false;
}
bool OpusVorbisDecoder::openVorbis(const WebMDemuxer &demuxer)
{
size_t extradataSize = 0;
const unsigned char *extradata = demuxer.getAudioExtradata(extradataSize);
if (extradataSize < 3 || !extradata || extradata[0] != 2)
return false;
size_t headerSize[3] = {0};
size_t offset = 1;
/* Calculate three headers sizes */
for (int i = 0; i < 2; ++i)
{
for (;;)
{
if (offset >= extradataSize)
return false;
headerSize[i] += extradata[offset];
if (extradata[offset++] < 0xFF)
break;
}
}
headerSize[2] = extradataSize - (headerSize[0] + headerSize[1] + offset);
if (headerSize[0] + headerSize[1] + headerSize[2] + offset != extradataSize)
return false;
ogg_packet op[3];
memset(op, 0, sizeof op);
op[0].packet = (unsigned char *)extradata + offset;
op[0].bytes = headerSize[0];
op[0].b_o_s = 1;
op[1].packet = (unsigned char *)extradata + offset + headerSize[0];
op[1].bytes = headerSize[1];
op[2].packet = (unsigned char *)extradata + offset + headerSize[0] + headerSize[1];
op[2].bytes = headerSize[2];
m_vorbis = new VorbisDecoder;
m_vorbis->hasDSPState = m_vorbis->hasBlock = false;
vorbis_info_init(&m_vorbis->info);
/* Upload three Vorbis headers into libvorbis */
vorbis_comment vc;
vorbis_comment_init(&vc);
for (int i = 0; i < 3; ++i)
{
if (vorbis_synthesis_headerin(&m_vorbis->info, &vc, &op[i]))
{
vorbis_comment_clear(&vc);
return false;
}
}
vorbis_comment_clear(&vc);
if (vorbis_synthesis_init(&m_vorbis->dspState, &m_vorbis->info))
return false;
m_vorbis->hasDSPState = true;
if (m_vorbis->info.channels != m_channels || m_vorbis->info.rate != demuxer.getSampleRate())
return false;
if (vorbis_block_init(&m_vorbis->dspState, &m_vorbis->block))
return false;
m_vorbis->hasBlock = true;
memset(&m_vorbis->op, 0, sizeof m_vorbis->op);
m_numSamples = 4096 / m_channels;
return true;
}
bool OpusVorbisDecoder::openOpus(const WebMDemuxer &demuxer)
{
int opusErr = 0;
m_opus = opus_decoder_create(demuxer.getSampleRate(), m_channels, &opusErr);
if (!opusErr)
{
m_numSamples = demuxer.getSampleRate() * 0.06 + 0.5; //Maximum frame size (for 60 ms frame)
return true;
}
return false;
}
void OpusVorbisDecoder::close()
{
if (m_vorbis)
{
if (m_vorbis->hasBlock)
vorbis_block_clear(&m_vorbis->block);
if (m_vorbis->hasDSPState)
vorbis_dsp_clear(&m_vorbis->dspState);
vorbis_info_clear(&m_vorbis->info);
delete m_vorbis;
}
if (m_opus)
opus_decoder_destroy(m_opus);
}
/*
MIT License
Copyright (c) 2016 Błażej Szczygieł
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef OPUSVORBISDECODER_HPP
#define OPUSVORBISDECODER_HPP
#include "WebMDemuxer.hpp"
struct VorbisDecoder;
struct OpusDecoder;
class OpusVorbisDecoder
{
OpusVorbisDecoder(const OpusVorbisDecoder &);
void operator =(const OpusVorbisDecoder &);
public:
OpusVorbisDecoder(const WebMDemuxer &demuxer);
~OpusVorbisDecoder();
bool isOpen() const;
inline int getBufferSamples() const
{
return m_numSamples;
}
bool getPCMS16(WebMFrame &frame, short *buffer, int &numOutSamples);
private:
bool openVorbis(const WebMDemuxer &demuxer);
bool openOpus(const WebMDemuxer &demuxer);
void close();
VorbisDecoder *m_vorbis;
OpusDecoder *m_opus;
int m_numSamples;
int m_channels;
};
#endif // OPUSVORBISDECODER_HPP
/*
MIT License
Copyright (c) 2016 Błażej Szczygieł
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "VPXDecoder.hpp"
#include <vpx/vpx_decoder.h>
#include <vpx/vp8dx.h>
#include <stdlib.h>
#include <string.h>
VPXDecoder::VPXDecoder(const WebMDemuxer &demuxer, unsigned threads) :
m_ctx(NULL),
m_iter(NULL),
m_delay(0)
{
if (threads > 8)
threads = 8;
else if (threads < 1)
threads = 1;
const vpx_codec_dec_cfg_t codecCfg = {
threads,
0,
0
};
vpx_codec_iface_t *codecIface = NULL;
switch (demuxer.getVideoCodec())
{
case WebMDemuxer::VIDEO_VP8:
codecIface = vpx_codec_vp8_dx();
break;
case WebMDemuxer::VIDEO_VP9:
codecIface = vpx_codec_vp9_dx();
m_delay = threads - 1;
break;
default:
return;
}
m_ctx = new vpx_codec_ctx_t;
if (vpx_codec_dec_init(m_ctx, codecIface, &codecCfg, m_delay > 0 ? VPX_CODEC_USE_FRAME_THREADING : 0))
{
delete m_ctx;
m_ctx = NULL;
}
}
VPXDecoder::~VPXDecoder()
{
if (m_ctx)
{
vpx_codec_destroy(m_ctx);
delete m_ctx;
}
}
bool VPXDecoder::decode(const WebMFrame &frame)
{
m_iter = NULL;
return !vpx_codec_decode(m_ctx, frame.buffer, frame.bufferSize, NULL, 0);
}
VPXDecoder::IMAGE_ERROR VPXDecoder::getImage(Image &image)
{
IMAGE_ERROR err = NO_FRAME;
if (vpx_image_t *img = vpx_codec_get_frame(m_ctx, &m_iter))
{
if ((img->fmt & VPX_IMG_FMT_PLANAR) && !(img->fmt & (VPX_IMG_FMT_HAS_ALPHA | VPX_IMG_FMT_HIGHBITDEPTH)))
{
if (img->stride[0] && img->stride[1] && img->stride[2])
{
const int uPlane = !!(img->fmt & VPX_IMG_FMT_UV_FLIP) + 1;
const int vPlane = !(img->fmt & VPX_IMG_FMT_UV_FLIP) + 1;
image.w = img->d_w;
image.h = img->d_h;
image.chromaShiftW = img->x_chroma_shift;
image.chromaShiftH = img->y_chroma_shift;
image.planes[0] = img->planes[0];
image.planes[1] = img->planes[uPlane];
image.planes[2] = img->planes[vPlane];
image.linesize[0] = img->stride[0];
image.linesize[1] = img->stride[uPlane];
image.linesize[2] = img->stride[vPlane];
err = NO_ERROR;
}
}
else
{
err = UNSUPPORTED_FRAME;
}
}
return err;
}
/**/
#if 0
static inline int ceilRshift(int val, int shift)
{
return (val + (1 << shift) - 1) >> shift;
}
int VPXDecoder::Image::getWidth(int plane) const
{
if (!plane)
return w;
return ceilRshift(w, chromaShiftW);
}
int VPXDecoder::Image::getHeight(int plane) const
{
if (!plane)
return h;
return ceilRshift(h, chromaShiftH);
}
#endif
/*
MIT License
Copyright (c) 2016 Błażej Szczygieł
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef VPXDECODER_HPP
#define VPXDECODER_HPP
#include "WebMDemuxer.hpp"
struct vpx_codec_ctx;
class VPXDecoder
{
VPXDecoder(const VPXDecoder &);
void operator =(const VPXDecoder &);
public:
class Image
{
public:
#if 0
int getWidth(int plane) const;
int getHeight(int plane) const;
#endif
int w, h;
int chromaShiftW, chromaShiftH;
unsigned char *planes[3];
int linesize[3];
};
enum IMAGE_ERROR
{
UNSUPPORTED_FRAME = -1,
NO_ERROR,
NO_FRAME
};
VPXDecoder(const WebMDemuxer &demuxer, unsigned threads = 1);
~VPXDecoder();
inline bool isOpen() const
{
return (bool)m_ctx;
}
inline int getFramesDelay() const
{
return m_delay;
}
bool decode(const WebMFrame &frame);
IMAGE_ERROR getImage(Image &image); //The data is NOT copied! Only 3-plane, 8-bit images are supported.
private:
vpx_codec_ctx *m_ctx;
const void *m_iter;
int m_delay;
};
#endif // VPXDECODER_HPP
/*
MIT License
Copyright (c) 2016 Błażej Szczygieł
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "WebMDemuxer.hpp"
#include "mkvparser/mkvparser.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
WebMFrame::WebMFrame() :
bufferSize(0), bufferCapacity(0),
buffer(NULL),
time(0),
key(false)
{}
WebMFrame::~WebMFrame()
{
free(buffer);
}
/**/
WebMDemuxer::WebMDemuxer(mkvparser::IMkvReader *reader, int videoTrack, int audioTrack) :
m_reader(reader),
m_segment(NULL),
m_cluster(NULL), m_block(NULL), m_blockEntry(NULL),
m_blockFrameIndex(0),
m_videoTrack(NULL), m_vCodec(NO_VIDEO),
m_audioTrack(NULL), m_aCodec(NO_AUDIO),
m_isOpen(false),
m_eos(false)
{
long long pos = 0;
if (mkvparser::EBMLHeader().Parse(m_reader, pos))
return;
if (mkvparser::Segment::CreateInstance(m_reader, pos, m_segment))
return;
if (m_segment->Load() < 0)
return;
const mkvparser::Tracks *tracks = m_segment->GetTracks();
const unsigned long tracksCount = tracks->GetTracksCount();
int currVideoTrack = -1, currAudioTrack = -1;
for (unsigned long i = 0; i < tracksCount; ++i)
{
const mkvparser::Track *track = tracks->GetTrackByIndex(i);
if (const char *codecId = track->GetCodecId())
{
if ((!m_videoTrack || currVideoTrack != videoTrack) && track->GetType() == mkvparser::Track::kVideo)
{
if (!strcmp(codecId, "V_VP8"))
m_vCodec = VIDEO_VP8;
else if (!strcmp(codecId, "V_VP9"))
m_vCodec = VIDEO_VP9;
if (m_vCodec != NO_VIDEO)
m_videoTrack = static_cast<const mkvparser::VideoTrack *>(track);
++currVideoTrack;
}
if ((!m_audioTrack || currAudioTrack != audioTrack) && track->GetType() == mkvparser::Track::kAudio)
{
if (!strcmp(codecId, "A_VORBIS"))
m_aCodec = AUDIO_VORBIS;
else if (!strcmp(codecId, "A_OPUS"))
m_aCodec = AUDIO_OPUS;
if (m_aCodec != NO_AUDIO)
m_audioTrack = static_cast<const mkvparser::AudioTrack *>(track);
++currAudioTrack;
}
}
}
if (!m_videoTrack && !m_audioTrack)
return;
m_isOpen = true;
}
WebMDemuxer::~WebMDemuxer()
{
delete m_segment;
delete m_reader;
}
double WebMDemuxer::getLength() const
{
return m_segment->GetDuration() / 1e9;
}
WebMDemuxer::VIDEO_CODEC WebMDemuxer::getVideoCodec() const
{
return m_vCodec;
}
int WebMDemuxer::getWidth() const
{
return m_videoTrack->GetWidth();
}
int WebMDemuxer::getHeight() const
{
return m_videoTrack->GetHeight();
}
WebMDemuxer::AUDIO_CODEC WebMDemuxer::getAudioCodec() const
{
return m_aCodec;
}
const unsigned char *WebMDemuxer::getAudioExtradata(size_t &size) const
{
return m_audioTrack->GetCodecPrivate(size);
}
double WebMDemuxer::getSampleRate() const
{
return m_audioTrack->GetSamplingRate();
}
int WebMDemuxer::getChannels() const
{
return m_audioTrack->GetChannels();
}
int WebMDemuxer::getAudioDepth() const
{
return m_audioTrack->GetBitDepth();
}
bool WebMDemuxer::readFrame(WebMFrame *videoFrame, WebMFrame *audioFrame)
{
const long videoTrackNumber = (videoFrame && m_videoTrack) ? m_videoTrack->GetNumber() : 0;
const long audioTrackNumber = (audioFrame && m_audioTrack) ? m_audioTrack->GetNumber() : 0;
bool blockEntryEOS = false;
if (videoFrame)
videoFrame->bufferSize = 0;
if (audioFrame)
audioFrame->bufferSize = 0;
if (videoTrackNumber == 0 && audioTrackNumber == 0)
return false;
if (m_eos)
return false;
if (!m_cluster)
m_cluster = m_segment->GetFirst();
do
{
bool getNewBlock = false;
long status = 0;
if (!m_blockEntry && !blockEntryEOS)
{
status = m_cluster->GetFirst(m_blockEntry);
getNewBlock = true;
}
else if (blockEntryEOS || m_blockEntry->EOS())
{
m_cluster = m_segment->GetNext(m_cluster);
if (!m_cluster || m_cluster->EOS())
{
m_eos = true;
return false;
}
status = m_cluster->GetFirst(m_blockEntry);
blockEntryEOS = false;
getNewBlock = true;
}
else if (!m_block || m_blockFrameIndex == m_block->GetFrameCount() || notSupportedTrackNumber(videoTrackNumber, audioTrackNumber))
{
status = m_cluster->GetNext(m_blockEntry, m_blockEntry);
if (!m_blockEntry || m_blockEntry->EOS())
{
blockEntryEOS = true;
continue;
}
getNewBlock = true;
}
if (status || !m_blockEntry)
return false;
if (getNewBlock)
{
m_block = m_blockEntry->GetBlock();
m_blockFrameIndex = 0;
}
} while (blockEntryEOS || notSupportedTrackNumber(videoTrackNumber, audioTrackNumber));
WebMFrame *frame = NULL;
const long trackNumber = m_block->GetTrackNumber();
if (trackNumber == videoTrackNumber)
frame = videoFrame;
else if (trackNumber == audioTrackNumber)
frame = audioFrame;
else
{
//Should not be possible
assert(trackNumber == videoTrackNumber || trackNumber == audioTrackNumber);
return false;
}
const mkvparser::Block::Frame &blockFrame = m_block->GetFrame(m_blockFrameIndex++);
if (blockFrame.len > frame->bufferCapacity)
{
unsigned char *newBuff = (unsigned char *)realloc(frame->buffer, frame->bufferCapacity = blockFrame.len);
if (newBuff)
frame->buffer = newBuff;
else // Out of memory
return false;
}
frame->bufferSize = blockFrame.len;
frame->time = m_block->GetTime(m_cluster) / 1e9;
frame->key = m_block->IsKey();
return !blockFrame.Read(m_reader, frame->buffer);
}
inline bool WebMDemuxer::notSupportedTrackNumber(long videoTrackNumber, long audioTrackNumber) const
{
const long trackNumber = m_block->GetTrackNumber();
return (trackNumber != videoTrackNumber && trackNumber != audioTrackNumber);
}
/*
MIT License
Copyright (c) 2016 Błażej Szczygieł
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef WEBMDEMUXER_HPP
#define WEBMDEMUXER_HPP
#include <stddef.h>
namespace mkvparser {
class IMkvReader;
class Segment;
class Cluster;
class Block;
class BlockEntry;
class VideoTrack;
class AudioTrack;
}
class WebMFrame
{
WebMFrame(const WebMFrame &);
void operator =(const WebMFrame &);
public:
WebMFrame();
~WebMFrame();
inline bool isValid() const
{
return bufferSize > 0;
}
long bufferSize, bufferCapacity;
unsigned char *buffer;
double time;
bool key;
};
class WebMDemuxer
{
WebMDemuxer(const WebMDemuxer &);
void operator =(const WebMDemuxer &);
public:
enum VIDEO_CODEC
{
NO_VIDEO,
VIDEO_VP8,
VIDEO_VP9
};
enum AUDIO_CODEC
{
NO_AUDIO,
AUDIO_VORBIS,
AUDIO_OPUS
};
WebMDemuxer(mkvparser::IMkvReader *reader, int videoTrack = 0, int audioTrack = 0);
~WebMDemuxer();
inline bool isOpen() const
{
return m_isOpen;
}
inline bool isEOS() const
{
return m_eos;
}
double getLength() const;
VIDEO_CODEC getVideoCodec() const;
int getWidth() const;
int getHeight() const;
AUDIO_CODEC getAudioCodec() const;
const unsigned char *getAudioExtradata(size_t &size) const; // Needed for Vorbis
double getSampleRate() const;
int getChannels() const;
int getAudioDepth() const;
bool readFrame(WebMFrame *videoFrame, WebMFrame *audioFrame);
private:
inline bool notSupportedTrackNumber(long videoTrackNumber, long audioTrackNumber) const;
mkvparser::IMkvReader *m_reader;
mkvparser::Segment *m_segment;
const mkvparser::Cluster *m_cluster;
const mkvparser::Block *m_block;
const mkvparser::BlockEntry *m_blockEntry;
int m_blockFrameIndex;
const mkvparser::VideoTrack *m_videoTrack;
VIDEO_CODEC m_vCodec;
const mkvparser::AudioTrack *m_audioTrack;
AUDIO_CODEC m_aCodec;
bool m_isOpen;
bool m_eos;
};
#endif // WEBMDEMUXER_HPP
# Names should be added to this file like so:
# Name or Organization <email address>
Google Inc.
Copyright (c) 2010, Google Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Google nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Additional IP Rights Grant (Patents)
------------------------------------
"These implementations" means the copyrightable works that implement the WebM
codecs distributed by Google as part of the WebM Project.
Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge,
royalty-free, irrevocable (except as stated in this section) patent license to
make, have made, use, offer to sell, sell, import, transfer, and otherwise
run, modify and propagate the contents of these implementations of WebM, where
such license applies only to those patent claims, both currently owned by
Google and acquired in the future, licensable by Google that are necessarily
infringed by these implementations of WebM. This grant does not include claims
that would be infringed only as a consequence of further modification of these
implementations. If you or your agent or exclusive licensee institute or order
or agree to the institution of patent litigation or any other patent
enforcement activity against any entity (including a cross-claim or
counterclaim in a lawsuit) alleging that any of these implementations of WebM
or any code incorporated within any of these implementations of WebM
constitute direct or contributory patent infringement, or inducement of
patent infringement, then any patent rights granted to you under this License
for these implementations of WebM shall terminate as of the date such
litigation is filed.
URL: https://chromium.googlesource.com/webm/libwebm
Version: 32d5ac49414a8914ec1e1f285f3f927c6e8ec29d
License: BSD
License File: LICENSE.txt
Description:
libwebm is used to handle WebM container I/O.
Local Changes:
* Removed: "mkvmuxer", "hdr_util", "file_util", "mkv_reader".
* Make "~IMkvRerader()" public.
// Copyright (c) 2012 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 COMMON_WEBMIDS_H_
#define COMMON_WEBMIDS_H_
namespace libwebm {
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,
kMkvTitle = 0x7BA9,
kMkvMuxingApp = 0x4D80,
kMkvWritingApp = 0x5741,
// Cluster
kMkvCluster = 0x1F43B675,
kMkvTimecode = 0xE7,
kMkvPrevSize = 0xAB,
kMkvBlockGroup = 0xA0,
kMkvBlock = 0xA1,
kMkvBlockDuration = 0x9B,
kMkvReferenceBlock = 0xFB,
kMkvLaceNumber = 0xCC,
kMkvSimpleBlock = 0xA3,
kMkvBlockAdditions = 0x75A1,
kMkvBlockMore = 0xA6,
kMkvBlockAddID = 0xEE,
kMkvBlockAdditional = 0xA5,
kMkvDiscardPadding = 0x75A2,
// Track
kMkvTracks = 0x1654AE6B,
kMkvTrackEntry = 0xAE,
kMkvTrackNumber = 0xD7,
kMkvTrackUID = 0x73C5,
kMkvTrackType = 0x83,
kMkvFlagEnabled = 0xB9,
kMkvFlagDefault = 0x88,
kMkvFlagForced = 0x55AA,
kMkvFlagLacing = 0x9C,
kMkvDefaultDuration = 0x23E383,
kMkvMaxBlockAdditionID = 0x55EE,
kMkvName = 0x536E,
kMkvLanguage = 0x22B59C,
kMkvCodecID = 0x86,
kMkvCodecPrivate = 0x63A2,
kMkvCodecName = 0x258688,
kMkvCodecDelay = 0x56AA,
kMkvSeekPreRoll = 0x56BB,
// video
kMkvVideo = 0xE0,
kMkvFlagInterlaced = 0x9A,
kMkvStereoMode = 0x53B8,
kMkvAlphaMode = 0x53C0,
kMkvPixelWidth = 0xB0,
kMkvPixelHeight = 0xBA,
kMkvPixelCropBottom = 0x54AA,
kMkvPixelCropTop = 0x54BB,
kMkvPixelCropLeft = 0x54CC,
kMkvPixelCropRight = 0x54DD,
kMkvDisplayWidth = 0x54B0,
kMkvDisplayHeight = 0x54BA,
kMkvDisplayUnit = 0x54B2,
kMkvAspectRatioType = 0x54B3,
kMkvFrameRate = 0x2383E3,
// end video
// colour
kMkvColour = 0x55B0,
kMkvMatrixCoefficients = 0x55B1,
kMkvBitsPerChannel = 0x55B2,
kMkvChromaSubsamplingHorz = 0x55B3,
kMkvChromaSubsamplingVert = 0x55B4,
kMkvCbSubsamplingHorz = 0x55B5,
kMkvCbSubsamplingVert = 0x55B6,
kMkvChromaSitingHorz = 0x55B7,
kMkvChromaSitingVert = 0x55B8,
kMkvRange = 0x55B9,
kMkvTransferCharacteristics = 0x55BA,
kMkvPrimaries = 0x55BB,
kMkvMaxCLL = 0x55BC,
kMkvMaxFALL = 0x55BD,
// mastering metadata
kMkvMasteringMetadata = 0x55D0,
kMkvPrimaryRChromaticityX = 0x55D1,
kMkvPrimaryRChromaticityY = 0x55D2,
kMkvPrimaryGChromaticityX = 0x55D3,
kMkvPrimaryGChromaticityY = 0x55D4,
kMkvPrimaryBChromaticityX = 0x55D5,
kMkvPrimaryBChromaticityY = 0x55D6,
kMkvWhitePointChromaticityX = 0x55D7,
kMkvWhitePointChromaticityY = 0x55D8,
kMkvLuminanceMax = 0x55D9,
kMkvLuminanceMin = 0x55DA,
// end mastering metadata
// end colour
// audio
kMkvAudio = 0xE1,
kMkvSamplingFrequency = 0xB5,
kMkvOutputSamplingFrequency = 0x78B5,
kMkvChannels = 0x9F,
kMkvBitDepth = 0x6264,
// end audio
// ContentEncodings
kMkvContentEncodings = 0x6D80,
kMkvContentEncoding = 0x6240,
kMkvContentEncodingOrder = 0x5031,
kMkvContentEncodingScope = 0x5032,
kMkvContentEncodingType = 0x5033,
kMkvContentCompression = 0x5034,
kMkvContentCompAlgo = 0x4254,
kMkvContentCompSettings = 0x4255,
kMkvContentEncryption = 0x5035,
kMkvContentEncAlgo = 0x47E1,
kMkvContentEncKeyID = 0x47E2,
kMkvContentSignature = 0x47E3,
kMkvContentSigKeyID = 0x47E4,
kMkvContentSigAlgo = 0x47E5,
kMkvContentSigHashAlgo = 0x47E6,
kMkvContentEncAESSettings = 0x47E7,
kMkvAESSettingsCipherMode = 0x47E8,
kMkvAESSettingsCipherInitData = 0x47E9,
// end ContentEncodings
// Cueing Data
kMkvCues = 0x1C53BB6B,
kMkvCuePoint = 0xBB,
kMkvCueTime = 0xB3,
kMkvCueTrackPositions = 0xB7,
kMkvCueTrack = 0xF7,
kMkvCueClusterPosition = 0xF1,
kMkvCueBlockNumber = 0x5378,
// Chapters
kMkvChapters = 0x1043A770,
kMkvEditionEntry = 0x45B9,
kMkvChapterAtom = 0xB6,
kMkvChapterUID = 0x73C4,
kMkvChapterStringUID = 0x5654,
kMkvChapterTimeStart = 0x91,
kMkvChapterTimeEnd = 0x92,
kMkvChapterDisplay = 0x80,
kMkvChapString = 0x85,
kMkvChapLanguage = 0x437C,
kMkvChapCountry = 0x437E,
// Tags
kMkvTags = 0x1254C367,
kMkvTag = 0x7373,
kMkvSimpleTag = 0x67C8,
kMkvTagName = 0x45A3,
kMkvTagString = 0x4487
};
} // namespace libwebm
#endif // COMMON_WEBMIDS_H_
// Copyright (c) 2012 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_MKVMUXERTYPES_H_
#define MKVMUXER_MKVMUXERTYPES_H_
namespace mkvmuxer {
typedef unsigned char uint8;
typedef short int16;
typedef int int32;
typedef unsigned int uint32;
typedef long long int64;
typedef unsigned long long uint64;
} // namespace mkvmuxer
// 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&)
#endif // MKVMUXER_MKVMUXERTYPES_HPP_
This source diff could not be displayed because it is too large. You can view the blob instead.
// Copyright (c) 2012 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 MKVPARSER_MKVPARSER_H_
#define MKVPARSER_MKVPARSER_H_
#include <stddef.h>
namespace mkvparser {
const int E_PARSE_FAILED = -1;
const int E_FILE_FORMAT_INVALID = -2;
const int E_BUFFER_NOT_FULL = -3;
class IMkvReader {
public:
virtual int Read(long long pos, long len, unsigned char* buf) = 0;
virtual int Length(long long* total, long long* available) = 0;
virtual ~IMkvReader();
};
template <typename Type>
Type* SafeArrayAlloc(unsigned long long num_elements,
unsigned long long element_size);
long long GetUIntLength(IMkvReader*, long long, long&);
long long ReadUInt(IMkvReader*, long long, long&);
long long ReadID(IMkvReader* pReader, long long pos, long& len);
long long UnserializeUInt(IMkvReader*, long long pos, long long size);
long UnserializeFloat(IMkvReader*, long long pos, long long size, double&);
long UnserializeInt(IMkvReader*, long long pos, long long size,
long long& result);
long UnserializeString(IMkvReader*, long long pos, long long size, char*& str);
long ParseElementHeader(IMkvReader* pReader,
long long& pos, // consume id and size fields
long long stop, // if you know size of element's parent
long long& id, long long& size);
bool Match(IMkvReader*, long long&, unsigned long, long long&);
bool Match(IMkvReader*, long long&, unsigned long, unsigned char*&, size_t&);
void GetVersion(int& major, int& minor, int& build, int& revision);
struct EBMLHeader {
EBMLHeader();
~EBMLHeader();
long long m_version;
long long m_readVersion;
long long m_maxIdLength;
long long m_maxSizeLength;
char* m_docType;
long long m_docTypeVersion;
long long m_docTypeReadVersion;
long long Parse(IMkvReader*, long long&);
void Init();
};
class Segment;
class Track;
class Cluster;
class Block {
Block(const Block&);
Block& operator=(const Block&);
public:
const long long m_start;
const long long m_size;
Block(long long start, long long size, long long discard_padding);
~Block();
long Parse(const Cluster*);
long long GetTrackNumber() const;
long long GetTimeCode(const Cluster*) const; // absolute, but not scaled
long long GetTime(const Cluster*) const; // absolute, and scaled (ns)
bool IsKey() const;
void SetKey(bool);
bool IsInvisible() const;
enum Lacing { kLacingNone, kLacingXiph, kLacingFixed, kLacingEbml };
Lacing GetLacing() const;
int GetFrameCount() const; // to index frames: [0, count)
struct Frame {
long long pos; // absolute offset
long len;
long Read(IMkvReader*, unsigned char*) const;
};
const Frame& GetFrame(int frame_index) const;
long long GetDiscardPadding() const;
private:
long long m_track; // Track::Number()
short m_timecode; // relative to cluster
unsigned char m_flags;
Frame* m_frames;
int m_frame_count;
protected:
const long long m_discard_padding;
};
class BlockEntry {
BlockEntry(const BlockEntry&);
BlockEntry& operator=(const BlockEntry&);
protected:
BlockEntry(Cluster*, long index);
public:
virtual ~BlockEntry();
bool EOS() const { return (GetKind() == kBlockEOS); }
const Cluster* GetCluster() const;
long GetIndex() const;
virtual const Block* GetBlock() const = 0;
enum Kind { kBlockEOS, kBlockSimple, kBlockGroup };
virtual Kind GetKind() const = 0;
protected:
Cluster* const m_pCluster;
const long m_index;
};
class SimpleBlock : public BlockEntry {
SimpleBlock(const SimpleBlock&);
SimpleBlock& operator=(const SimpleBlock&);
public:
SimpleBlock(Cluster*, long index, long long start, long long size);
long Parse();
Kind GetKind() const;
const Block* GetBlock() const;
protected:
Block m_block;
};
class BlockGroup : public BlockEntry {
BlockGroup(const BlockGroup&);
BlockGroup& operator=(const BlockGroup&);
public:
BlockGroup(Cluster*, long index,
long long block_start, // absolute pos of block's payload
long long block_size, // size of block's payload
long long prev, long long next, long long duration,
long long discard_padding);
long Parse();
Kind GetKind() const;
const Block* GetBlock() const;
long long GetPrevTimeCode() const; // relative to block's time
long long GetNextTimeCode() const; // as above
long long GetDurationTimeCode() const;
private:
Block m_block;
const long long m_prev;
const long long m_next;
const long long m_duration;
};
///////////////////////////////////////////////////////////////
// ContentEncoding element
// Elements used to describe if the track data has been encrypted or
// compressed with zlib or header stripping.
class ContentEncoding {
public:
enum { kCTR = 1 };
ContentEncoding();
~ContentEncoding();
// ContentCompression element names
struct ContentCompression {
ContentCompression();
~ContentCompression();
unsigned long long algo;
unsigned char* settings;
long long settings_len;
};
// ContentEncAESSettings element names
struct ContentEncAESSettings {
ContentEncAESSettings() : cipher_mode(kCTR) {}
~ContentEncAESSettings() {}
unsigned long long cipher_mode;
};
// ContentEncryption element names
struct ContentEncryption {
ContentEncryption();
~ContentEncryption();
unsigned long long algo;
unsigned char* key_id;
long long key_id_len;
unsigned char* signature;
long long signature_len;
unsigned char* sig_key_id;
long long sig_key_id_len;
unsigned long long sig_algo;
unsigned long long sig_hash_algo;
ContentEncAESSettings aes_settings;
};
// Returns ContentCompression represented by |idx|. Returns NULL if |idx|
// is out of bounds.
const ContentCompression* GetCompressionByIndex(unsigned long idx) const;
// Returns number of ContentCompression elements in this ContentEncoding
// element.
unsigned long GetCompressionCount() const;
// Parses the ContentCompression element from |pReader|. |start| is the
// starting offset of the ContentCompression payload. |size| is the size in
// bytes of the ContentCompression payload. |compression| is where the parsed
// values will be stored.
long ParseCompressionEntry(long long start, long long size,
IMkvReader* pReader,
ContentCompression* compression);
// Returns ContentEncryption represented by |idx|. Returns NULL if |idx|
// is out of bounds.
const ContentEncryption* GetEncryptionByIndex(unsigned long idx) const;
// Returns number of ContentEncryption elements in this ContentEncoding
// element.
unsigned long GetEncryptionCount() const;
// Parses the ContentEncAESSettings element from |pReader|. |start| is the
// starting offset of the ContentEncAESSettings payload. |size| is the
// size in bytes of the ContentEncAESSettings payload. |encryption| is
// where the parsed values will be stored.
long ParseContentEncAESSettingsEntry(long long start, long long size,
IMkvReader* pReader,
ContentEncAESSettings* aes);
// Parses the ContentEncoding element from |pReader|. |start| is the
// starting offset of the ContentEncoding payload. |size| is the size in
// bytes of the ContentEncoding payload. Returns true on success.
long ParseContentEncodingEntry(long long start, long long size,
IMkvReader* pReader);
// Parses the ContentEncryption element from |pReader|. |start| is the
// starting offset of the ContentEncryption payload. |size| is the size in
// bytes of the ContentEncryption payload. |encryption| is where the parsed
// values will be stored.
long ParseEncryptionEntry(long long start, long long size,
IMkvReader* pReader, ContentEncryption* encryption);
unsigned long long encoding_order() const { return encoding_order_; }
unsigned long long encoding_scope() const { return encoding_scope_; }
unsigned long long encoding_type() const { return encoding_type_; }
private:
// Member variables for list of ContentCompression elements.
ContentCompression** compression_entries_;
ContentCompression** compression_entries_end_;
// Member variables for list of ContentEncryption elements.
ContentEncryption** encryption_entries_;
ContentEncryption** encryption_entries_end_;
// ContentEncoding element names
unsigned long long encoding_order_;
unsigned long long encoding_scope_;
unsigned long long encoding_type_;
// LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncoding);
ContentEncoding(const ContentEncoding&);
ContentEncoding& operator=(const ContentEncoding&);
};
class Track {
Track(const Track&);
Track& operator=(const Track&);
public:
class Info;
static long Create(Segment*, const Info&, long long element_start,
long long element_size, Track*&);
enum Type { kVideo = 1, kAudio = 2, kSubtitle = 0x11, kMetadata = 0x21 };
Segment* const m_pSegment;
const long long m_element_start;
const long long m_element_size;
virtual ~Track();
long GetType() const;
long GetNumber() const;
unsigned long long GetUid() const;
const char* GetNameAsUTF8() const;
const char* GetLanguage() const;
const char* GetCodecNameAsUTF8() const;
const char* GetCodecId() const;
const unsigned char* GetCodecPrivate(size_t&) const;
bool GetLacing() const;
unsigned long long GetDefaultDuration() const;
unsigned long long GetCodecDelay() const;
unsigned long long GetSeekPreRoll() const;
const BlockEntry* GetEOS() const;
struct Settings {
long long start;
long long size;
};
class Info {
public:
Info();
~Info();
int Copy(Info&) const;
void Clear();
long type;
long number;
unsigned long long uid;
unsigned long long defaultDuration;
unsigned long long codecDelay;
unsigned long long seekPreRoll;
char* nameAsUTF8;
char* language;
char* codecId;
char* codecNameAsUTF8;
unsigned char* codecPrivate;
size_t codecPrivateSize;
bool lacing;
Settings settings;
private:
Info(const Info&);
Info& operator=(const Info&);
int CopyStr(char* Info::*str, Info&) const;
};
long GetFirst(const BlockEntry*&) const;
long GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const;
virtual bool VetEntry(const BlockEntry*) const;
virtual long Seek(long long time_ns, const BlockEntry*&) const;
const ContentEncoding* GetContentEncodingByIndex(unsigned long idx) const;
unsigned long GetContentEncodingCount() const;
long ParseContentEncodingsEntry(long long start, long long size);
protected:
Track(Segment*, long long element_start, long long element_size);
Info m_info;
class EOSBlock : public BlockEntry {
public:
EOSBlock();
Kind GetKind() const;
const Block* GetBlock() const;
};
EOSBlock m_eos;
private:
ContentEncoding** content_encoding_entries_;
ContentEncoding** content_encoding_entries_end_;
};
struct PrimaryChromaticity {
PrimaryChromaticity() : x(0), y(0) {}
~PrimaryChromaticity() {}
static bool Parse(IMkvReader* reader, long long read_pos,
long long value_size, bool is_x,
PrimaryChromaticity** chromaticity);
float x;
float y;
};
struct MasteringMetadata {
static const float kValueNotPresent;
MasteringMetadata()
: r(NULL),
g(NULL),
b(NULL),
white_point(NULL),
luminance_max(kValueNotPresent),
luminance_min(kValueNotPresent) {}
~MasteringMetadata() {
delete r;
delete g;
delete b;
delete white_point;
}
static bool Parse(IMkvReader* reader, long long element_start,
long long element_size,
MasteringMetadata** mastering_metadata);
PrimaryChromaticity* r;
PrimaryChromaticity* g;
PrimaryChromaticity* b;
PrimaryChromaticity* white_point;
float luminance_max;
float luminance_min;
};
struct Colour {
static const long long kValueNotPresent;
// Unless otherwise noted all values assigned upon construction are the
// equivalent of unspecified/default.
Colour()
: matrix_coefficients(kValueNotPresent),
bits_per_channel(kValueNotPresent),
chroma_subsampling_horz(kValueNotPresent),
chroma_subsampling_vert(kValueNotPresent),
cb_subsampling_horz(kValueNotPresent),
cb_subsampling_vert(kValueNotPresent),
chroma_siting_horz(kValueNotPresent),
chroma_siting_vert(kValueNotPresent),
range(kValueNotPresent),
transfer_characteristics(kValueNotPresent),
primaries(kValueNotPresent),
max_cll(kValueNotPresent),
max_fall(kValueNotPresent),
mastering_metadata(NULL) {}
~Colour() {
delete mastering_metadata;
mastering_metadata = NULL;
}
static bool Parse(IMkvReader* reader, long long element_start,
long long element_size, Colour** colour);
long long matrix_coefficients;
long long bits_per_channel;
long long chroma_subsampling_horz;
long long chroma_subsampling_vert;
long long cb_subsampling_horz;
long long cb_subsampling_vert;
long long chroma_siting_horz;
long long chroma_siting_vert;
long long range;
long long transfer_characteristics;
long long primaries;
long long max_cll;
long long max_fall;
MasteringMetadata* mastering_metadata;
};
class VideoTrack : public Track {
VideoTrack(const VideoTrack&);
VideoTrack& operator=(const VideoTrack&);
VideoTrack(Segment*, long long element_start, long long element_size);
public:
virtual ~VideoTrack();
static long Parse(Segment*, const Info&, long long element_start,
long long element_size, VideoTrack*&);
long long GetWidth() const;
long long GetHeight() const;
long long GetDisplayWidth() const;
long long GetDisplayHeight() const;
long long GetDisplayUnit() const;
long long GetStereoMode() const;
double GetFrameRate() const;
bool VetEntry(const BlockEntry*) const;
long Seek(long long time_ns, const BlockEntry*&) const;
Colour* GetColour() const;
private:
long long m_width;
long long m_height;
long long m_display_width;
long long m_display_height;
long long m_display_unit;
long long m_stereo_mode;
double m_rate;
Colour* m_colour;
};
class AudioTrack : public Track {
AudioTrack(const AudioTrack&);
AudioTrack& operator=(const AudioTrack&);
AudioTrack(Segment*, long long element_start, long long element_size);
public:
static long Parse(Segment*, const Info&, long long element_start,
long long element_size, AudioTrack*&);
double GetSamplingRate() const;
long long GetChannels() const;
long long GetBitDepth() const;
private:
double m_rate;
long long m_channels;
long long m_bitDepth;
};
class Tracks {
Tracks(const Tracks&);
Tracks& operator=(const Tracks&);
public:
Segment* const m_pSegment;
const long long m_start;
const long long m_size;
const long long m_element_start;
const long long m_element_size;
Tracks(Segment*, long long start, long long size, long long element_start,
long long element_size);
~Tracks();
long Parse();
unsigned long GetTracksCount() const;
const Track* GetTrackByNumber(long tn) const;
const Track* GetTrackByIndex(unsigned long idx) const;
private:
Track** m_trackEntries;
Track** m_trackEntriesEnd;
long ParseTrackEntry(long long payload_start, long long payload_size,
long long element_start, long long element_size,
Track*&) const;
};
class Chapters {
Chapters(const Chapters&);
Chapters& operator=(const Chapters&);
public:
Segment* const m_pSegment;
const long long m_start;
const long long m_size;
const long long m_element_start;
const long long m_element_size;
Chapters(Segment*, long long payload_start, long long payload_size,
long long element_start, long long element_size);
~Chapters();
long Parse();
class Atom;
class Edition;
class Display {
friend class Atom;
Display();
Display(const Display&);
~Display();
Display& operator=(const Display&);
public:
const char* GetString() const;
const char* GetLanguage() const;
const char* GetCountry() const;
private:
void Init();
void ShallowCopy(Display&) const;
void Clear();
long Parse(IMkvReader*, long long pos, long long size);
char* m_string;
char* m_language;
char* m_country;
};
class Atom {
friend class Edition;
Atom();
Atom(const Atom&);
~Atom();
Atom& operator=(const Atom&);
public:
unsigned long long GetUID() const;
const char* GetStringUID() const;
long long GetStartTimecode() const;
long long GetStopTimecode() const;
long long GetStartTime(const Chapters*) const;
long long GetStopTime(const Chapters*) const;
int GetDisplayCount() const;
const Display* GetDisplay(int index) const;
private:
void Init();
void ShallowCopy(Atom&) const;
void Clear();
long Parse(IMkvReader*, long long pos, long long size);
static long long GetTime(const Chapters*, long long timecode);
long ParseDisplay(IMkvReader*, long long pos, long long size);
bool ExpandDisplaysArray();
char* m_string_uid;
unsigned long long m_uid;
long long m_start_timecode;
long long m_stop_timecode;
Display* m_displays;
int m_displays_size;
int m_displays_count;
};
class Edition {
friend class Chapters;
Edition();
Edition(const Edition&);
~Edition();
Edition& operator=(const Edition&);
public:
int GetAtomCount() const;
const Atom* GetAtom(int index) const;
private:
void Init();
void ShallowCopy(Edition&) const;
void Clear();
long Parse(IMkvReader*, long long pos, long long size);
long ParseAtom(IMkvReader*, long long pos, long long size);
bool ExpandAtomsArray();
Atom* m_atoms;
int m_atoms_size;
int m_atoms_count;
};
int GetEditionCount() const;
const Edition* GetEdition(int index) const;
private:
long ParseEdition(long long pos, long long size);
bool ExpandEditionsArray();
Edition* m_editions;
int m_editions_size;
int m_editions_count;
};
class Tags {
Tags(const Tags&);
Tags& operator=(const Tags&);
public:
Segment* const m_pSegment;
const long long m_start;
const long long m_size;
const long long m_element_start;
const long long m_element_size;
Tags(Segment*, long long payload_start, long long payload_size,
long long element_start, long long element_size);
~Tags();
long Parse();
class Tag;
class SimpleTag;
class SimpleTag {
friend class Tag;
SimpleTag();
SimpleTag(const SimpleTag&);
~SimpleTag();
SimpleTag& operator=(const SimpleTag&);
public:
const char* GetTagName() const;
const char* GetTagString() const;
private:
void Init();
void ShallowCopy(SimpleTag&) const;
void Clear();
long Parse(IMkvReader*, long long pos, long long size);
char* m_tag_name;
char* m_tag_string;
};
class Tag {
friend class Tags;
Tag();
Tag(const Tag&);
~Tag();
Tag& operator=(const Tag&);
public:
int GetSimpleTagCount() const;
const SimpleTag* GetSimpleTag(int index) const;
private:
void Init();
void ShallowCopy(Tag&) const;
void Clear();
long Parse(IMkvReader*, long long pos, long long size);
long ParseSimpleTag(IMkvReader*, long long pos, long long size);
bool ExpandSimpleTagsArray();
SimpleTag* m_simple_tags;
int m_simple_tags_size;
int m_simple_tags_count;
};
int GetTagCount() const;
const Tag* GetTag(int index) const;
private:
long ParseTag(long long pos, long long size);
bool ExpandTagsArray();
Tag* m_tags;
int m_tags_size;
int m_tags_count;
};
class SegmentInfo {
SegmentInfo(const SegmentInfo&);
SegmentInfo& operator=(const SegmentInfo&);
public:
Segment* const m_pSegment;
const long long m_start;
const long long m_size;
const long long m_element_start;
const long long m_element_size;
SegmentInfo(Segment*, long long start, long long size,
long long element_start, long long element_size);
~SegmentInfo();
long Parse();
long long GetTimeCodeScale() const;
long long GetDuration() const; // scaled
const char* GetMuxingAppAsUTF8() const;
const char* GetWritingAppAsUTF8() const;
const char* GetTitleAsUTF8() const;
private:
long long m_timecodeScale;
double m_duration;
char* m_pMuxingAppAsUTF8;
char* m_pWritingAppAsUTF8;
char* m_pTitleAsUTF8;
};
class SeekHead {
SeekHead(const SeekHead&);
SeekHead& operator=(const SeekHead&);
public:
Segment* const m_pSegment;
const long long m_start;
const long long m_size;
const long long m_element_start;
const long long m_element_size;
SeekHead(Segment*, long long start, long long size, long long element_start,
long long element_size);
~SeekHead();
long Parse();
struct Entry {
// the SeekHead entry payload
long long id;
long long pos;
// absolute pos of SeekEntry ID
long long element_start;
// SeekEntry ID size + size size + payload
long long element_size;
};
int GetCount() const;
const Entry* GetEntry(int idx) const;
struct VoidElement {
// absolute pos of Void ID
long long element_start;
// ID size + size size + payload size
long long element_size;
};
int GetVoidElementCount() const;
const VoidElement* GetVoidElement(int idx) const;
private:
Entry* m_entries;
int m_entry_count;
VoidElement* m_void_elements;
int m_void_element_count;
static bool ParseEntry(IMkvReader*,
long long pos, // payload
long long size, Entry*);
};
class Cues;
class CuePoint {
friend class Cues;
CuePoint(long, long long);
~CuePoint();
CuePoint(const CuePoint&);
CuePoint& operator=(const CuePoint&);
public:
long long m_element_start;
long long m_element_size;
bool Load(IMkvReader*);
long long GetTimeCode() const; // absolute but unscaled
long long GetTime(const Segment*) const; // absolute and scaled (ns units)
struct TrackPosition {
long long m_track;
long long m_pos; // of cluster
long long m_block;
// codec_state //defaults to 0
// reference = clusters containing req'd referenced blocks
// reftime = timecode of the referenced block
bool Parse(IMkvReader*, long long, long long);
};
const TrackPosition* Find(const Track*) const;
private:
const long m_index;
long long m_timecode;
TrackPosition* m_track_positions;
size_t m_track_positions_count;
};
class Cues {
friend class Segment;
Cues(Segment*, long long start, long long size, long long element_start,
long long element_size);
~Cues();
Cues(const Cues&);
Cues& operator=(const Cues&);
public:
Segment* const m_pSegment;
const long long m_start;
const long long m_size;
const long long m_element_start;
const long long m_element_size;
bool Find( // lower bound of time_ns
long long time_ns, const Track*, const CuePoint*&,
const CuePoint::TrackPosition*&) const;
const CuePoint* GetFirst() const;
const CuePoint* GetLast() const;
const CuePoint* GetNext(const CuePoint*) const;
const BlockEntry* GetBlock(const CuePoint*,
const CuePoint::TrackPosition*) const;
bool LoadCuePoint() const;
long GetCount() const; // loaded only
// long GetTotal() const; //loaded + preloaded
bool DoneParsing() const;
private:
bool Init() const;
bool PreloadCuePoint(long&, long long) const;
mutable CuePoint** m_cue_points;
mutable long m_count;
mutable long m_preload_count;
mutable long long m_pos;
};
class Cluster {
friend class Segment;
Cluster(const Cluster&);
Cluster& operator=(const Cluster&);
public:
Segment* const m_pSegment;
public:
static Cluster* Create(Segment*,
long index, // index in segment
long long off); // offset relative to segment
// long long element_size);
Cluster(); // EndOfStream
~Cluster();
bool EOS() const;
long long GetTimeCode() const; // absolute, but not scaled
long long GetTime() const; // absolute, and scaled (nanosecond units)
long long GetFirstTime() const; // time (ns) of first (earliest) block
long long GetLastTime() const; // time (ns) of last (latest) block
long GetFirst(const BlockEntry*&) const;
long GetLast(const BlockEntry*&) const;
long GetNext(const BlockEntry* curr, const BlockEntry*& next) const;
const BlockEntry* GetEntry(const Track*, long long ns = -1) const;
const BlockEntry* GetEntry(const CuePoint&,
const CuePoint::TrackPosition&) const;
// const BlockEntry* GetMaxKey(const VideoTrack*) const;
// static bool HasBlockEntries(const Segment*, long long);
static long HasBlockEntries(const Segment*, long long idoff, long long& pos,
long& size);
long GetEntryCount() const;
long Load(long long& pos, long& size) const;
long Parse(long long& pos, long& size) const;
long GetEntry(long index, const mkvparser::BlockEntry*&) const;
protected:
Cluster(Segment*, long index, long long element_start);
// long long element_size);
public:
const long long m_element_start;
long long GetPosition() const; // offset relative to segment
long GetIndex() const;
long long GetElementSize() const;
// long long GetPayloadSize() const;
// long long Unparsed() const;
private:
long m_index;
mutable long long m_pos;
// mutable long long m_size;
mutable long long m_element_size;
mutable long long m_timecode;
mutable BlockEntry** m_entries;
mutable long m_entries_size;
mutable long m_entries_count;
long ParseSimpleBlock(long long, long long&, long&);
long ParseBlockGroup(long long, long long&, long&);
long CreateBlock(long long id, long long pos, long long size,
long long discard_padding);
long CreateBlockGroup(long long start_offset, long long size,
long long discard_padding);
long CreateSimpleBlock(long long, long long);
};
class Segment {
friend class Cues;
friend class Track;
friend class VideoTrack;
Segment(const Segment&);
Segment& operator=(const Segment&);
private:
Segment(IMkvReader*, long long elem_start,
// long long elem_size,
long long pos, long long size);
public:
IMkvReader* const m_pReader;
const long long m_element_start;
// const long long m_element_size;
const long long m_start; // posn of segment payload
const long long m_size; // size of segment payload
Cluster m_eos; // TODO: make private?
static long long CreateInstance(IMkvReader*, long long, Segment*&);
~Segment();
long Load(); // loads headers and all clusters
// for incremental loading
// long long Unparsed() const;
bool DoneParsing() const;
long long ParseHeaders(); // stops when first cluster is found
// long FindNextCluster(long long& pos, long& size) const;
long LoadCluster(long long& pos, long& size); // load one cluster
long LoadCluster();
long ParseNext(const Cluster* pCurr, const Cluster*& pNext, long long& pos,
long& size);
const SeekHead* GetSeekHead() const;
const Tracks* GetTracks() const;
const SegmentInfo* GetInfo() const;
const Cues* GetCues() const;
const Chapters* GetChapters() const;
const Tags* GetTags() const;
long long GetDuration() const;
unsigned long GetCount() const;
const Cluster* GetFirst() const;
const Cluster* GetLast() const;
const Cluster* GetNext(const Cluster*);
const Cluster* FindCluster(long long time_nanoseconds) const;
// const BlockEntry* Seek(long long time_nanoseconds, const Track*) const;
const Cluster* FindOrPreloadCluster(long long pos);
long ParseCues(long long cues_off, // offset relative to start of segment
long long& parse_pos, long& parse_len);
private:
long long m_pos; // absolute file posn; what has been consumed so far
Cluster* m_pUnknownSize;
SeekHead* m_pSeekHead;
SegmentInfo* m_pInfo;
Tracks* m_pTracks;
Cues* m_pCues;
Chapters* m_pChapters;
Tags* m_pTags;
Cluster** m_clusters;
long m_clusterCount; // number of entries for which m_index >= 0
long m_clusterPreloadCount; // number of entries for which m_index < 0
long m_clusterSize; // array size
long DoLoadCluster(long long&, long&);
long DoLoadClusterUnknownSize(long long&, long&);
long DoParseNext(const Cluster*&, long long&, long&);
bool AppendCluster(Cluster*);
bool PreloadCluster(Cluster*, ptrdiff_t);
// void ParseSeekHead(long long pos, long long size);
// void ParseSeekEntry(long long pos, long long size);
// void ParseCues(long long);
const BlockEntry* GetBlock(const CuePoint&, const CuePoint::TrackPosition&);
};
} // namespace mkvparser
inline long mkvparser::Segment::LoadCluster() {
long long pos;
long size;
return LoadCluster(pos, size);
}
#endif // MKVPARSER_MKVPARSER_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment