blob: ad4806ec9eb83de3c1294012bd292a5eb4f5c6b0 [file] [log] [blame]
// Copyright (c) 2010 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 <strmif.h>
#include "webmconstants.hpp"
#include "webmmuxcontext.hpp"
#include <cstdlib>
#include <cassert>
#include <algorithm>
namespace WebmMuxLib
{
StreamAudio::AudioFrame::AudioFrame()
{
}
StreamAudio::StreamAudio(
Context& ctx,
const BYTE* pb,
ULONG cb) :
Stream(ctx),
m_pFormat(malloc(cb)),
m_cFormat(cb)
{
assert(m_pFormat);
memcpy(m_pFormat, pb, cb);
}
StreamAudio::~StreamAudio()
{
free(m_pFormat);
}
bool StreamAudio::Wait() const
{
return m_context.WaitAudio();
}
const void* StreamAudio::GetFormat(ULONG& cb) const
{
cb = m_cFormat;
return m_pFormat;
}
void StreamAudio::WriteTrackType()
{
WebmUtil::EbmlScratchBuf& buf = m_context.m_buf;
buf.WriteID1(WebmUtil::kEbmlTrackTypeID);
buf.Write1UInt(1);
buf.Serialize1UInt(WebmUtil::kEbmlTrackTypeAudio);
}
void StreamAudio::WriteTrackSettings()
{
WebmUtil::EbmlScratchBuf& buf = m_context.m_buf;
// we need the starting length of |buf| to properly calculate
// |num_bytes_to_ignore|
const uint64 buf_start_len = buf.GetBufferLength();
buf.WriteID1(WebmUtil::kEbmlAudioSettingsID);
// store audio settings offset for patching later
const uint64 audio_len_offset = buf.GetBufferLength();
// We must exclude |num_bytes_to_ignore| from the size we obtain from
// |buf|. The value from |buf| includes the bytes storing all preceding
// data in the track entry -- using it as-is would result in an invalid
// tracks element.
const uint64 num_bytes_to_ignore = buf_start_len + 1 + sizeof(uint16);
// reserve 2 bytes for size of settings
buf.Serialize2UInt(0);
const uint32 samples_per_sec_ = GetSamplesPerSec();
assert(samples_per_sec_ > 0);
const float samples_per_sec = static_cast<float>(samples_per_sec_);
buf.WriteID1(WebmUtil::kEbmlSamplingFrequencyID);
buf.Write1UInt(4);
buf.Serialize4Float(samples_per_sec);
const uint8 channels = GetChannels();
assert(channels > 0);
buf.WriteID1(WebmUtil::kEbmlChannelsID);
buf.Write1UInt(1);
buf.Serialize1UInt(channels);
const uint64 audio_len = buf.GetBufferLength() - num_bytes_to_ignore;
buf.RewriteUInt(audio_len_offset, audio_len, sizeof(uint16));
}
#if 0
void StreamAudio::AudioFrame::Write(
const Stream& s,
ULONG cluster_timecode) const
{
EbmlIO::File& file = s.m_context.m_file;
//block = 1 byte ID + 4 byte size + f->size
//block duration = 1 byte ID + 1 byte size + 1 byte value
//reference block = 1 byte ID + 2 byte size + 2(?) byte signed value
const ULONG block_size = 1 + 2 + 1 + GetSize(); //tn, tc, flg, f
const ULONG block_group_size = 1 + 4 + block_size; //block id, size, payload
file.WriteID1(0xA0); //block group ID
file.Write4UInt(block_group_size); //size of payload for this block group
#ifdef _DEBUG
const __int64 pos = file.GetPosition();
#endif
//begin block
file.WriteID1(0xA1); //Block ID
file.Write4UInt(block_size);
const int tn_ = s.GetTrackNumber();
assert(tn_ > 0);
assert(tn_ <= 127);
const BYTE tn = static_cast<BYTE>(tn_);
file.Write1UInt(tn); //track number
const ULONG ft = GetTimecode();
{
const LONG tc_ = LONG(ft) - LONG(cluster_timecode);
assert(tc_ >= SHRT_MIN);
assert(tc_ <= SHRT_MAX);
const SHORT tc = static_cast<SHORT>(tc_);
file.Serialize2SInt(tc); //relative timecode
}
const BYTE flags = 0;
file.Write(&flags, 1); //written as binary, not uint
file.Write(GetData(), GetSize()); //frame
//end block
#ifdef _DEBUG
const __int64 newpos = file.GetPosition();
assert((newpos - pos) == block_group_size);
#endif
}
#endif
bool StreamAudio::AudioFrame::IsKey() const
{
return true;
}
StreamAudio::frames_t& StreamAudio::GetFrames()
{
return m_frames;
}
void StreamAudio::Flush()
{
m_context.FlushAudio(this);
}
} //end namespace WebmMuxLib