// MovieWriter.cpp: implementation of basic file structure classes.
//
//
// Geraint Davies, May 2004
//
// Copyright (c) GDCL 2004-6. All Rights Reserved.
// You are free to re-use this as the basis for your own filter development,
// provided you retain this copyright notice in the source.
// http://www.gdcl.co.uk
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "MovieWriter.h"
#include "TypeHandler.h"
Atom::Atom(AtomWriter* pContainer, LONGLONG llOffset, DWORD type)
: m_pContainer(pContainer),
m_cBytes(0),
m_llOffset(llOffset),
m_bClosed(false)
{
// write the initial length and type dwords
BYTE b[8];
WriteLong(8, b);
WriteLong(type, b+4);
Append(b, 8);
}
HRESULT
Atom::Close()
{
m_bClosed = true;
// we only support 32-bit lengths for atoms
// (otherwise you would have to either decide in the constructor
// or shift the whole atom down).
if (m_cBytes > 0xffffffff)
{
return E_INVALIDARG;
}
BYTE b[4];
WriteLong(long(m_cBytes), b);
return Replace(0, b, 4);
}
Atom*
Atom::CreateAtom(DWORD type)
{
return new Atom(this, Length(), type);
}
// --------------------------------------------------------------------
MovieWriter::MovieWriter(AtomWriter* pContainer)
: m_pContainer(pContainer),
m_bStopped(false),
m_bFTYPInserted(false)
{
}
TrackWriter*
MovieWriter::MakeTrack(const CMediaType* pmt)
{
TypeHandler* ph = TypeHandler::Make(pmt);
if (!ph)
{
return NULL;
}
TrackWriter* pTrack = new TrackWriter(this, (long)m_Tracks.size(), ph);
m_Tracks.push_back(pTrack);
return pTrack;
}
HRESULT
MovieWriter::Close(REFERENCE_TIME* pDuration)
{
// get longest duration of all tracks
// also get earliest sample
vector<TrackWriterPtr>::iterator it;
REFERENCE_TIME tEarliest = -1;
REFERENCE_TIME tThis;
for (it = m_Tracks.begin(); it != m_Tracks.end(); it++)
{
TrackWriter* pTrack = *it;
tThis = pTrack->Earliest();
if (tThis != -1)
{
if ((tEarliest == -1) || (tThis < tEarliest))
{
tEarliest = tThis;
}
}
}
// adjust track start times so that the earliest track starts at 0
REFERENCE_TIME tDur = 0;
REFERENCE_TIME tAdj = -tEarliest;
for (it = m_Tracks.begin(); it != m_Tracks.end(); it++)
{
TrackWriter* pTrack = *it;
pTrack->AdjustStart(tAdj);
tThis = pTrack->Duration();
if (tThis > tDur)
{
tDur = tThis;
}
}
*pDuration = tDur;
LONGLONG tScaledDur = tDur * MovieScale() / UNITS;
// finish writing mdat
if (m_patmMDAT)
{
m_patmMDAT->Close();
m_patmMDAT = NULL;
}
// create moov atom
HRESULT hr = S_OK;
smart_ptr<Atom> pmoov = new Atom(m_pContainer, m_pContainer->Length(), DWORD('moov'));
// movie header
// we are using 90khz as the movie timescale, so
// we may need 64-bits.
smart_ptr<Atom> pmvhd = pmoov->CreateAtom('mvhd');
BYTE b[28*4];
ZeroMemory(b, (28*4));
int cHdr;
if (tScaledDur > 0x7fffffff)
{
b[0] = 1; // version 1
// create time 64bit
// modify time 64bit
// timescale 32-bit
// duration 64-bit
WriteLong(MovieScale(), b + (5*4));
WriteI64(tScaledDur, b + (6 * 4));
cHdr = 8 * 4;
}
else
{
long lDur = long(tScaledDur);
WriteLong(MovieScale(), b + (3 * 4));
WriteLong(lDur, b + (4 * 4));
cHdr = 5 * 4;
}
b[cHdr + 1] = 0x01;
b[cHdr + 4] = 0x01;
b[cHdr + 17] = 0x01;
b[cHdr + 33] = 0x01;
b[cHdr + 48] = 0x40;
WriteLong((long)m_Tracks.size() + 1, b + cHdr + 76); // one-based next-track-id
pmvhd->Append(b, cHdr + 80);
pmvhd->Close();
MakeIODS(pmoov);
for (it = m_Tracks.begin(); it != m_Tracks.end(); it++)
{
TrackWriter* pTrack = *it;
hr = pTrack->Close(pmoov);
if (FAILED(hr))
{
break;
}
}
pmoov->Close();
return hr;
}
void
MovieWriter::Stop()
{
CAutoLock lock(&m_csWrite);
m_bStopped = true;
}
void
MovieWriter::InsertFTYP(AtomWriter* pFile)
{
if (!m_bFTYPInserted)
{
smart_ptr<Atom> pFTYP = new Atom(pFile, pFile->Length(), DWORD('ftyp'));
// file type
BYTE b[4];
WriteLong(DWORD('mp42'), b);
pFTYP->Append(b, 4);
// minor version
WriteLong(0, b);
pFTYP->Append(b, 4);
// additional compatible specs
WriteLong(DWORD('mp42'), b);
pFTYP->Append(b, 4);
WriteLong(DWORD('isom'), b);
pFTYP->Append(b, 4);
pFTYP->Close();
m_bFTYPInserted = true;
}
}
bool
MovieWriter::CheckQueues()
{
CAutoLock lock(&m_csWrite);
if (m_bStopped)
{
return false;
}
// threading notes: we don't lock the
// individual track queues except during the
// actual access functions. The tracks are free to
// add data to the end of the queue. The head of the queue
// will not be removed except during Stop and by us. The
// m_bStopped flag ensures that we are not running when the
// tracks enter Stop.
// we need to return true if the whole set is at EOS
// and all queues emptied
bool bAllFinished;
for(;;)
{
bAllFinished = true; // ... until proven otherwise
// scan tracks to find which if any should write a chunk
bool bSomeNotReady = false;
bool bSomeAtEOS = false;
LONGLONG tEarliestNotReady = -1;
LONGLONG tEarliestReady = -1;
int indexReady = -1;
for (UINT i = 0; i < m_Tracks.size(); i++)
{
LONGLONG tHead;
if (!m_Tracks[i]->GetHeadTime(&tHead))
{
// no chunk ready -- ok if finished
if (!m_Tracks[i]->IsAtEOS())
{
bAllFinished = false;
// note last write time
bSomeNotReady = true;
LONGLONG tWritten = m_Tracks[i]->LastWrite();
if ((tEarliestNotReady == -1) || (tWritten < tEarliestNotReady))
{
// remember the time of the track that is furthest
// behind
tEarliestNotReady = tWritten;
}
} else {
bSomeAtEOS = true;
}
} else {
if (m_Tracks[i]->IsAtEOS())
{
bSomeAtEOS = true;
}
bAllFinished = false; // queue not empty -> not finished
// remember the earliest of the ready blocks
if ((tEarliestReady == -1) || (tHead < tEarliestReady))
{
tEarliestReady = tHead;
indexReady = i;
}
}
}
// is there anything to write
if (indexReady < 0)
{
break;
}
// mustn't get too far ahead of any blocked tracks (unless we have reached EOS)
if (!bSomeAtEOS && bSomeNotReady && ((tEarliestReady - tEarliestNotReady) > UNITS))
{
// wait for more data on earliest-not-ready track
break;
}
WriteTrack(indexReady);
}
return bAllFinished;
}
void
MovieWriter::WriteTrack(int indexReady)
{
// make sure we have space in an mdat atom
// -- make a new atom every 1Gb
if ((m_patmMDAT) && (m_patmMDAT->Length() >= 1024*1024*1024))
mpeg4.rar_Directshow Filter_directshow mp4mux_mpeg-4 multiplexor
版权申诉
118 浏览量
2022-09-23
09:42:39
上传
评论
收藏 452KB RAR 举报
刘良运
- 粉丝: 66
- 资源: 1万+