rollbaack accidental commit
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30499 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -22,8 +22,6 @@ SubInclude HAIKU_TOP src add-ons media plugins speex ;
|
||||
SubInclude HAIKU_TOP src add-ons media plugins mov_reader ;
|
||||
SubInclude HAIKU_TOP src add-ons media plugins mp4_reader ;
|
||||
|
||||
SubInclude HAIKU_TOP src add-ons media plugins asf_reader ;
|
||||
|
||||
# The following add-ons are GPL licensed, and can only be used with
|
||||
# software whose license is GPL compatible. To include these GPL
|
||||
# licensed add-ons, you need to run configure with the --include-gpl-addons
|
||||
|
||||
@@ -8,14 +8,12 @@ SubDirHdrs [ FDirName $(SUBDIR) libavcodec ] ;
|
||||
SubDirHdrs [ FDirName $(SUBDIR) libavutil ] ;
|
||||
SubDirHdrs [ FDirName $(SUBDIR) libswscale ] ;
|
||||
|
||||
SubDirCcFlags -fomit-frame-pointer -DPIC -fno-common ;
|
||||
|
||||
Addon avcodec :
|
||||
avcodec.cpp
|
||||
codectbl.cpp
|
||||
gfx_conv_c.cpp
|
||||
gfx_conv_c_lookup.cpp
|
||||
gfx_conv_mmx.cpp
|
||||
# gfx_conv_mmx.cpp
|
||||
gfx_util.cpp
|
||||
:
|
||||
libavcodec.a
|
||||
|
||||
@@ -466,18 +466,12 @@ avCodec::Decode(void *out_buffer, int64 *out_frameCount,
|
||||
if (fChunkBufferSize == 0) {
|
||||
media_header chunk_mh;
|
||||
status_t err;
|
||||
printf("Asking for more data after %Ld frames\n",fFrame);
|
||||
err = GetNextChunk(&fChunkBuffer, &fChunkBufferSize, &chunk_mh);
|
||||
if (err == B_LAST_BUFFER_ERROR) {
|
||||
printf("Last Chunk with chunk size %ld\n",fChunkBufferSize);
|
||||
return err;
|
||||
}
|
||||
if (err != B_OK || fChunkBufferSize < 0) {
|
||||
printf("GetNextChunk error %ld\n",fChunkBufferSize);
|
||||
TRACE("GetNextChunk error %ld\n",fChunkBufferSize);
|
||||
fChunkBufferSize = 0;
|
||||
break;
|
||||
}
|
||||
printf("Got a Chunk with start time of %Ld\n",chunk_mh.start_time);
|
||||
fChunkBufferOffset = 0;
|
||||
fStartTime = chunk_mh.start_time;
|
||||
if (*out_frameCount == 0)
|
||||
|
||||
@@ -69,7 +69,6 @@ const struct codec_table gCodecTable[] = {
|
||||
|
||||
{CODEC_ID_WMAV1, B_MEDIA_ENCODED_AUDIO, B_WAV_FORMAT_FAMILY, 0x160, "MS WMA v1"},
|
||||
{CODEC_ID_WMAV2, B_MEDIA_ENCODED_AUDIO, B_WAV_FORMAT_FAMILY, 0x161, "MS WMA v2"},
|
||||
{CODEC_ID_VOXWARE, B_MEDIA_ENCODED_AUDIO, B_WAV_FORMAT_FAMILY, 0x75, "Voxware"},
|
||||
|
||||
{CODEC_ID_CINEPAK, B_MEDIA_ENCODED_VIDEO, B_AVI_FORMAT_FAMILY, FOURCC('cvid'), "Cinepak Video"},
|
||||
{CODEC_ID_CINEPAK, B_MEDIA_ENCODED_VIDEO, B_QUICKTIME_FORMAT_FAMILY, 'cvid', "Cinepak Video"},
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
extern "C" {
|
||||
#include "libavcodec/imgconvert.h"
|
||||
}
|
||||
|
||||
void gfx_conv_null_mmx(AVFrame *in, AVFrame *out, int width, int height) {
|
||||
memcpy(out->data[0], in->data[0], height * in->linesize[0]);
|
||||
}
|
||||
|
||||
void gfx_conv_yuv410p_ycbcr422_mmx(AVFrame *in, AVFrame *out, int width, int height)
|
||||
{
|
||||
img_convert((AVPicture *)out,PIX_FMT_YUV422P,(const AVPicture *)in,PIX_FMT_YUV410P,width,height);
|
||||
}
|
||||
|
||||
void gfx_conv_yuv411p_ycbcr422_mmx(AVFrame *in, AVFrame *out, int width, int height)
|
||||
{
|
||||
img_convert((AVPicture *)out,PIX_FMT_YUV422P,(const AVPicture *)in,PIX_FMT_YUV411P,width,height);
|
||||
}
|
||||
|
||||
void gfx_conv_yuv420p_ycbcr422_mmx(AVFrame *in, AVFrame *out, int width, int height)
|
||||
{
|
||||
img_convert((AVPicture *)out,PIX_FMT_YUV422P,(const AVPicture *)in,PIX_FMT_YUV420P,width,height);
|
||||
}
|
||||
|
||||
void gfx_conv_yuv410p_rgb32_mmx(AVFrame *in, AVFrame *out, int width, int height)
|
||||
{
|
||||
img_convert((AVPicture *)out,PIX_FMT_RGB32,(const AVPicture *)in,PIX_FMT_YUV410P,width,height);
|
||||
}
|
||||
|
||||
void gfx_conv_yuv411p_rgb32_mmx(AVFrame *in, AVFrame *out, int width, int height)
|
||||
{
|
||||
img_convert((AVPicture *)out,PIX_FMT_RGB32,(const AVPicture *)in,PIX_FMT_YUV411P,width,height);
|
||||
}
|
||||
|
||||
void gfx_conv_yuv420p_rgb32_mmx(AVFrame *in, AVFrame *out, int width, int height)
|
||||
{
|
||||
img_convert((AVPicture *)out,PIX_FMT_RGB32,(const AVPicture *)in,PIX_FMT_YUV420P,width,height);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <GraphicsDefs.h>
|
||||
#include "libavcodec/avcodec.h"
|
||||
|
||||
bool IsMmxCpu();
|
||||
|
||||
void gfx_conv_null_mmx(AVFrame *in, AVFrame *out, int width, int height);
|
||||
|
||||
void gfx_conv_yuv410p_ycbcr422_mmx(AVFrame *in, AVFrame *out, int width, int height);
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
#endif
|
||||
|
||||
//#define INCLUDE_MMX defined(__INTEL__)
|
||||
#define INCLUDE_MMX 1
|
||||
#define INCLUDE_MMX 0
|
||||
|
||||
// this function will try to find the best colorspaces for both the ff-codec and
|
||||
// the Media Kit sides.
|
||||
gfx_convert_func resolve_colorspace(color_space colorSpace, PixelFormat pixelFormat)
|
||||
{
|
||||
#if INCLUDE_MMX
|
||||
bool mmx = true;
|
||||
bool mmx = IsMmxCpu();
|
||||
#endif
|
||||
|
||||
switch (colorSpace)
|
||||
|
||||
@@ -14,7 +14,7 @@ TARGET_WARNING_CCFLAGS = [ FFilter $(TARGET_WARNING_CCFLAGS)
|
||||
if $(HAIKU_GCC_VERSION[1]) >= 3 {
|
||||
SubDirCcFlags -fomit-frame-pointer -fno-pic ;
|
||||
} else {
|
||||
SubDirCcFlags -fomit-frame-pointer -DPIC -fno-common ;
|
||||
SubDirCcFlags -fomit-frame-pointer -DPIC ;
|
||||
}
|
||||
|
||||
local defines ;
|
||||
|
||||
@@ -54,9 +54,7 @@
|
||||
#define HAVE_DLFCN_H 0
|
||||
#define HAVE_DLOPEN 0
|
||||
#define HAVE_DOS_PATHS 0
|
||||
// Jamfile must have -fomit_frame_pointer
|
||||
#define HAVE_EBP_AVAILABLE 1
|
||||
// We use position independant code so no EBX
|
||||
#define HAVE_EBP_AVAILABLE 0
|
||||
#define HAVE_EBX_AVAILABLE 0
|
||||
#define HAVE_FAST_64BIT 0
|
||||
#define HAVE_FAST_CMOV 0
|
||||
@@ -77,10 +75,10 @@
|
||||
#define HAVE_MACHINE_IOCTL_BT848_H 0
|
||||
#define HAVE_MACHINE_IOCTL_METEOR_H 0
|
||||
#define HAVE_MALLOC_H 1
|
||||
#define HAVE_MEMALIGN 0
|
||||
#define HAVE_MEMALIGN 1
|
||||
#define HAVE_MKSTEMP 1
|
||||
#define HAVE_PLD 0
|
||||
#define HAVE_POSIX_MEMALIGN 1
|
||||
#define HAVE_POSIX_MEMALIGN 0
|
||||
#define HAVE_PPC64 0
|
||||
#define HAVE_ROUND 1
|
||||
#define HAVE_ROUNDF 1
|
||||
|
||||
@@ -2412,8 +2412,6 @@ b= t;
|
||||
}
|
||||
}
|
||||
}
|
||||
#include <stdio.h>
|
||||
#undef printf
|
||||
|
||||
static av_always_inline void hl_decode_mb_internal(H264Context *h, int simple){
|
||||
MpegEncContext * const s = &h->s;
|
||||
@@ -2422,8 +2420,6 @@ static av_always_inline void hl_decode_mb_internal(H264Context *h, int simple){
|
||||
const int mb_xy= h->mb_xy;
|
||||
const int mb_type= s->current_picture.mb_type[mb_xy];
|
||||
uint8_t *dest_y, *dest_cb, *dest_cr;
|
||||
uintptr_t v;
|
||||
size_t align;
|
||||
int linesize, uvlinesize /*dct_offset*/;
|
||||
int i;
|
||||
int *block_offset = &h->block_offset[0];
|
||||
@@ -2437,14 +2433,6 @@ static av_always_inline void hl_decode_mb_internal(H264Context *h, int simple){
|
||||
dest_cb = s->current_picture.data[1] + (mb_x + mb_y * s->uvlinesize) * 8;
|
||||
dest_cr = s->current_picture.data[2] + (mb_x + mb_y * s->uvlinesize) * 8;
|
||||
|
||||
v = (uintptr_t)dest_y;
|
||||
|
||||
align = ffs((int)v);
|
||||
|
||||
printf("aligned(16): %s: address: %p alignment: %d (2^%u)\n",
|
||||
align > 4 ? "PASS" : "FAIL", v, 1<<(align-1), align-1);
|
||||
|
||||
|
||||
s->dsp.prefetch(dest_y + (s->mb_x&3)*4*s->linesize + 64, s->linesize, 4);
|
||||
s->dsp.prefetch(dest_cb + (s->mb_x&7)*s->uvlinesize + 64, dest_cr - dest_cb, 2);
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ local defines ;
|
||||
defines = HAVE_AV_CONFIG_H=1 ;
|
||||
defines += ARCH_X86=1 ARCH_X86_32=1 ARCH_PPC=0 ARCH_SPARC=0 ;
|
||||
defines += HAVE_AMD3DNOW=0 HAVE_AMD3DNOWEXT=0 ;
|
||||
defines += HAVE_MMX=1 HAVE_MMX2=1 HAVE_SSE=1 HAVE_SSE3=1 ;
|
||||
defines += HAVE_MMX=1 HAVE_MMX2=1 HAVE_SSE=0 HAVE_SSE3=1 ;
|
||||
defines += HAVE_ALTIVEC=0 ;
|
||||
defines += HAVE_VIS=0 ;
|
||||
|
||||
|
||||
@@ -2391,56 +2391,6 @@ void ff_x264_deblock_h_luma_intra_sse2(uint8_t *pix, int stride, int alpha, int
|
||||
#define ff_float_to_int16_interleave6_3dnow(a,b,c) float_to_int16_interleave_misc_3dnow(a,b,c,6)
|
||||
#define ff_float_to_int16_interleave6_3dn2(a,b,c) float_to_int16_interleave_misc_3dnow(a,b,c,6)
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#undef printf
|
||||
|
||||
void haiku_x264_deblock_v_luma_sse2(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0) {
|
||||
|
||||
uintptr_t v = (uintptr_t)pix;
|
||||
size_t align1;
|
||||
size_t align2;
|
||||
|
||||
align1 = ffs((int)v);
|
||||
printf("V pix aligned(16): %s: address: %p alignment: %d (2^%u)\n",
|
||||
align1 > 4 ? "PASS" : "FAIL", v, 1<<(align1-1), align1-1);
|
||||
|
||||
v = (uintptr_t)tc0;
|
||||
|
||||
align2 = ffs((int)v);
|
||||
printf("V tc0 aligned(16): %s: address: %p alignment: %d (2^%u)\n",
|
||||
align2 > 4 ? "PASS" : "FAIL", v, 1<<(align2-1), align2-1);
|
||||
|
||||
if (align1 > 4 && align2 > 4) {
|
||||
ff_x264_deblock_v_luma_sse2(pix, stride, alpha, beta, tc0);
|
||||
} else {
|
||||
h264_v_loop_filter_luma_mmx2(pix, stride, alpha, beta, tc0);
|
||||
}
|
||||
}
|
||||
|
||||
void haiku_x264_deblock_h_luma_sse2(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0) {
|
||||
|
||||
uintptr_t v = (uintptr_t)pix;
|
||||
size_t align1;
|
||||
size_t align2;
|
||||
|
||||
align1 = ffs((int)v);
|
||||
printf("H pix aligned(16): %s: address: %p alignment: %d (2^%u)\n",
|
||||
align1 > 4 ? "PASS" : "FAIL", v, 1<<(align1-1), align1-1);
|
||||
|
||||
v = (uintptr_t)tc0;
|
||||
|
||||
align2 = ffs((int)v);
|
||||
printf("H tc0 aligned(16): %s: address: %p alignment: %d (2^%u)\n",
|
||||
align2 > 4 ? "PASS" : "FAIL", v, 1<<(align2-1), align2-1);
|
||||
|
||||
if (align1 > 4 && align2 > 4) {
|
||||
ff_x264_deblock_h_luma_sse2(pix, stride, alpha, beta, tc0);
|
||||
} else {
|
||||
h264_h_loop_filter_luma_mmx2(pix, stride, alpha, beta, tc0);
|
||||
}
|
||||
}
|
||||
|
||||
#define ff_float_to_int16_interleave6_sse2 ff_float_to_int16_interleave6_sse
|
||||
|
||||
#define FLOAT_TO_INT16_INTERLEAVE(cpu, body) \
|
||||
@@ -2995,8 +2945,8 @@ void dsputil_init_mmx(DSPContext* c, AVCodecContext *avctx)
|
||||
#endif
|
||||
if( mm_flags&FF_MM_SSE2 ){
|
||||
#if ARCH_X86_64 || !defined(__ICC) || __ICC > 1100
|
||||
c->h264_v_loop_filter_luma = haiku_x264_deblock_v_luma_sse2;
|
||||
c->h264_h_loop_filter_luma = haiku_x264_deblock_h_luma_sse2;
|
||||
c->h264_v_loop_filter_luma = ff_x264_deblock_v_luma_sse2;
|
||||
c->h264_h_loop_filter_luma = ff_x264_deblock_h_luma_sse2;
|
||||
c->h264_v_loop_filter_luma_intra = ff_x264_deblock_v_luma_intra_sse2;
|
||||
c->h264_h_loop_filter_luma_intra = ff_x264_deblock_h_luma_intra_sse2;
|
||||
#endif
|
||||
|
||||
@@ -7,7 +7,7 @@ TARGET_WARNING_CCFLAGS = [ FFilter $(TARGET_WARNING_CCFLAGS)
|
||||
SubDirHdrs [ FDirName $(SUBDIR) .. ] ;
|
||||
SubDirHdrs [ FDirName $(SUBDIR) ../libavcodec ] ;
|
||||
|
||||
SubDirCcFlags -fomit-frame-pointer -DPIC -fno-common ;
|
||||
SubDirCcFlags -fomit-frame-pointer -DPIC ;
|
||||
#SubDirCcFlags -DHAVE_AV_CONFIG_H=1 ;
|
||||
|
||||
StaticLibrary libavutil.a :
|
||||
|
||||
@@ -8,7 +8,7 @@ SubDirHdrs [ FDirName $(SUBDIR) ../libavcodec ] ;
|
||||
TARGET_WARNING_CCFLAGS = [ FFilter $(TARGET_WARNING_CCFLAGS)
|
||||
: -Wall -Wmissing-prototypes -Wsign-compare -Wpointer-arith ] ;
|
||||
|
||||
SubDirCcFlags -fomit-frame-pointer -DPIC -fno-common ;
|
||||
SubDirCcFlags -fomit-frame-pointer -DPIC ;
|
||||
|
||||
local arch_sources ;
|
||||
arch_sources = ;
|
||||
|
||||
@@ -41,17 +41,6 @@ AtomBase::~AtomBase()
|
||||
parentAtom = NULL;
|
||||
}
|
||||
|
||||
char *AtomBase::getAtomTypeAsFourcc()
|
||||
{
|
||||
fourcc[0] = (char)((atomType >> 24) & 0xff);
|
||||
fourcc[1] = (char)((atomType >> 16) & 0xff);
|
||||
fourcc[2] = (char)((atomType >> 8) & 0xff);
|
||||
fourcc[3] = (char)((atomType >> 0) & 0xff);
|
||||
fourcc[4] = '\0';
|
||||
|
||||
return fourcc;
|
||||
}
|
||||
|
||||
char *AtomBase::getAtomName()
|
||||
{
|
||||
char *_result;
|
||||
@@ -118,7 +107,7 @@ void AtomBase::DisplayAtoms()
|
||||
void AtomBase::DisplayAtoms(uint32 pindent)
|
||||
{
|
||||
Indent(pindent);
|
||||
printf("(%s)\n",getAtomName());
|
||||
printf("%s\n",getAtomName());
|
||||
}
|
||||
|
||||
void AtomBase::Indent(uint32 pindent)
|
||||
@@ -135,6 +124,10 @@ bool AtomBase::IsKnown()
|
||||
|
||||
void AtomBase::ReadArrayHeader(array_header *pHeader)
|
||||
{
|
||||
Read(&pHeader->Version);
|
||||
Read(&pHeader->Flags1);
|
||||
Read(&pHeader->Flags2);
|
||||
Read(&pHeader->Flags3);
|
||||
Read(&pHeader->NoEntries);
|
||||
}
|
||||
|
||||
@@ -171,17 +164,6 @@ void AtomBase::Read(uint32 *value)
|
||||
*value = B_BENDIAN_TO_HOST_INT32(*value);
|
||||
}
|
||||
|
||||
void AtomBase::Read(int32 *value)
|
||||
{
|
||||
uint32 bytes_read;
|
||||
|
||||
bytes_read = getStream()->Read(value,sizeof(int32));
|
||||
|
||||
// Assert((bytes_read == sizeof(int32),"Read Error");
|
||||
|
||||
*value = B_BENDIAN_TO_HOST_INT32(*value);
|
||||
}
|
||||
|
||||
void AtomBase::Read(uint16 *value)
|
||||
{
|
||||
uint32 bytes_read;
|
||||
@@ -220,52 +202,6 @@ void AtomBase::Read(uint8 *value, uint32 maxread)
|
||||
// Assert((bytes_read == maxread,"Read Error");
|
||||
}
|
||||
|
||||
uint64 AtomBase::GetBits(uint64 buffer, uint8 startBit, uint8 totalBits)
|
||||
{
|
||||
// startBit should range from 0-63, totalBits should range from 1-64
|
||||
if ((startBit < 64) && (totalBits > 0) && (totalBits <= 64) && (startBit + totalBits <= 64)) {
|
||||
// Ok pull from the buffer the bits wanted.
|
||||
buffer = buffer << startBit;
|
||||
buffer = buffer >> (64 - (totalBits + startBit) + startBit);
|
||||
|
||||
printf("buffer = %Ld\n",buffer);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
return 0L;
|
||||
}
|
||||
|
||||
uint32 AtomBase::GetBits(uint32 buffer, uint8 startBit, uint8 totalBits)
|
||||
{
|
||||
// startBit should range from 0-31, totalBits should range from 1-32
|
||||
if ((startBit < 32) && (totalBits > 0) && (totalBits <= 32) && (startBit + totalBits <= 32)) {
|
||||
// Ok pull from the buffer the bits wanted.
|
||||
buffer = buffer << startBit;
|
||||
buffer = buffer >> (32 - (startBit + totalBits) + startBit);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FullAtom::FullAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
|
||||
{
|
||||
}
|
||||
|
||||
FullAtom::~FullAtom()
|
||||
{
|
||||
}
|
||||
|
||||
void FullAtom::OnProcessMetaData()
|
||||
{
|
||||
Read(&Version);
|
||||
Read(&Flags1);
|
||||
Read(&Flags2);
|
||||
Read(&Flags3);
|
||||
}
|
||||
|
||||
AtomContainer::AtomContainer(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
|
||||
{
|
||||
TotalChildren = 0;
|
||||
@@ -278,7 +214,7 @@ AtomContainer::~AtomContainer()
|
||||
void AtomContainer::DisplayAtoms(uint32 pindent)
|
||||
{
|
||||
Indent(pindent);
|
||||
printf("%ld:(%s)\n",TotalChildren,getAtomName());
|
||||
printf("%ld:%s\n",TotalChildren,getAtomName());
|
||||
pindent++;
|
||||
// for each child
|
||||
for (uint32 i = 0;i < TotalChildren;i++) {
|
||||
|
||||
@@ -101,18 +101,17 @@ public:
|
||||
|
||||
uint64 getAtomSize() {return atomSize;};
|
||||
uint32 getAtomType() {return atomType;};
|
||||
char *getAtomTypeAsFourcc();
|
||||
off_t getAtomOffset() { return atomOffset; };
|
||||
off_t getStreamOffset() { return streamOffset; };
|
||||
|
||||
uint64 getDataSize() { return atomSize - 8;};
|
||||
off_t getAtomOffset() {return atomOffset;};
|
||||
off_t getStreamOffset() {return streamOffset;};
|
||||
|
||||
uint64 getDataSize() {return atomSize - 8;};
|
||||
|
||||
uint64 getBytesRemaining();
|
||||
|
||||
bool IsType(uint32 patomType) { return patomType == atomType; };
|
||||
bool IsType(uint32 patomType) {return patomType == atomType;};
|
||||
|
||||
void setAtomOffset(off_t patomOffset) { atomOffset = patomOffset; };
|
||||
void setStreamOffset(off_t pstreamOffset) { streamOffset = pstreamOffset; };
|
||||
void setAtomOffset(off_t patomOffset) {atomOffset = patomOffset;};
|
||||
void setStreamOffset(off_t pstreamOffset) {streamOffset = pstreamOffset;};
|
||||
|
||||
char *getAtomName();
|
||||
|
||||
@@ -135,42 +134,20 @@ public:
|
||||
|
||||
void setParent(AtomBase *pParent) {parentAtom = pParent;};
|
||||
AtomBase *getParent() { return parentAtom;};
|
||||
|
||||
|
||||
void Read(uint64 *value);
|
||||
void Read(uint32 *value);
|
||||
void Read(int32 *value);
|
||||
void Read(uint16 *value);
|
||||
void Read(uint8 *value);
|
||||
void Read(char *value, uint32 maxread);
|
||||
void Read(uint8 *value, uint32 maxread);
|
||||
|
||||
uint64 GetBits(uint64 buffer, uint8 startBit, uint8 totalBits);
|
||||
uint32 GetBits(uint32 buffer, uint8 startBit, uint8 totalBits);
|
||||
};
|
||||
|
||||
class FullAtom : public AtomBase {
|
||||
public:
|
||||
FullAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
|
||||
virtual ~FullAtom();
|
||||
|
||||
virtual void OnProcessMetaData();
|
||||
uint8 getVersion() {return Version;};
|
||||
uint8 getFlags1() {return Flags1;};
|
||||
uint8 getFlags2() {return Flags2;};
|
||||
uint8 getFlags3() {return Flags3;};
|
||||
|
||||
private:
|
||||
uint8 Version;
|
||||
uint8 Flags1;
|
||||
uint8 Flags2;
|
||||
uint8 Flags3;
|
||||
};
|
||||
|
||||
class AtomContainer : public AtomBase {
|
||||
|
||||
/*
|
||||
|
||||
This is an Atom that contains other atoms. It has children that may be Container Atoms or Standard Atoms
|
||||
This is an Atom that contains other atoms. It has children that may be Containter Atoms or Standard Atoms
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -39,13 +39,14 @@ extern AtomBase *getAtom(BPositionIO *pStream);
|
||||
MOVFileReader::MOVFileReader(BPositionIO *pStream)
|
||||
{
|
||||
theStream = pStream;
|
||||
|
||||
|
||||
// Find Size of Stream, need to rethink this for non seekable streams
|
||||
theStream->Seek(0,SEEK_END);
|
||||
StreamSize = theStream->Position();
|
||||
|
||||
theStream->Seek(0,SEEK_SET);
|
||||
TotalChildren = 0;
|
||||
|
||||
|
||||
theMVHDAtom = NULL;
|
||||
}
|
||||
|
||||
@@ -55,52 +56,41 @@ MOVFileReader::~MOVFileReader()
|
||||
theMVHDAtom = NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
MOVFileReader::IsEndOfData(off_t position)
|
||||
bool MOVFileReader::IsEndOfData(off_t pPosition)
|
||||
{
|
||||
AtomBase* aAtomBase;
|
||||
AtomBase *aAtomBase;
|
||||
|
||||
// check all mdat atoms to make sure position is within one of them
|
||||
|
||||
for (uint32 index=0;index<CountChildAtoms('mdat');index++) {
|
||||
aAtomBase = GetChildAtom(uint32('mdat'),index);
|
||||
if ((aAtomBase) && (aAtomBase->getAtomSize() > 8)) {
|
||||
MDATAtom *aMDATAtom = dynamic_cast<MDATAtom *>(aAtomBase);
|
||||
if (position >= aMDATAtom->getAtomOffset() && position <= aMDATAtom->getEOF()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
aAtomBase = GetChildAtom(uint32('mdat'),0);
|
||||
if (aAtomBase) {
|
||||
MDATAtom *aMdatAtom = dynamic_cast<MDATAtom *>(aAtomBase);
|
||||
return pPosition >= aMdatAtom->getEOF();
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MOVFileReader::IsEndOfFile(off_t position)
|
||||
bool MOVFileReader::IsEndOfFile(off_t pPosition)
|
||||
{
|
||||
return (position >= StreamSize);
|
||||
return (pPosition >= StreamSize);
|
||||
}
|
||||
|
||||
bool
|
||||
MOVFileReader::IsEndOfFile()
|
||||
bool MOVFileReader::IsEndOfFile()
|
||||
{
|
||||
return theStream->Position() >= StreamSize;
|
||||
return (theStream->Position() >= StreamSize);
|
||||
}
|
||||
|
||||
bool
|
||||
MOVFileReader::AddChild(AtomBase *childAtom)
|
||||
bool MOVFileReader::AddChild(AtomBase *pChildAtom)
|
||||
{
|
||||
if (childAtom) {
|
||||
atomChildren[TotalChildren++] = childAtom;
|
||||
if (pChildAtom) {
|
||||
atomChildren[TotalChildren++] = pChildAtom;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
AtomBase *
|
||||
MOVFileReader::GetChildAtom(uint32 patomType, uint32 offset)
|
||||
AtomBase *MOVFileReader::GetChildAtom(uint32 patomType, uint32 offset)
|
||||
{
|
||||
for (uint32 i = 0; i < TotalChildren; i++) {
|
||||
for (uint32 i=0;i<TotalChildren;i++) {
|
||||
if (atomChildren[i]->IsType(patomType)) {
|
||||
// found match, skip if offset non zero.
|
||||
if (offset == 0) {
|
||||
@@ -123,8 +113,7 @@ MOVFileReader::GetChildAtom(uint32 patomType, uint32 offset)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32
|
||||
MOVFileReader::CountChildAtoms(uint32 patomType)
|
||||
uint32 MOVFileReader::CountChildAtoms(uint32 patomType)
|
||||
{
|
||||
uint32 count = 0;
|
||||
|
||||
@@ -134,10 +123,9 @@ MOVFileReader::CountChildAtoms(uint32 patomType)
|
||||
return count;
|
||||
}
|
||||
|
||||
MVHDAtom*
|
||||
MOVFileReader::getMVHDAtom()
|
||||
MVHDAtom *MOVFileReader::getMVHDAtom()
|
||||
{
|
||||
AtomBase *aAtomBase;
|
||||
AtomBase *aAtomBase;
|
||||
|
||||
if (theMVHDAtom == NULL) {
|
||||
aAtomBase = GetChildAtom(uint32('mvhd'));
|
||||
@@ -148,11 +136,223 @@ MOVFileReader::getMVHDAtom()
|
||||
return theMVHDAtom;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MOVFileReader::BuildSuperIndex()
|
||||
uint32 MOVFileReader::getMovieTimeScale()
|
||||
{
|
||||
AtomBase *aAtomBase;
|
||||
return getMVHDAtom()->getTimeScale();
|
||||
}
|
||||
|
||||
bigtime_t MOVFileReader::getMovieDuration()
|
||||
{
|
||||
return ((bigtime_t(getMVHDAtom()->getDuration()) * 1000000L) / getMovieTimeScale());
|
||||
}
|
||||
|
||||
uint32 MOVFileReader::getStreamCount()
|
||||
{
|
||||
// count the number of tracks in the file
|
||||
return (CountChildAtoms(uint32('trak')));
|
||||
}
|
||||
|
||||
bigtime_t MOVFileReader::getVideoDuration(uint32 stream_index)
|
||||
{
|
||||
AtomBase *aAtomBase;
|
||||
|
||||
aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||
|
||||
if ((aAtomBase) && (dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo())) {
|
||||
return (dynamic_cast<TRAKAtom *>(aAtomBase)->Duration(1));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bigtime_t MOVFileReader::getAudioDuration(uint32 stream_index)
|
||||
{
|
||||
AtomBase *aAtomBase;
|
||||
|
||||
aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||
|
||||
if ((aAtomBase) && (dynamic_cast<TRAKAtom *>(aAtomBase)->IsAudio())) {
|
||||
return (dynamic_cast<TRAKAtom *>(aAtomBase)->Duration(1));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bigtime_t MOVFileReader::getMaxDuration()
|
||||
{
|
||||
AtomBase *aAtomBase;
|
||||
int32 video_index,audio_index;
|
||||
video_index = -1;
|
||||
audio_index = -1;
|
||||
|
||||
// find the active video and audio tracks
|
||||
for (uint32 i=0;i<getStreamCount();i++) {
|
||||
aAtomBase = GetChildAtom(uint32('trak'),i);
|
||||
|
||||
if ((aAtomBase) && (dynamic_cast<TRAKAtom *>(aAtomBase)->IsActive())) {
|
||||
if (dynamic_cast<TRAKAtom *>(aAtomBase)->IsAudio()) {
|
||||
audio_index = int32(i);
|
||||
}
|
||||
if (dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo()) {
|
||||
video_index = int32(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((video_index >= 0) && (audio_index >= 0)) {
|
||||
return MAX(getVideoDuration(video_index),getAudioDuration(audio_index));
|
||||
}
|
||||
if ((video_index < 0) && (audio_index >= 0)) {
|
||||
return getAudioDuration(audio_index);
|
||||
}
|
||||
if ((video_index >= 0) && (audio_index < 0)) {
|
||||
return getVideoDuration(video_index);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 MOVFileReader::getVideoFrameCount(uint32 stream_index)
|
||||
{
|
||||
AtomBase *aAtomBase;
|
||||
|
||||
aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||
|
||||
if ((aAtomBase) && (dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo())) {
|
||||
|
||||
return dynamic_cast<TRAKAtom *>(aAtomBase)->FrameCount();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32 MOVFileReader::getAudioFrameCount(uint32 stream_index)
|
||||
{
|
||||
if (IsAudio(stream_index)) {
|
||||
return uint32(((getAudioDuration(stream_index) * AudioFormat(stream_index)->SampleRate) / 1000000L) + 0.5);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool MOVFileReader::IsVideo(uint32 stream_index)
|
||||
{
|
||||
// Look for a trak with a vmhd atom
|
||||
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||
|
||||
if (aAtomBase) {
|
||||
return (dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo());
|
||||
}
|
||||
|
||||
// No trak
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MOVFileReader::IsAudio(uint32 stream_index)
|
||||
{
|
||||
// Look for a trak with a smhd atom
|
||||
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||
|
||||
if (aAtomBase) {
|
||||
return (dynamic_cast<TRAKAtom *>(aAtomBase)->IsAudio());
|
||||
}
|
||||
|
||||
// No trak
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 MOVFileReader::getFirstFrameInChunk(uint32 stream_index, uint32 pChunkID)
|
||||
{
|
||||
// Find Track
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||
if (aAtomBase) {
|
||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||
|
||||
return aTrakAtom->getFirstSampleInChunk(pChunkID);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 MOVFileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo)
|
||||
{
|
||||
// Find Track
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||
if (aAtomBase) {
|
||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||
uint32 ChunkNo = 1;
|
||||
|
||||
if (IsAudio(stream_index)) {
|
||||
ChunkNo = pFrameNo;
|
||||
}
|
||||
|
||||
if (IsVideo(stream_index)) {
|
||||
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
||||
|
||||
uint32 OffsetInChunk;
|
||||
ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk);
|
||||
}
|
||||
|
||||
return aTrakAtom->getNoSamplesInChunk(ChunkNo);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64 MOVFileReader::getOffsetForFrame(uint32 stream_index, uint32 pFrameNo)
|
||||
{
|
||||
// Find Track
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||
if (aAtomBase) {
|
||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||
|
||||
if (IsAudio(stream_index)) {
|
||||
// FrameNo is really chunk No for audio
|
||||
uint32 ChunkNo = pFrameNo;
|
||||
|
||||
// Get Offset For Chunk
|
||||
return aTrakAtom->getOffsetForChunk(ChunkNo);
|
||||
}
|
||||
|
||||
if (IsVideo(stream_index)) {
|
||||
|
||||
if (pFrameNo < aTrakAtom->FrameCount()) {
|
||||
// Get Sample for Frame
|
||||
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
||||
// Get Chunk For Sample and the offset for the frame within that chunk
|
||||
uint32 OffsetInChunk;
|
||||
uint32 ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk);
|
||||
// Get Offset For Chunk
|
||||
uint64 OffsetNo = aTrakAtom->getOffsetForChunk(ChunkNo);
|
||||
|
||||
if (ChunkNo != 0) {
|
||||
uint32 SampleSize;
|
||||
// Adjust the Offset for the Offset in the chunk
|
||||
if (aTrakAtom->IsSingleSampleSize()) {
|
||||
SampleSize = aTrakAtom->getSizeForSample(SampleNo);
|
||||
OffsetNo = OffsetNo + (OffsetInChunk * SampleSize);
|
||||
} else {
|
||||
// This is bad news performance wise
|
||||
for (uint32 i=1;i<=OffsetInChunk;i++) {
|
||||
SampleSize = aTrakAtom->getSizeForSample(SampleNo-i);
|
||||
OffsetNo = OffsetNo + SampleSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return OffsetNo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MOVFileReader::BuildSuperIndex()
|
||||
{
|
||||
AtomBase *aAtomBase;
|
||||
|
||||
for (uint32 stream=0;stream<getStreamCount();stream++) {
|
||||
aAtomBase = GetChildAtom(uint32('trak'),stream);
|
||||
@@ -163,7 +363,7 @@ MOVFileReader::BuildSuperIndex()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add end of file to index
|
||||
aAtomBase = GetChildAtom(uint32('mdat'),0);
|
||||
if (aAtomBase) {
|
||||
@@ -172,215 +372,7 @@ MOVFileReader::BuildSuperIndex()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
MOVFileReader::getMovieTimeScale()
|
||||
{
|
||||
return getMVHDAtom()->getTimeScale();
|
||||
}
|
||||
|
||||
bigtime_t
|
||||
MOVFileReader::getMovieDuration()
|
||||
{
|
||||
return bigtime_t((getMVHDAtom()->getDuration() * 1000000.0) / getMovieTimeScale());
|
||||
}
|
||||
|
||||
uint32
|
||||
MOVFileReader::getStreamCount()
|
||||
{
|
||||
// count the number of tracks in the file
|
||||
return CountChildAtoms(uint32('trak'));
|
||||
}
|
||||
|
||||
bigtime_t
|
||||
MOVFileReader::getVideoDuration(uint32 streamIndex)
|
||||
{
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex);
|
||||
|
||||
if (aAtomBase && dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo())
|
||||
return dynamic_cast<TRAKAtom *>(aAtomBase)->Duration(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bigtime_t
|
||||
MOVFileReader::getAudioDuration(uint32 streamIndex)
|
||||
{
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex);
|
||||
|
||||
if (aAtomBase && dynamic_cast<TRAKAtom *>(aAtomBase)->IsAudio())
|
||||
return dynamic_cast<TRAKAtom *>(aAtomBase)->Duration(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bigtime_t
|
||||
MOVFileReader::getMaxDuration()
|
||||
{
|
||||
AtomBase *aAtomBase;
|
||||
int32 videoIndex = -1;
|
||||
int32 audioIndex = -1;
|
||||
|
||||
// find the active video and audio tracks
|
||||
for (uint32 i = 0; i < getStreamCount(); i++) {
|
||||
aAtomBase = GetChildAtom(uint32('trak'), i);
|
||||
|
||||
if ((aAtomBase) && (dynamic_cast<TRAKAtom *>(aAtomBase)->IsActive())) {
|
||||
if (dynamic_cast<TRAKAtom *>(aAtomBase)->IsAudio()) {
|
||||
audioIndex = int32(i);
|
||||
}
|
||||
if (dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo()) {
|
||||
videoIndex = int32(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (videoIndex >= 0 && audioIndex >= 0) {
|
||||
return max_c(getVideoDuration(videoIndex),
|
||||
getAudioDuration(audioIndex));
|
||||
}
|
||||
if (videoIndex < 0 && audioIndex >= 0) {
|
||||
return getAudioDuration(audioIndex);
|
||||
}
|
||||
if (videoIndex >= 0 && audioIndex < 0) {
|
||||
return getVideoDuration(videoIndex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32
|
||||
MOVFileReader::getFrameCount(uint32 streamIndex)
|
||||
{
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex);
|
||||
|
||||
if (aAtomBase) {
|
||||
return dynamic_cast<TRAKAtom *>(aAtomBase)->FrameCount();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32
|
||||
MOVFileReader::getAudioChunkCount(uint32 streamIndex)
|
||||
{
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex);
|
||||
|
||||
if (aAtomBase && dynamic_cast<TRAKAtom *>(aAtomBase)->IsAudio())
|
||||
return dynamic_cast<TRAKAtom *>(aAtomBase)->getTotalChunks();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
MOVFileReader::IsVideo(uint32 streamIndex)
|
||||
{
|
||||
// Look for a 'trak' with a vmhd atom
|
||||
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex);
|
||||
if (aAtomBase)
|
||||
return dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo();
|
||||
|
||||
// No track
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
MOVFileReader::IsAudio(uint32 streamIndex)
|
||||
{
|
||||
// Look for a 'trak' with a smhd atom
|
||||
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex);
|
||||
|
||||
if (aAtomBase)
|
||||
return dynamic_cast<TRAKAtom *>(aAtomBase)->IsAudio();
|
||||
|
||||
// No track
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32
|
||||
MOVFileReader::getFirstFrameInChunk(uint32 streamIndex, uint32 pChunkID)
|
||||
{
|
||||
// Find Track
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex);
|
||||
if (aAtomBase) {
|
||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||
|
||||
return aTrakAtom->getFirstSampleInChunk(pChunkID);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32
|
||||
MOVFileReader::getNoFramesInChunk(uint32 streamIndex, uint32 pFrameNo)
|
||||
{
|
||||
// Find Track
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex);
|
||||
if (aAtomBase) {
|
||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||
uint32 ChunkNo = 1;
|
||||
|
||||
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
||||
|
||||
uint32 OffsetInChunk;
|
||||
ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk);
|
||||
|
||||
return aTrakAtom->getNoSamplesInChunk(ChunkNo);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64
|
||||
MOVFileReader::getOffsetForFrame(uint32 streamIndex, uint32 pFrameNo)
|
||||
{
|
||||
// Find Track
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex);
|
||||
if (aAtomBase) {
|
||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||
|
||||
if (pFrameNo < aTrakAtom->FrameCount()) {
|
||||
// Get time for Frame
|
||||
bigtime_t Time = aTrakAtom->getTimeForFrame(pFrameNo);
|
||||
|
||||
// Get Sample for Time
|
||||
uint32 SampleNo = aTrakAtom->getSampleForTime(Time);
|
||||
|
||||
// Get Chunk For Sample and the offset for the frame within that chunk
|
||||
uint32 OffsetInChunk;
|
||||
uint32 ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk);
|
||||
// Get Offset For Chunk
|
||||
uint64 OffsetNo = aTrakAtom->getOffsetForChunk(ChunkNo);
|
||||
|
||||
if (ChunkNo != 0) {
|
||||
uint32 SizeForSample;
|
||||
// Adjust the Offset for the Offset in the chunk
|
||||
if (aTrakAtom->IsSingleSampleSize()) {
|
||||
SizeForSample = aTrakAtom->getSizeForSample(SampleNo);
|
||||
OffsetNo = OffsetNo + (OffsetInChunk * SizeForSample);
|
||||
} else {
|
||||
// This is bad news performance wise
|
||||
for (uint32 i=1;i<=OffsetInChunk;i++) {
|
||||
SizeForSample = aTrakAtom->getSizeForSample(SampleNo-i);
|
||||
OffsetNo = OffsetNo + SizeForSample;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("frame %ld, time %Ld, sample %ld, Chunk %ld, OffsetInChunk %ld, Offset %Ld\n",pFrameNo, Time, SampleNo, ChunkNo, OffsetInChunk, OffsetNo);
|
||||
|
||||
return OffsetNo;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
MOVFileReader::ParseFile()
|
||||
status_t MOVFileReader::ParseFile()
|
||||
{
|
||||
AtomBase *aChild;
|
||||
while (IsEndOfFile() == false) {
|
||||
@@ -400,8 +392,7 @@ MOVFileReader::ParseFile()
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
const mov_main_header*
|
||||
MOVFileReader::MovMainHeader()
|
||||
const mov_main_header *MOVFileReader::MovMainHeader()
|
||||
{
|
||||
// Fill In theMainHeader
|
||||
// uint32 micro_sec_per_frame;
|
||||
@@ -437,22 +428,22 @@ MOVFileReader::MovMainHeader()
|
||||
} else {
|
||||
theMainHeader.width = VideoFormat(videoStream)->width;
|
||||
theMainHeader.height = VideoFormat(videoStream)->height;
|
||||
theMainHeader.total_frames = getFrameCount(videoStream);
|
||||
theMainHeader.total_frames = getVideoFrameCount(videoStream);
|
||||
theMainHeader.suggested_buffer_size = theMainHeader.width * theMainHeader.height * VideoFormat(videoStream)->bit_count / 8;
|
||||
theMainHeader.micro_sec_per_frame = uint32(1000000.0 / VideoFormat(videoStream)->FrameRate);
|
||||
}
|
||||
|
||||
|
||||
theMainHeader.padding_granularity = 0;
|
||||
theMainHeader.max_bytes_per_sec = 0;
|
||||
|
||||
return &theMainHeader;
|
||||
}
|
||||
|
||||
const AudioMetaData *
|
||||
MOVFileReader::AudioFormat(uint32 streamIndex)
|
||||
const AudioMetaData *MOVFileReader::AudioFormat(uint32 stream_index)
|
||||
{
|
||||
if (IsAudio(streamIndex)) {
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex);
|
||||
if (IsAudio(stream_index)) {
|
||||
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||
|
||||
if (aAtomBase) {
|
||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||
@@ -505,16 +496,17 @@ MOVFileReader::AudioFormat(uint32 streamIndex)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const VideoMetaData*
|
||||
MOVFileReader::VideoFormat(uint32 streamIndex)
|
||||
const VideoMetaData *MOVFileReader::VideoFormat(uint32 stream_index)
|
||||
{
|
||||
if (IsVideo(streamIndex)) {
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex);
|
||||
if (IsVideo(stream_index)) {
|
||||
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||
|
||||
if (aAtomBase) {
|
||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||
|
||||
|
||||
aAtomBase = aTrakAtom->GetChildAtom(uint32('stsd'),0);
|
||||
|
||||
if (aAtomBase) {
|
||||
STSDAtom *aSTSDAtom = dynamic_cast<STSDAtom *>(aAtomBase);
|
||||
|
||||
@@ -548,30 +540,29 @@ MOVFileReader::VideoFormat(uint32 streamIndex)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const mov_stream_header*
|
||||
MOVFileReader::StreamFormat(uint32 streamIndex)
|
||||
const mov_stream_header *MOVFileReader::StreamFormat(uint32 stream_index)
|
||||
{
|
||||
if (IsActive(streamIndex) == false) {
|
||||
// Fill In a Stream Header
|
||||
theStreamHeader.length = 0;
|
||||
|
||||
if (IsActive(stream_index) == false) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Fill In a Stream Header
|
||||
theStreamHeader.length = 0;
|
||||
|
||||
if (IsVideo(streamIndex)) {
|
||||
theStreamHeader.rate = uint32(1000000.0*VideoFormat(streamIndex)->FrameRate);
|
||||
if (IsVideo(stream_index)) {
|
||||
theStreamHeader.rate = uint32(1000000L*VideoFormat(stream_index)->FrameRate);
|
||||
theStreamHeader.scale = 1000000L;
|
||||
theStreamHeader.length = getFrameCount(streamIndex);
|
||||
theStreamHeader.length = getVideoFrameCount(stream_index);
|
||||
}
|
||||
|
||||
if (IsAudio(streamIndex)) {
|
||||
theStreamHeader.rate = uint32(AudioFormat(streamIndex)->SampleRate);
|
||||
|
||||
if (IsAudio(stream_index)) {
|
||||
theStreamHeader.rate = uint32(AudioFormat(stream_index)->SampleRate);
|
||||
theStreamHeader.scale = 1;
|
||||
theStreamHeader.length = getFrameCount(streamIndex);
|
||||
theStreamHeader.sample_size = AudioFormat(streamIndex)->SampleSize;
|
||||
theStreamHeader.suggested_buffer_size = AudioFormat(streamIndex)->BufferSize;
|
||||
theStreamHeader.length = getAudioFrameCount(stream_index);
|
||||
theStreamHeader.sample_size = AudioFormat(stream_index)->SampleSize;
|
||||
theStreamHeader.suggested_buffer_size = theStreamHeader.rate * theStreamHeader.sample_size;
|
||||
}
|
||||
|
||||
|
||||
return &theStreamHeader;
|
||||
}
|
||||
|
||||
@@ -579,14 +570,23 @@ MOVFileReader::StreamFormat(uint32 streamIndex)
|
||||
uint32
|
||||
MOVFileReader::getChunkSize(uint32 streamIndex, uint32 frameNumber)
|
||||
{
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex);
|
||||
if (aAtomBase) {
|
||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex);
|
||||
if (aAtomBase == NULL)
|
||||
return 0;
|
||||
|
||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||
|
||||
if (IsAudio(streamIndex)) {
|
||||
// We read audio in chunk by chunk so chunk size is chunk size
|
||||
off_t chunkStart = aTrakAtom->getOffsetForChunk(frameNumber);
|
||||
return theChunkSuperIndex.getChunkSize(streamIndex, frameNumber, chunkStart);
|
||||
}
|
||||
|
||||
if (IsVideo(streamIndex)) {
|
||||
if (frameNumber < aTrakAtom->FrameCount()) {
|
||||
uint32 SampleNo = aTrakAtom->getSampleForFrame(frameNumber);
|
||||
|
||||
return aTrakAtom->getSizeForSample(SampleNo);
|
||||
// We read video in Sample by Sample so chunk size is Sample Size
|
||||
uint32 sampleNumber = aTrakAtom->getSampleForFrame(frameNumber);
|
||||
return aTrakAtom->getSizeForSample(sampleNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -595,62 +595,57 @@ MOVFileReader::getChunkSize(uint32 streamIndex, uint32 frameNumber)
|
||||
|
||||
|
||||
bool
|
||||
MOVFileReader::IsKeyFrame(uint32 streamIndex, uint32 pFrameNo)
|
||||
MOVFileReader::IsKeyFrame(uint32 stream_index, uint32 pFrameNo)
|
||||
{
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex);
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||
if (aAtomBase) {
|
||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||
|
||||
return aTrakAtom->IsSyncSample(pFrameNo);
|
||||
|
||||
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
||||
return aTrakAtom->IsSyncSample(SampleNo);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
MOVFileReader::GetNextChunkInfo(uint32 streamIndex, uint32 pFrameNo,
|
||||
off_t *start, uint32 *size, bool *keyframe)
|
||||
bool MOVFileReader::GetNextChunkInfo(uint32 stream_index, uint32 pFrameNo, off_t *start, uint32 *size, bool *keyframe)
|
||||
{
|
||||
*start = getOffsetForFrame(streamIndex, pFrameNo);
|
||||
*size = getChunkSize(streamIndex, pFrameNo);
|
||||
|
||||
*start = getOffsetForFrame(stream_index, pFrameNo);
|
||||
*size = getChunkSize(stream_index, pFrameNo);
|
||||
|
||||
if ((*start > 0) && (*size > 0)) {
|
||||
*keyframe = IsKeyFrame(streamIndex, pFrameNo);
|
||||
*keyframe = IsKeyFrame(stream_index, pFrameNo);
|
||||
}
|
||||
|
||||
// printf("start %Ld, size %ld, eof %s, eod %s\n",*start,*size, IsEndOfFile(*start + *size) ? "true" : "false", IsEndOfData(*start + *size) ? "true" : "false");
|
||||
|
||||
// TODO need a better method for detecting End of Data Note ChunkSize of 0 seems to be it.
|
||||
return *start > 0 && *size > 0 && !IsEndOfFile(*start + *size)
|
||||
&& !IsEndOfData(*start + *size);
|
||||
return ((*start > 0) && (*size > 0) && !(IsEndOfFile(*start + *size)) && !(IsEndOfData(*start + *size)));
|
||||
}
|
||||
|
||||
bool
|
||||
MOVFileReader::IsActive(uint32 streamIndex)
|
||||
bool MOVFileReader::IsActive(uint32 stream_index)
|
||||
{
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex);
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||
if (aAtomBase) {
|
||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||
return aTrakAtom->IsActive();
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
MOVFileReader::IsSupported(BPositionIO *source)
|
||||
bool MOVFileReader::IsSupported(BPositionIO *source)
|
||||
{
|
||||
// MOV files normally do not have ftyp atoms
|
||||
// But when they do we need to check if they have a qt brand
|
||||
// No qt brand means the file is likely to be a MP4 file
|
||||
|
||||
AtomBase *aAtom = getAtom(source);
|
||||
AtomBase *aAtom;
|
||||
|
||||
aAtom = getAtom(source);
|
||||
|
||||
if (aAtom) {
|
||||
if (dynamic_cast<FTYPAtom *>(aAtom)) {
|
||||
aAtom->ProcessMetaData();
|
||||
printf("ftyp atom found checking for qt brand\n");
|
||||
aAtom->ProcessMetaData();
|
||||
// MP4 files start with a ftyp atom that contains an isom brand
|
||||
// MOV files with a ftyp atom contain the qt brand
|
||||
return dynamic_cast<FTYPAtom *>(aAtom)->HasBrand(uint32('qt '));
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "MOVParser.h"
|
||||
#include "ChunkSuperIndex.h"
|
||||
|
||||
// QT MOV file reader
|
||||
// QT MOV file reader (and maybe MP4 as well)
|
||||
class MOVFileReader {
|
||||
private:
|
||||
// Atom List
|
||||
@@ -68,9 +68,9 @@ public:
|
||||
// getter for MVHDAtom
|
||||
MVHDAtom *getMVHDAtom();
|
||||
|
||||
bool IsEndOfFile(off_t position);
|
||||
bool IsEndOfFile(off_t pPosition);
|
||||
bool IsEndOfFile();
|
||||
bool IsEndOfData(off_t position);
|
||||
bool IsEndOfData(off_t pPosition);
|
||||
|
||||
// Is this a quicktime file
|
||||
static bool IsSupported(BPositionIO *source);
|
||||
@@ -81,44 +81,45 @@ public:
|
||||
// Duration defined by the movie header
|
||||
bigtime_t getMovieDuration();
|
||||
|
||||
// The first video track duration indexed by streamIndex
|
||||
bigtime_t getVideoDuration(uint32 streamIndex);
|
||||
// the first audio track duration indexed by streamIndex
|
||||
bigtime_t getAudioDuration(uint32 streamIndex);
|
||||
// The first video track duration indexed by stream_index
|
||||
bigtime_t getVideoDuration(uint32 stream_index);
|
||||
// the first audio track duration indexed by stream_index
|
||||
bigtime_t getAudioDuration(uint32 stream_index);
|
||||
// the max of all active audio or video durations
|
||||
bigtime_t getMaxDuration();
|
||||
|
||||
// The no of frames in the track indexed by streamIndex
|
||||
uint32 getFrameCount(uint32 streamIndex);
|
||||
// The no of chunks in the audio track indexed by streamIndex
|
||||
uint32 getAudioChunkCount(uint32 streamIndex);
|
||||
// The no of frames in the video track indexed by stream_index
|
||||
uint32 getVideoFrameCount(uint32 stream_index);
|
||||
// The no of frames in the audio track indexed by stream_index
|
||||
uint32 getAudioFrameCount(uint32 stream_index);
|
||||
|
||||
// Is stream (track) a video track
|
||||
bool IsVideo(uint32 streamIndex);
|
||||
bool IsVideo(uint32 stream_index);
|
||||
// Is stream (track) a audio track
|
||||
bool IsAudio(uint32 streamIndex);
|
||||
bool IsAudio(uint32 stream_index);
|
||||
|
||||
uint32 getNoFramesInChunk(uint32 streamIndex, uint32 pFrameNo);
|
||||
uint32 getFirstFrameInChunk(uint32 streamIndex, uint32 pChunkID);
|
||||
uint32 getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo);
|
||||
uint32 getFirstFrameInChunk(uint32 stream_index, uint32 pChunkID);
|
||||
|
||||
uint64 getOffsetForFrame(uint32 streamIndex, uint32 pFrameNo);
|
||||
uint32 getChunkSize(uint32 streamIndex, uint32 pFrameNo);
|
||||
bool IsKeyFrame(uint32 streamIndex, uint32 pFrameNo);
|
||||
uint64 getOffsetForFrame(uint32 stream_index, uint32 pFrameNo);
|
||||
uint32 getChunkSize(uint32 stream_index, uint32 pFrameNo);
|
||||
bool IsKeyFrame(uint32 stream_index, uint32 pFrameNo);
|
||||
|
||||
status_t ParseFile();
|
||||
BPositionIO *Source() {return theStream;};
|
||||
|
||||
bool IsActive(uint32 streamIndex);
|
||||
bool IsActive(uint32 stream_index);
|
||||
|
||||
bool GetNextChunkInfo(uint32 streamIndex, uint32 pFrameNo, off_t *start, uint32 *size, bool *keyframe);
|
||||
bool GetNextChunkInfo(uint32 stream_index, uint32 pFrameNo, off_t *start, uint32 *size, bool *keyframe);
|
||||
|
||||
// Return all Audio Meta Data
|
||||
const AudioMetaData *AudioFormat(uint32 streamIndex);
|
||||
const AudioMetaData *AudioFormat(uint32 stream_index);
|
||||
// Return all Video Meta Data
|
||||
const VideoMetaData *VideoFormat(uint32 streamIndex);
|
||||
const VideoMetaData *VideoFormat(uint32 stream_index);
|
||||
|
||||
// XXX these need work
|
||||
const mov_main_header *MovMainHeader();
|
||||
const mov_stream_header *StreamFormat(uint32 streamIndex);
|
||||
const mov_stream_header *StreamFormat(uint32 stream_index);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -57,10 +57,6 @@ AtomBase *getAtom(BPositionIO *pStream)
|
||||
// Handle extended size
|
||||
pStream->Read(&aRealAtomSize,4);
|
||||
aRealAtomSize = B_BENDIAN_TO_HOST_INT64(aRealAtomSize);
|
||||
} else if (aAtomSize == 0) {
|
||||
// aAtomSize extends to end of file.
|
||||
// TODO this is broken
|
||||
aRealAtomSize = 0;
|
||||
} else {
|
||||
aRealAtomSize = aAtomSize;
|
||||
}
|
||||
@@ -161,22 +157,10 @@ AtomBase *getAtom(BPositionIO *pStream)
|
||||
return new STSSAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
|
||||
}
|
||||
|
||||
if (aAtomType == uint32('ctts')) {
|
||||
return new CTTSAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
|
||||
}
|
||||
|
||||
if (aAtomType == uint32('stsz')) {
|
||||
return new STSZAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
|
||||
}
|
||||
|
||||
if (aAtomType == uint32('stz2')) {
|
||||
return new STZ2Atom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
|
||||
}
|
||||
|
||||
if (aAtomType == uint32('ftyp')) {
|
||||
return new FTYPAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
|
||||
}
|
||||
|
||||
if (aAtomType == uint32('cmov')) {
|
||||
return new CMOVAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
|
||||
}
|
||||
@@ -193,6 +177,10 @@ AtomBase *getAtom(BPositionIO *pStream)
|
||||
return new ESDSAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
|
||||
}
|
||||
|
||||
if (aAtomType == uint32('ftyp')) {
|
||||
return new FTYPAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
|
||||
}
|
||||
|
||||
return new AtomBase(pStream, aStreamOffset, aAtomType, aRealAtomSize);
|
||||
|
||||
}
|
||||
@@ -377,7 +365,7 @@ char *CMVDAtom::OnGetAtomName()
|
||||
return "Compressed Movie Data";
|
||||
}
|
||||
|
||||
MVHDAtom::MVHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize)
|
||||
MVHDAtom::MVHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -387,7 +375,6 @@ MVHDAtom::~MVHDAtom()
|
||||
|
||||
void MVHDAtom::OnProcessMetaData()
|
||||
{
|
||||
FullAtom::OnProcessMetaData();
|
||||
Read(&theHeader.CreationTime);
|
||||
Read(&theHeader.ModificationTime);
|
||||
Read(&theHeader.TimeScale);
|
||||
@@ -400,7 +387,7 @@ void MVHDAtom::OnProcessMetaData()
|
||||
Read(&theHeader.SelectionTime);
|
||||
Read(&theHeader.SelectionDuration);
|
||||
Read(&theHeader.CurrentTime);
|
||||
Read(&theHeader.NextTrackID);
|
||||
Read(&theHeader.NextTrackID);
|
||||
}
|
||||
|
||||
char *MVHDAtom::OnGetAtomName()
|
||||
@@ -421,7 +408,7 @@ AtomBase *aAtomBase;
|
||||
return theMVHDAtom;
|
||||
}
|
||||
|
||||
STTSAtom::STTSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize)
|
||||
STTSAtom::STTSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
|
||||
{
|
||||
theHeader.NoEntries = 0;
|
||||
SUMDurations = 0;
|
||||
@@ -440,12 +427,8 @@ void STTSAtom::OnProcessMetaData()
|
||||
{
|
||||
TimeToSample *aTimeToSample;
|
||||
|
||||
FullAtom::OnProcessMetaData();
|
||||
|
||||
ReadArrayHeader(&theHeader);
|
||||
|
||||
// printf("STTS:: Entries %ld\n",theHeader.NoEntries);
|
||||
|
||||
for (uint32 i=0;i<theHeader.NoEntries;i++) {
|
||||
aTimeToSample = new TimeToSample;
|
||||
|
||||
@@ -455,11 +438,7 @@ TimeToSample *aTimeToSample;
|
||||
theTimeToSampleArray[i] = aTimeToSample;
|
||||
SUMDurations += (theTimeToSampleArray[i]->Duration * theTimeToSampleArray[i]->Count);
|
||||
SUMCounts += theTimeToSampleArray[i]->Count;
|
||||
|
||||
// printf("(%ld,%ld)",aTimeToSample->Count,aTimeToSample->Duration);
|
||||
|
||||
}
|
||||
// printf("\n");
|
||||
}
|
||||
|
||||
char *STTSAtom::OnGetAtomName()
|
||||
@@ -467,55 +446,28 @@ char *STTSAtom::OnGetAtomName()
|
||||
return "Time to Sample Atom";
|
||||
}
|
||||
|
||||
uint32 STTSAtom::getSampleForTime(bigtime_t pTime)
|
||||
uint32 STTSAtom::getSampleForTime(uint32 pTime)
|
||||
{
|
||||
// Sample for time is this calc, how does STTS help us?
|
||||
return uint32((pTime * FrameRate + 50) / 1000000.0);
|
||||
// TODO this is too slow. PreCalc when loading this?
|
||||
uint64 Duration = 0;
|
||||
|
||||
for (uint32 i=0;i<theHeader.NoEntries;i++) {
|
||||
Duration += (theTimeToSampleArray[i]->Duration * theTimeToSampleArray[i]->Count);
|
||||
if (Duration > pTime) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 STTSAtom::getSampleForFrame(uint32 pFrame)
|
||||
{
|
||||
// Convert frame to time and call getSampleForTime()
|
||||
// Hmm Sample is Frame really, this Atom is more usefull for time->sample calcs
|
||||
return pFrame;
|
||||
}
|
||||
|
||||
CTTSAtom::CTTSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize)
|
||||
{
|
||||
theHeader.NoEntries = 0;
|
||||
}
|
||||
|
||||
CTTSAtom::~CTTSAtom()
|
||||
{
|
||||
for (uint32 i=0;i<theHeader.NoEntries;i++) {
|
||||
delete theCompTimeToSampleArray[i];
|
||||
theCompTimeToSampleArray[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CTTSAtom::OnProcessMetaData()
|
||||
{
|
||||
CompTimeToSample *aCompTimeToSample;
|
||||
|
||||
FullAtom::OnProcessMetaData();
|
||||
|
||||
ReadArrayHeader(&theHeader);
|
||||
|
||||
for (uint32 i=0;i<theHeader.NoEntries;i++) {
|
||||
aCompTimeToSample = new CompTimeToSample;
|
||||
|
||||
Read(&aCompTimeToSample->Count);
|
||||
Read(&aCompTimeToSample->Offset);
|
||||
|
||||
theCompTimeToSampleArray[i] = aCompTimeToSample;
|
||||
}
|
||||
}
|
||||
|
||||
char *CTTSAtom::OnGetAtomName()
|
||||
{
|
||||
return "Composition Time to Sample Atom";
|
||||
}
|
||||
|
||||
STSCAtom::STSCAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize)
|
||||
STSCAtom::STSCAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
|
||||
{
|
||||
theHeader.NoEntries = 0;
|
||||
}
|
||||
@@ -532,13 +484,9 @@ void STSCAtom::OnProcessMetaData()
|
||||
{
|
||||
SampleToChunk *aSampleToChunk;
|
||||
|
||||
FullAtom::OnProcessMetaData();
|
||||
|
||||
ReadArrayHeader(&theHeader);
|
||||
|
||||
uint32 TotalPrevSamples = 0;
|
||||
|
||||
// printf("STSC:: Entries %ld\n",theHeader.NoEntries);
|
||||
|
||||
for (uint32 i=0;i<theHeader.NoEntries;i++) {
|
||||
aSampleToChunk = new SampleToChunk;
|
||||
@@ -554,11 +502,8 @@ SampleToChunk *aSampleToChunk;
|
||||
aSampleToChunk->TotalPrevSamples = 0;
|
||||
}
|
||||
|
||||
// printf("(%ld,%ld)",aSampleToChunk->SamplesPerChunk, aSampleToChunk->TotalPrevSamples);
|
||||
|
||||
theSampleToChunkArray[i] = aSampleToChunk;
|
||||
}
|
||||
// printf("\n");
|
||||
}
|
||||
|
||||
char *STSCAtom::OnGetAtomName()
|
||||
@@ -614,7 +559,7 @@ uint32 STSCAtom::getChunkForSample(uint32 pSample, uint32 *pOffsetInChunk)
|
||||
return theSampleToChunkArray[theHeader.NoEntries-1]->FirstChunk;
|
||||
}
|
||||
|
||||
STSSAtom::STSSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize)
|
||||
STSSAtom::STSSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
|
||||
{
|
||||
theHeader.NoEntries = 0;
|
||||
}
|
||||
@@ -631,15 +576,12 @@ void STSSAtom::OnProcessMetaData()
|
||||
{
|
||||
SyncSample *aSyncSample;
|
||||
|
||||
FullAtom::OnProcessMetaData();
|
||||
|
||||
ReadArrayHeader(&theHeader);
|
||||
|
||||
|
||||
for (uint32 i=0;i<theHeader.NoEntries;i++) {
|
||||
aSyncSample = new SyncSample;
|
||||
|
||||
Read(&aSyncSample->SyncSampleNo);
|
||||
|
||||
theSyncSampleArray[i] = aSyncSample;
|
||||
}
|
||||
}
|
||||
@@ -657,7 +599,7 @@ bool STSSAtom::IsSyncSample(uint32 pSampleNo)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pSampleNo < theSyncSampleArray[i]->SyncSampleNo) {
|
||||
if (pSampleNo > theSyncSampleArray[i]->SyncSampleNo) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -665,14 +607,14 @@ bool STSSAtom::IsSyncSample(uint32 pSampleNo)
|
||||
return false;
|
||||
}
|
||||
|
||||
STSZAtom::STSZAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize)
|
||||
STSZAtom::STSZAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
|
||||
{
|
||||
SampleCount = 0;
|
||||
theHeader.NoEntries = 0;
|
||||
}
|
||||
|
||||
STSZAtom::~STSZAtom()
|
||||
{
|
||||
for (uint32 i=0;i<SampleCount;i++) {
|
||||
for (uint32 i=0;i<theHeader.NoEntries;i++) {
|
||||
delete theSampleSizeArray[i];
|
||||
theSampleSizeArray[i] = NULL;
|
||||
}
|
||||
@@ -680,36 +622,38 @@ STSZAtom::~STSZAtom()
|
||||
|
||||
void STSZAtom::OnProcessMetaData()
|
||||
{
|
||||
FullAtom::OnProcessMetaData();
|
||||
|
||||
Read(&SampleSize);
|
||||
Read(&SampleCount);
|
||||
SampleSizeEntry *aSampleSize;
|
||||
|
||||
// Just to make things difficult this is not quite a standard array header
|
||||
Read(&theHeader.Version);
|
||||
Read(&theHeader.Flags1);
|
||||
Read(&theHeader.Flags2);
|
||||
Read(&theHeader.Flags3);
|
||||
Read(&theHeader.SampleSize);
|
||||
Read(&theHeader.NoEntries);
|
||||
|
||||
// If the sample size is constant there is no array and NoEntries seems to contain bad values
|
||||
if (SampleSize == 0) {
|
||||
SampleSizePtr aSampleSizePtr;
|
||||
|
||||
for (uint32 i=0;i<SampleCount;i++) {
|
||||
aSampleSizePtr = new SampleSizeEntry;
|
||||
if (theHeader.SampleSize == 0) {
|
||||
for (uint32 i=0;i<theHeader.NoEntries;i++) {
|
||||
aSampleSize = new SampleSizeEntry;
|
||||
|
||||
Read(&aSampleSizePtr->EntrySize);
|
||||
|
||||
theSampleSizeArray[i] = aSampleSizePtr;
|
||||
Read(&aSampleSize->EntrySize);
|
||||
theSampleSizeArray[i] = aSampleSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *STSZAtom::OnGetAtomName()
|
||||
{
|
||||
printf("SS=%ld Count=%ld ",SampleSize,SampleCount);
|
||||
printf("%ld ",theHeader.SampleSize);
|
||||
return "Sample Size Atom";
|
||||
}
|
||||
|
||||
uint32 STSZAtom::getSizeForSample(uint32 pSampleNo)
|
||||
{
|
||||
if (SampleSize > 0) {
|
||||
if (theHeader.SampleSize > 0) {
|
||||
// All samples are the same size
|
||||
return SampleSize;
|
||||
return theHeader.SampleSize;
|
||||
}
|
||||
|
||||
// Sample Array indexed by SampleNo
|
||||
@@ -718,96 +662,10 @@ uint32 STSZAtom::getSizeForSample(uint32 pSampleNo)
|
||||
|
||||
bool STSZAtom::IsSingleSampleSize()
|
||||
{
|
||||
return (SampleSize > 0);
|
||||
return (theHeader.SampleSize > 0);
|
||||
}
|
||||
|
||||
STZ2Atom::STZ2Atom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize)
|
||||
{
|
||||
SampleCount = 0;
|
||||
}
|
||||
|
||||
STZ2Atom::~STZ2Atom()
|
||||
{
|
||||
for (uint32 i=0;i<SampleCount;i++) {
|
||||
delete theSampleSizeArray[i];
|
||||
theSampleSizeArray[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void STZ2Atom::OnProcessMetaData()
|
||||
{
|
||||
FullAtom::OnProcessMetaData();
|
||||
|
||||
uint8 reserved;
|
||||
Read(&reserved);
|
||||
Read(&reserved);
|
||||
Read(&reserved);
|
||||
|
||||
Read(&FieldSize);
|
||||
Read(&SampleCount);
|
||||
|
||||
SampleSizePtr aSampleSizePtr;
|
||||
uint8 EntrySize8;
|
||||
uint16 EntrySize16;
|
||||
|
||||
for (uint32 i=0;i<SampleCount;i++) {
|
||||
aSampleSizePtr = new SampleSizeEntry;
|
||||
|
||||
switch (FieldSize) {
|
||||
case 4:
|
||||
Read(&EntrySize8);
|
||||
// 2 values per byte
|
||||
aSampleSizePtr->EntrySize = (uint32)(EntrySize8);
|
||||
break;
|
||||
case 8:
|
||||
Read(&EntrySize8);
|
||||
// 1 value per byte
|
||||
aSampleSizePtr->EntrySize = (uint32)(EntrySize8);
|
||||
break;
|
||||
case 16:
|
||||
Read(&EntrySize16);
|
||||
// 1 value per 2 bytes
|
||||
aSampleSizePtr->EntrySize = (uint32)(EntrySize16);
|
||||
break;
|
||||
}
|
||||
|
||||
theSampleSizeArray[i] = aSampleSizePtr;
|
||||
}
|
||||
}
|
||||
|
||||
char *STZ2Atom::OnGetAtomName()
|
||||
{
|
||||
return "Compressed Sample Size Atom";
|
||||
}
|
||||
|
||||
uint32 STZ2Atom::getSizeForSample(uint32 pSampleNo)
|
||||
{
|
||||
// THIS CODE NEEDS SOME TESTING, never seen a STZ2 atom
|
||||
|
||||
uint32 index;
|
||||
|
||||
if (FieldSize == 4) {
|
||||
// 2 entries per array entry so Divide by 2
|
||||
index = pSampleNo / 2;
|
||||
if (index * 2 == pSampleNo) {
|
||||
// even so return low nibble
|
||||
return theSampleSizeArray[index]->EntrySize && 0x0000000f;
|
||||
} else {
|
||||
// odd so return high nibble
|
||||
return theSampleSizeArray[index]->EntrySize && 0x000000f0;
|
||||
}
|
||||
}
|
||||
|
||||
// Sample Array indexed by SampleNo
|
||||
return theSampleSizeArray[pSampleNo]->EntrySize;
|
||||
}
|
||||
|
||||
bool STZ2Atom::IsSingleSampleSize()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
STCOAtom::STCOAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize)
|
||||
STCOAtom::STCOAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
|
||||
{
|
||||
theHeader.NoEntries = 0;
|
||||
}
|
||||
@@ -834,8 +692,6 @@ void STCOAtom::OnProcessMetaData()
|
||||
{
|
||||
ChunkToOffset *aChunkToOffset;
|
||||
|
||||
FullAtom::OnProcessMetaData();
|
||||
|
||||
ReadArrayHeader(&theHeader);
|
||||
|
||||
for (uint32 i=0;i<theHeader.NoEntries;i++) {
|
||||
@@ -862,8 +718,8 @@ uint64 STCOAtom::getOffsetForChunk(uint32 pChunkID)
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
char msg[100]; sprintf(msg, "Bad Chunk ID %ld / %ld\n", pChunkID, theHeader.NoEntries);
|
||||
DEBUGGER(msg);
|
||||
char msg[100]; sprintf(msg, "Bad Chunk ID %ld / %ld\n", pChunkID, theHeader.NoEntries);
|
||||
DEBUGGER(msg);
|
||||
#endif
|
||||
|
||||
TRESPASS();
|
||||
@@ -898,7 +754,7 @@ char *ESDSAtom::OnGetAtomName()
|
||||
return "Extended Sample Description Atom";
|
||||
}
|
||||
|
||||
STSDAtom::STSDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize)
|
||||
STSDAtom::STSDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
|
||||
{
|
||||
theHeader.NoEntries = 0;
|
||||
}
|
||||
@@ -930,7 +786,7 @@ STSDAtom::~STSDAtom()
|
||||
|
||||
uint32 STSDAtom::getMediaComponentSubType()
|
||||
{
|
||||
return dynamic_cast<STBLAtom *>(getParent())->getMediaHandlerType();
|
||||
return dynamic_cast<STBLAtom *>(getParent())->getMediaComponentSubType();
|
||||
}
|
||||
|
||||
void STSDAtom::ReadSoundDescription()
|
||||
@@ -1089,9 +945,6 @@ void STSDAtom::ReadVideoDescription()
|
||||
|
||||
void STSDAtom::OnProcessMetaData()
|
||||
{
|
||||
|
||||
FullAtom::OnProcessMetaData();
|
||||
|
||||
ReadArrayHeader(&theHeader);
|
||||
|
||||
for (uint32 i=0;i<theHeader.NoEntries;i++) {
|
||||
@@ -1268,13 +1121,12 @@ void MDATAtom::OnProcessMetaData()
|
||||
|
||||
char *MDATAtom::OnGetAtomName()
|
||||
{
|
||||
printf("Offset %lld, Size %lld ",getAtomOffset(),getAtomSize() - 8);
|
||||
return "Media Data Atom";
|
||||
}
|
||||
|
||||
off_t MDATAtom::getEOF()
|
||||
{
|
||||
return getAtomOffset() + getAtomSize() - 8;
|
||||
return getStreamOffset() + getAtomSize();
|
||||
}
|
||||
|
||||
MINFAtom::MINFAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomContainer(pStream, pstreamOffset, patomType, patomSize)
|
||||
@@ -1294,9 +1146,9 @@ char *MINFAtom::OnGetAtomName()
|
||||
return "Quicktime Media Information Atom";
|
||||
}
|
||||
|
||||
uint32 MINFAtom::getMediaHandlerType()
|
||||
uint32 MINFAtom::getMediaComponentSubType()
|
||||
{
|
||||
return dynamic_cast<MDIAAtom *>(getParent())->getMediaHandlerType();
|
||||
return dynamic_cast<MDIAAtom *>(getParent())->getMediaComponentSubType();
|
||||
}
|
||||
|
||||
STBLAtom::STBLAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomContainer(pStream, pstreamOffset, patomType, patomSize)
|
||||
@@ -1316,9 +1168,9 @@ char *STBLAtom::OnGetAtomName()
|
||||
return "Quicktime Sample Table Atom";
|
||||
}
|
||||
|
||||
uint32 STBLAtom::getMediaHandlerType()
|
||||
uint32 STBLAtom::getMediaComponentSubType()
|
||||
{
|
||||
return dynamic_cast<MINFAtom *>(getParent())->getMediaHandlerType();
|
||||
return dynamic_cast<MINFAtom *>(getParent())->getMediaComponentSubType();
|
||||
}
|
||||
|
||||
DINFAtom::DINFAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomContainer(pStream, pstreamOffset, patomType, patomSize)
|
||||
@@ -1338,7 +1190,7 @@ char *DINFAtom::OnGetAtomName()
|
||||
return "Quicktime Data Information Atom";
|
||||
}
|
||||
|
||||
TKHDAtom::TKHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize)
|
||||
TKHDAtom::TKHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1348,11 +1200,15 @@ TKHDAtom::~TKHDAtom()
|
||||
|
||||
void TKHDAtom::OnProcessMetaData()
|
||||
{
|
||||
|
||||
FullAtom::OnProcessMetaData();
|
||||
Read(&Version);
|
||||
|
||||
if (getVersion() == 0) {
|
||||
if (Version == 0) {
|
||||
// Read into V0 header and convert to V1 Header
|
||||
tkhdV0 aHeaderV0;
|
||||
|
||||
Read(&aHeaderV0.Flags1);
|
||||
Read(&aHeaderV0.Flags2);
|
||||
Read(&aHeaderV0.Flags3);
|
||||
Read(&aHeaderV0.CreationTime);
|
||||
Read(&aHeaderV0.ModificationTime);
|
||||
Read(&aHeaderV0.TrackID);
|
||||
@@ -1363,23 +1219,26 @@ void TKHDAtom::OnProcessMetaData()
|
||||
Read(&aHeaderV0.AlternateGroup);
|
||||
Read(&aHeaderV0.Volume);
|
||||
Read(&aHeaderV0.Reserved3);
|
||||
|
||||
for (uint32 i=0;i<9;i++) {
|
||||
Read(&theHeader.MatrixStructure[i]);
|
||||
}
|
||||
|
||||
Read(aHeaderV0.MatrixStructure,36);
|
||||
Read(&aHeaderV0.TrackWidth);
|
||||
Read(&aHeaderV0.TrackHeight);
|
||||
|
||||
theHeader.Flags1 = aHeaderV0.Flags1;
|
||||
theHeader.Flags2 = aHeaderV0.Flags2;
|
||||
theHeader.Flags3 = aHeaderV0.Flags3;
|
||||
theHeader.Reserved1 = aHeaderV0.Reserved1;
|
||||
theHeader.Reserved2 = aHeaderV0.Reserved2;
|
||||
theHeader.Reserved3 = aHeaderV0.Reserved3;
|
||||
|
||||
for (uint32 i=0;i<36;i++) {
|
||||
theHeader.MatrixStructure[i] = aHeaderV0.MatrixStructure[i];
|
||||
}
|
||||
|
||||
// upconvert to V1 header
|
||||
theHeader.CreationTime = (uint64)(aHeaderV0.CreationTime);
|
||||
theHeader.ModificationTime = (uint64)(aHeaderV0.ModificationTime);
|
||||
theHeader.CreationTime = uint64(aHeaderV0.CreationTime);
|
||||
theHeader.ModificationTime = uint64(aHeaderV0.ModificationTime);
|
||||
theHeader.TrackID = aHeaderV0.TrackID;
|
||||
theHeader.Duration = (uint64)(aHeaderV0.Duration);
|
||||
theHeader.Duration = aHeaderV0.Duration;
|
||||
theHeader.Layer = aHeaderV0.Layer;
|
||||
theHeader.AlternateGroup = aHeaderV0.AlternateGroup;
|
||||
theHeader.Volume = aHeaderV0.Volume;
|
||||
@@ -1387,6 +1246,10 @@ void TKHDAtom::OnProcessMetaData()
|
||||
theHeader.TrackHeight = aHeaderV0.TrackHeight;
|
||||
|
||||
} else {
|
||||
// Read direct into V1 Header
|
||||
Read(&theHeader.Flags1);
|
||||
Read(&theHeader.Flags2);
|
||||
Read(&theHeader.Flags3);
|
||||
Read(&theHeader.CreationTime);
|
||||
Read(&theHeader.ModificationTime);
|
||||
Read(&theHeader.TrackID);
|
||||
@@ -1397,11 +1260,7 @@ void TKHDAtom::OnProcessMetaData()
|
||||
Read(&theHeader.AlternateGroup);
|
||||
Read(&theHeader.Volume);
|
||||
Read(&theHeader.Reserved3);
|
||||
|
||||
for (uint32 i=0;i<9;i++) {
|
||||
Read(&theHeader.MatrixStructure[i]);
|
||||
}
|
||||
|
||||
Read(theHeader.MatrixStructure,36);
|
||||
Read(&theHeader.TrackWidth);
|
||||
Read(&theHeader.TrackHeight);
|
||||
}
|
||||
@@ -1430,20 +1289,20 @@ char *MDIAAtom::OnGetAtomName()
|
||||
return "Quicktime Media Atom";
|
||||
}
|
||||
|
||||
uint32 MDIAAtom::getMediaHandlerType()
|
||||
uint32 MDIAAtom::getMediaComponentSubType()
|
||||
{
|
||||
// get child atom hdlr
|
||||
HDLRAtom *aHDLRAtom;
|
||||
aHDLRAtom = dynamic_cast<HDLRAtom *>(GetChildAtom(uint32('hdlr')));
|
||||
|
||||
if (aHDLRAtom) {
|
||||
return aHDLRAtom->getMediaHandlerType();
|
||||
return aHDLRAtom->getMediaComponentSubType();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MDHDAtom::MDHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize)
|
||||
MDHDAtom::MDHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1453,7 +1312,10 @@ MDHDAtom::~MDHDAtom()
|
||||
|
||||
void MDHDAtom::OnProcessMetaData()
|
||||
{
|
||||
FullAtom::OnProcessMetaData();
|
||||
Read(&theHeader.Version);
|
||||
Read(&theHeader.Flags1);
|
||||
Read(&theHeader.Flags2);
|
||||
Read(&theHeader.Flags3);
|
||||
Read(&theHeader.CreationTime);
|
||||
Read(&theHeader.ModificationTime);
|
||||
Read(&theHeader.TimeScale);
|
||||
@@ -1469,7 +1331,7 @@ char *MDHDAtom::OnGetAtomName()
|
||||
|
||||
bigtime_t MDHDAtom::getDuration()
|
||||
{
|
||||
return bigtime_t((theHeader.Duration * 1000000.0) / theHeader.TimeScale);
|
||||
return bigtime_t((uint64(theHeader.Duration) * 1000000L) / theHeader.TimeScale);
|
||||
}
|
||||
|
||||
uint32 MDHDAtom::getTimeScale()
|
||||
@@ -1477,30 +1339,27 @@ uint32 MDHDAtom::getTimeScale()
|
||||
return theHeader.TimeScale;
|
||||
}
|
||||
|
||||
HDLRAtom::HDLRAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize)
|
||||
HDLRAtom::HDLRAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
|
||||
{
|
||||
name = NULL;
|
||||
}
|
||||
|
||||
HDLRAtom::~HDLRAtom()
|
||||
{
|
||||
if (name) {
|
||||
free(name);
|
||||
}
|
||||
}
|
||||
|
||||
void HDLRAtom::OnProcessMetaData()
|
||||
{
|
||||
FullAtom::OnProcessMetaData();
|
||||
Read(&theHeader.Version);
|
||||
Read(&theHeader.Flags1);
|
||||
Read(&theHeader.Flags2);
|
||||
Read(&theHeader.Flags3);
|
||||
Read(&theHeader.ComponentType);
|
||||
Read(&theHeader.ComponentSubType);
|
||||
Read(&theHeader.ComponentManufacturer);
|
||||
Read(&theHeader.ComponentFlags);
|
||||
Read(&theHeader.ComponentFlagsMask);
|
||||
|
||||
name = (char *)(malloc(getBytesRemaining()));
|
||||
|
||||
Read(name,getBytesRemaining());
|
||||
|
||||
// Read Array of Strings?
|
||||
}
|
||||
|
||||
char *HDLRAtom::OnGetAtomName()
|
||||
@@ -1518,12 +1377,12 @@ bool HDLRAtom::IsAudioHandler()
|
||||
return (theHeader.ComponentSubType == 'soun');
|
||||
}
|
||||
|
||||
uint32 HDLRAtom::getMediaHandlerType()
|
||||
uint32 HDLRAtom::getMediaComponentSubType()
|
||||
{
|
||||
return theHeader.ComponentSubType;
|
||||
}
|
||||
|
||||
VMHDAtom::VMHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize)
|
||||
VMHDAtom::VMHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1533,11 +1392,15 @@ VMHDAtom::~VMHDAtom()
|
||||
|
||||
void VMHDAtom::OnProcessMetaData()
|
||||
{
|
||||
FullAtom::OnProcessMetaData();
|
||||
Read(&theHeader.GraphicsMode);
|
||||
Read(&theHeader.OpColourRed);
|
||||
Read(&theHeader.OpColourGreen);
|
||||
Read(&theHeader.OpColourBlue);
|
||||
vmhd aHeader;
|
||||
Read(&aHeader.Version);
|
||||
Read(&aHeader.Flags1);
|
||||
Read(&aHeader.Flags2);
|
||||
Read(&aHeader.Flags3);
|
||||
Read(&aHeader.GraphicsMode);
|
||||
Read(&aHeader.OpColourRed);
|
||||
Read(&aHeader.OpColourGreen);
|
||||
Read(&aHeader.OpColourBlue);
|
||||
}
|
||||
|
||||
char *VMHDAtom::OnGetAtomName()
|
||||
@@ -1545,7 +1408,7 @@ char *VMHDAtom::OnGetAtomName()
|
||||
return "Quicktime Video Media Header";
|
||||
}
|
||||
|
||||
SMHDAtom::SMHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize)
|
||||
SMHDAtom::SMHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1555,9 +1418,13 @@ SMHDAtom::~SMHDAtom()
|
||||
|
||||
void SMHDAtom::OnProcessMetaData()
|
||||
{
|
||||
FullAtom::OnProcessMetaData();
|
||||
Read(&theHeader.Balance);
|
||||
Read(&theHeader.Reserved);
|
||||
smhd aHeader;
|
||||
Read(&aHeader.Version);
|
||||
Read(&aHeader.Flags1);
|
||||
Read(&aHeader.Flags2);
|
||||
Read(&aHeader.Flags3);
|
||||
Read(&aHeader.Balance);
|
||||
Read(&aHeader.Reserved);
|
||||
}
|
||||
|
||||
char *SMHDAtom::OnGetAtomName()
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#define _MOV_PARSER_H
|
||||
|
||||
|
||||
#include "MOVAtom.h"
|
||||
|
||||
#include <File.h>
|
||||
#include <MediaDefs.h>
|
||||
#include <MediaFormats.h>
|
||||
@@ -33,10 +35,7 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "MOVAtom.h"
|
||||
|
||||
typedef CompTimeToSample* CompTimeToSamplePtr;
|
||||
typedef std::map<uint32, CompTimeToSamplePtr, std::less<uint32> > CompTimeToSampleArray;
|
||||
typedef SoundDescriptionV1* SoundDescPtr;
|
||||
typedef std::map<uint32, SoundDescPtr, std::less<uint32> > SoundDescArray;
|
||||
typedef VideoDescriptionV0* VideoDescPtr;
|
||||
@@ -49,11 +48,11 @@ typedef ChunkToOffset* ChunkToOffsetPtr;
|
||||
typedef std::map<uint32, ChunkToOffsetPtr, std::less<uint32> > ChunkToOffsetArray;
|
||||
typedef SyncSample* SyncSamplePtr;
|
||||
typedef std::map<uint32, SyncSamplePtr, std::less<uint32> > SyncSampleArray;
|
||||
typedef SampleSizeEntry* SampleSizePtr;
|
||||
typedef std::map<uint32, SampleSizePtr, std::less<uint32> > SampleSizeArray;
|
||||
typedef SampleSizeEntry* SampleSizeEntryPtr;
|
||||
typedef std::map<uint32, SampleSizeEntryPtr, std::less<uint32> > SampleSizeArray;
|
||||
|
||||
// Atom class for reading the movie header atom
|
||||
class MVHDAtom : public FullAtom {
|
||||
class MVHDAtom : public AtomBase {
|
||||
public:
|
||||
MVHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
|
||||
virtual ~MVHDAtom();
|
||||
@@ -122,22 +121,6 @@ private:
|
||||
uint8 *Buffer;
|
||||
};
|
||||
|
||||
// Atom class for reading the ftyp atom
|
||||
class FTYPAtom : public AtomBase {
|
||||
public:
|
||||
FTYPAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
|
||||
virtual ~FTYPAtom();
|
||||
void OnProcessMetaData();
|
||||
char *OnGetAtomName();
|
||||
|
||||
bool HasBrand(uint32 brand);
|
||||
private:
|
||||
uint32 major_brand;
|
||||
uint32 minor_version;
|
||||
uint32 compatable_brands[32]; // Should be infinite but we will settle for max 32
|
||||
uint32 total_brands;
|
||||
};
|
||||
|
||||
// Atom class for reading the wide atom
|
||||
class WIDEAtom : public AtomBase {
|
||||
public:
|
||||
@@ -169,42 +152,26 @@ public:
|
||||
};
|
||||
|
||||
// Atom class for reading the time to sample atom
|
||||
class STTSAtom : public FullAtom {
|
||||
class STTSAtom : public AtomBase {
|
||||
public:
|
||||
STTSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
|
||||
virtual ~STTSAtom();
|
||||
void OnProcessMetaData();
|
||||
char *OnGetAtomName();
|
||||
|
||||
uint64 getSUMCounts() { return SUMCounts; };
|
||||
bigtime_t getSUMDurations() { return SUMDurations; };
|
||||
uint32 getSampleForTime(bigtime_t pTime);
|
||||
uint64 getSUMCounts() {return SUMCounts;};
|
||||
uint64 getSUMDurations() {return SUMDurations;};
|
||||
uint32 getSampleForTime(uint32 pTime);
|
||||
uint32 getSampleForFrame(uint32 pFrame);
|
||||
void setFrameRate(float pFrameRate) { FrameRate = pFrameRate; };
|
||||
|
||||
private:
|
||||
array_header theHeader;
|
||||
TimeToSampleArray theTimeToSampleArray;
|
||||
bigtime_t SUMDurations;
|
||||
uint64 SUMDurations;
|
||||
uint64 SUMCounts;
|
||||
float FrameRate;
|
||||
};
|
||||
|
||||
// Atom class for reading the composition time to sample atom
|
||||
class CTTSAtom : public FullAtom {
|
||||
public:
|
||||
CTTSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
|
||||
virtual ~CTTSAtom();
|
||||
void OnProcessMetaData();
|
||||
char *OnGetAtomName();
|
||||
|
||||
private:
|
||||
array_header theHeader;
|
||||
CompTimeToSampleArray theCompTimeToSampleArray;
|
||||
};
|
||||
|
||||
// Atom class for reading the sample to chunk atom
|
||||
class STSCAtom : public FullAtom {
|
||||
class STSCAtom : public AtomBase {
|
||||
public:
|
||||
STSCAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
|
||||
virtual ~STSCAtom();
|
||||
@@ -220,7 +187,7 @@ private:
|
||||
};
|
||||
|
||||
// Atom class for reading the chunk to offset atom
|
||||
class STCOAtom : public FullAtom {
|
||||
class STCOAtom : public AtomBase {
|
||||
public:
|
||||
STCOAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
|
||||
virtual ~STCOAtom();
|
||||
@@ -240,7 +207,7 @@ private:
|
||||
};
|
||||
|
||||
// Atom class for reading the sync sample atom
|
||||
class STSSAtom : public FullAtom {
|
||||
class STSSAtom : public AtomBase {
|
||||
public:
|
||||
STSSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
|
||||
virtual ~STSSAtom();
|
||||
@@ -254,7 +221,7 @@ private:
|
||||
};
|
||||
|
||||
// Atom class for reading the sample size atom
|
||||
class STSZAtom : public FullAtom {
|
||||
class STSZAtom : public AtomBase {
|
||||
public:
|
||||
STSZAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
|
||||
virtual ~STSZAtom();
|
||||
@@ -264,27 +231,7 @@ public:
|
||||
uint32 getSizeForSample(uint32 pSampleNo);
|
||||
bool IsSingleSampleSize();
|
||||
private:
|
||||
uint32 SampleSize;
|
||||
uint32 SampleCount;
|
||||
|
||||
SampleSizeArray theSampleSizeArray;
|
||||
};
|
||||
|
||||
// Atom class for reading the sample size 2 atom
|
||||
class STZ2Atom : public FullAtom {
|
||||
public:
|
||||
STZ2Atom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
|
||||
virtual ~STZ2Atom();
|
||||
void OnProcessMetaData();
|
||||
char *OnGetAtomName();
|
||||
|
||||
uint32 getSizeForSample(uint32 pSampleNo);
|
||||
bool IsSingleSampleSize();
|
||||
private:
|
||||
uint32 SampleSize;
|
||||
uint32 SampleCount;
|
||||
uint8 FieldSize;
|
||||
|
||||
SampleSizeHeader theHeader;
|
||||
SampleSizeArray theSampleSizeArray;
|
||||
};
|
||||
|
||||
@@ -321,7 +268,7 @@ private:
|
||||
};
|
||||
|
||||
// Atom class for reading the sdst atom
|
||||
class STSDAtom : public FullAtom {
|
||||
class STSDAtom : public AtomBase {
|
||||
public:
|
||||
STSDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
|
||||
virtual ~STSDAtom();
|
||||
@@ -343,7 +290,7 @@ private:
|
||||
};
|
||||
|
||||
// Atom class for reading the track header atom
|
||||
class TKHDAtom : public FullAtom {
|
||||
class TKHDAtom : public AtomBase {
|
||||
public:
|
||||
TKHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
|
||||
virtual ~TKHDAtom();
|
||||
@@ -357,16 +304,18 @@ public:
|
||||
// 0x002 Track in Movie
|
||||
// 0x004 Track in Preview
|
||||
// 0x008 Track in Poster
|
||||
// It seems active tracks have all 4 flags set?
|
||||
|
||||
bool IsActive() {return ((getFlags3() && 0x01) || (getFlags3() && 0x0f));};
|
||||
bool IsActive() {return ((theHeader.Flags3 == 0x0f) || (theHeader.Flags3 == 0x03));};
|
||||
|
||||
private:
|
||||
tkhdV1 theHeader;
|
||||
uint8 Version;
|
||||
|
||||
};
|
||||
|
||||
// Atom class for reading the media header atom
|
||||
class MDHDAtom : public FullAtom {
|
||||
class MDHDAtom : public AtomBase {
|
||||
public:
|
||||
MDHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
|
||||
virtual ~MDHDAtom();
|
||||
@@ -383,27 +332,23 @@ private:
|
||||
};
|
||||
|
||||
// Atom class for reading the video media header atom
|
||||
class VMHDAtom : public FullAtom {
|
||||
class VMHDAtom : public AtomBase {
|
||||
public:
|
||||
VMHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
|
||||
virtual ~VMHDAtom();
|
||||
void OnProcessMetaData();
|
||||
char *OnGetAtomName();
|
||||
|
||||
bool IsCopyMode() {return theHeader.GraphicsMode == 0;};
|
||||
private:
|
||||
vmhd theHeader ;
|
||||
};
|
||||
|
||||
// Atom class for reading the sound media header atom
|
||||
class SMHDAtom : public FullAtom {
|
||||
class SMHDAtom : public AtomBase {
|
||||
public:
|
||||
SMHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
|
||||
virtual ~SMHDAtom();
|
||||
void OnProcessMetaData();
|
||||
char *OnGetAtomName();
|
||||
private:
|
||||
smhd theHeader;
|
||||
|
||||
};
|
||||
|
||||
// Atom class for reading the track atom
|
||||
@@ -416,15 +361,14 @@ public:
|
||||
void OnChildProcessingComplete();
|
||||
|
||||
bigtime_t Duration(uint32 TimeScale); // Return duration of track
|
||||
bigtime_t Duration() { return Duration(timescale); }
|
||||
uint32 FrameCount() { return framecount; };
|
||||
uint32 FrameCount() {return framecount;};
|
||||
bool IsVideo(); // Is this a video track
|
||||
bool IsAudio(); // Is this a audio track
|
||||
// GetAudioMetaData() // If this is a audio track get the audio meta data
|
||||
// GetVideoMetaData() // If this is a video track get the video meta data
|
||||
|
||||
bigtime_t getTimeForFrame(uint32 pFrame);
|
||||
uint32 getSampleForTime(bigtime_t pTime);
|
||||
uint32 getTimeForFrame(uint32 pFrame, uint32 pTimeScale);
|
||||
uint32 getSampleForTime(uint32 pTime);
|
||||
uint32 getSampleForFrame(uint32 pFrame);
|
||||
uint32 getChunkForSample(uint32 pSample, uint32 *pOffsetInChunk);
|
||||
uint64 getOffsetForChunk(uint32 pChunkID);
|
||||
@@ -433,15 +377,12 @@ public:
|
||||
uint32 getNoSamplesInChunk(uint32 pChunkID);
|
||||
uint32 getTotalChunks();
|
||||
|
||||
float getSampleRate();
|
||||
float getFrameRate();
|
||||
|
||||
bool IsSyncSample(uint32 pSampleNo);
|
||||
bool IsSingleSampleSize();
|
||||
bool IsActive();
|
||||
|
||||
uint32 getBytesPerSample();
|
||||
|
||||
|
||||
TKHDAtom *getTKHDAtom();
|
||||
MDHDAtom *getMDHDAtom();
|
||||
private:
|
||||
@@ -450,7 +391,6 @@ private:
|
||||
|
||||
uint32 framecount;
|
||||
uint32 bytespersample;
|
||||
uint32 timescale;
|
||||
};
|
||||
|
||||
// Atom class for reading the media container atom
|
||||
@@ -461,7 +401,7 @@ public:
|
||||
void OnProcessMetaData();
|
||||
char *OnGetAtomName();
|
||||
|
||||
uint32 getMediaHandlerType();
|
||||
uint32 getMediaComponentSubType();
|
||||
};
|
||||
|
||||
// Atom class for reading the media information atom
|
||||
@@ -472,7 +412,7 @@ public:
|
||||
void OnProcessMetaData();
|
||||
char *OnGetAtomName();
|
||||
|
||||
uint32 getMediaHandlerType();
|
||||
uint32 getMediaComponentSubType();
|
||||
};
|
||||
|
||||
// Atom class for reading the stbl atom
|
||||
@@ -483,7 +423,7 @@ public:
|
||||
void OnProcessMetaData();
|
||||
char *OnGetAtomName();
|
||||
|
||||
uint32 getMediaHandlerType();
|
||||
uint32 getMediaComponentSubType();
|
||||
};
|
||||
|
||||
// Atom class for reading the dinf atom
|
||||
@@ -518,7 +458,7 @@ private:
|
||||
};
|
||||
|
||||
// Atom class for reading the Media Handler atom
|
||||
class HDLRAtom : public FullAtom {
|
||||
class HDLRAtom : public AtomBase {
|
||||
public:
|
||||
HDLRAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
|
||||
virtual ~HDLRAtom();
|
||||
@@ -527,11 +467,26 @@ public:
|
||||
|
||||
bool IsVideoHandler();
|
||||
bool IsAudioHandler();
|
||||
uint32 getMediaHandlerType();
|
||||
uint32 getMediaComponentSubType();
|
||||
|
||||
private:
|
||||
hdlr theHeader;
|
||||
char *name;
|
||||
};
|
||||
|
||||
class FTYPAtom : public AtomBase {
|
||||
public:
|
||||
FTYPAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
|
||||
virtual ~FTYPAtom();
|
||||
void OnProcessMetaData();
|
||||
char *OnGetAtomName();
|
||||
bool HasBrand(uint32 brand);
|
||||
|
||||
private:
|
||||
uint32 major_brand;
|
||||
uint32 minor_version;
|
||||
uint32 compatable_brands[32]; // Should be infinite but we will settle for max 32
|
||||
uint32 total_brands;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -30,7 +30,6 @@ TRAKAtom::TRAKAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType,
|
||||
theMDHDAtom = NULL;
|
||||
framecount = 0;
|
||||
bytespersample = 0;
|
||||
timescale = 1;
|
||||
}
|
||||
|
||||
TRAKAtom::~TRAKAtom()
|
||||
@@ -79,20 +78,16 @@ bigtime_t TRAKAtom::Duration(uint32 TimeScale)
|
||||
return getMDHDAtom()->getDuration();
|
||||
}
|
||||
|
||||
return bigtime_t(getTKHDAtom()->getDuration() * 1000000.0) / TimeScale;
|
||||
return bigtime_t(getTKHDAtom()->getDuration() * 1000000L) / TimeScale;
|
||||
}
|
||||
|
||||
void TRAKAtom::OnChildProcessingComplete()
|
||||
{
|
||||
timescale = getMDHDAtom()->getTimeScale();
|
||||
|
||||
STTSAtom *aSTTSAtom = dynamic_cast<STTSAtom *>(GetChildAtom(uint32('stts'),0));
|
||||
|
||||
if (aSTTSAtom) {
|
||||
framecount = aSTTSAtom->getSUMCounts();
|
||||
aSTTSAtom->setFrameRate(getFrameRate());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Is this a video track
|
||||
@@ -109,46 +104,25 @@ bool TRAKAtom::IsAudio()
|
||||
return (GetChildAtom(uint32('smhd'),0) != NULL);
|
||||
}
|
||||
|
||||
// frames per us
|
||||
float TRAKAtom::getFrameRate()
|
||||
uint32 TRAKAtom::getTimeForFrame(uint32 pFrame, uint32 pTimeScale)
|
||||
{
|
||||
if (IsAudio()) {
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('stsd'),0);
|
||||
if (aAtomBase) {
|
||||
STSDAtom *aSTSDAtom = dynamic_cast<STSDAtom *>(aAtomBase);
|
||||
|
||||
SoundDescriptionV1 aAudioDescription = aSTSDAtom->getAsAudio();
|
||||
return (aAudioDescription.desc.SampleRate / 65536.0) / aAudioDescription.bytesPerFrame;
|
||||
}
|
||||
} else if (IsVideo()) {
|
||||
return (framecount * 1000000.0) / Duration();
|
||||
}
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('stts'),0);
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
if (aAtomBase) {
|
||||
STTSAtom *aSTTSAtom = dynamic_cast<STTSAtom *>(aAtomBase);
|
||||
|
||||
float TRAKAtom::getSampleRate()
|
||||
{
|
||||
// Only valid for Audio
|
||||
if (IsAudio()) {
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('stsd'),0);
|
||||
if (aAtomBase) {
|
||||
STSDAtom *aSTSDAtom = dynamic_cast<STSDAtom *>(aAtomBase);
|
||||
|
||||
SoundDescriptionV1 aAudioDescription = aSTSDAtom->getAsAudio();
|
||||
return aAudioDescription.desc.SampleRate / 65536;
|
||||
if (IsAudio()) {
|
||||
// Frame * SampleRate = Time
|
||||
} else if (IsVideo()) {
|
||||
// Frame * fps = Time
|
||||
return pFrame * ((aSTTSAtom->getSUMCounts() * 1000000L) / Duration(pTimeScale));
|
||||
}
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bigtime_t TRAKAtom::getTimeForFrame(uint32 pFrame)
|
||||
{
|
||||
return bigtime_t((pFrame * 1000000.0) / getFrameRate());
|
||||
}
|
||||
|
||||
uint32 TRAKAtom::getSampleForTime(bigtime_t pTime)
|
||||
uint32 TRAKAtom::getSampleForTime(uint32 pTime)
|
||||
{
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('stts'),0);
|
||||
|
||||
@@ -164,7 +138,7 @@ uint32 TRAKAtom::getSampleForFrame(uint32 pFrame)
|
||||
AtomBase *aAtomBase = GetChildAtom(uint32('stts'),0);
|
||||
|
||||
if (aAtomBase) {
|
||||
return (dynamic_cast<STTSAtom *>(aAtomBase))->getSampleForTime(getTimeForFrame(pFrame));
|
||||
return (dynamic_cast<STTSAtom *>(aAtomBase))->getSampleForFrame(pFrame);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -140,11 +140,6 @@ struct TimeToSample {
|
||||
uint32 Duration;
|
||||
};
|
||||
|
||||
struct CompTimeToSample {
|
||||
uint32 Count;
|
||||
uint32 Offset;
|
||||
};
|
||||
|
||||
struct SampleToChunk {
|
||||
uint32 FirstChunk;
|
||||
uint32 SamplesPerChunk;
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
#include "mov_reader.h"
|
||||
|
||||
#define TRACE_MOV_READER
|
||||
//#define TRACE_MOV_READER
|
||||
#ifdef TRACE_MOV_READER
|
||||
#define TRACE printf
|
||||
#else
|
||||
@@ -56,6 +56,7 @@ struct mov_cookie
|
||||
bool audio;
|
||||
|
||||
// audio only:
|
||||
off_t byte_pos;
|
||||
uint32 bytes_per_sec_rate;
|
||||
uint32 bytes_per_sec_scale;
|
||||
|
||||
@@ -66,7 +67,6 @@ struct mov_cookie
|
||||
uint32 frame_pos;
|
||||
uint32 frames_per_sec_rate;
|
||||
uint32 frames_per_sec_scale;
|
||||
uint32 frame_size;
|
||||
};
|
||||
|
||||
|
||||
@@ -175,12 +175,11 @@ movReader::AllocateCookie(int32 streamNumber, void **_cookie)
|
||||
|
||||
codecID = B_BENDIAN_TO_HOST_INT32(audio_format->compression);
|
||||
|
||||
// frame_count is actually sample_count for audio - makes media_player happy but david sad
|
||||
cookie->frame_count = theFileReader->getFrameCount(cookie->stream) * audio_format->FrameSize;
|
||||
cookie->frame_count = theFileReader->getAudioFrameCount(cookie->stream);
|
||||
cookie->duration = theFileReader->getAudioDuration(cookie->stream);
|
||||
cookie->frame_size = audio_format->FrameSize;
|
||||
|
||||
|
||||
cookie->audio = true;
|
||||
cookie->byte_pos = 0;
|
||||
|
||||
if (stream_header->scale && stream_header->rate) {
|
||||
cookie->bytes_per_sec_rate = stream_header->rate * audio_format->SampleSize * audio_format->NoOfChannels / 8;
|
||||
@@ -212,7 +211,6 @@ movReader::AllocateCookie(int32 streamNumber, void **_cookie)
|
||||
(audio_format->compression == AUDIO_RAW) ||
|
||||
(audio_format->compression == AUDIO_TWOS1) ||
|
||||
(audio_format->compression == AUDIO_TWOS2)) {
|
||||
|
||||
description.family = B_BEOS_FORMAT_FAMILY;
|
||||
description.u.beos.format = B_BEOS_FORMAT_RAW_AUDIO;
|
||||
if (B_OK != formats.GetFormatFor(description, format)) {
|
||||
@@ -352,8 +350,7 @@ movReader::AllocateCookie(int32 streamNumber, void **_cookie)
|
||||
|
||||
cookie->audio = false;
|
||||
cookie->line_count = theFileReader->MovMainHeader()->height;
|
||||
cookie->frame_size = 1;
|
||||
|
||||
|
||||
if (stream_header->scale && stream_header->rate) {
|
||||
cookie->frames_per_sec_rate = stream_header->rate;
|
||||
cookie->frames_per_sec_scale = stream_header->scale;
|
||||
@@ -478,14 +475,14 @@ movReader::Seek(void *cookie,
|
||||
if (seekTo & B_MEDIA_SEEK_TO_TIME) {
|
||||
// frame = (time * rate) / fps / 1000000LL
|
||||
*frame = ((*time * movcookie->frames_per_sec_rate) / (int64)movcookie->frames_per_sec_scale) / 1000000LL;
|
||||
movcookie->frame_pos = *frame / movcookie->frame_size;
|
||||
movcookie->frame_pos = *frame;
|
||||
TRACE("Time %Ld to Frame %Ld\n",*time, *frame);
|
||||
}
|
||||
|
||||
if (seekTo & B_MEDIA_SEEK_TO_FRAME) {
|
||||
// time = frame * 1000000LL * fps / rate
|
||||
*time = (*frame * 1000000LL * (int64)movcookie->frames_per_sec_scale) / movcookie->frames_per_sec_rate;
|
||||
movcookie->frame_pos = *frame / movcookie->frame_size;
|
||||
movcookie->frame_pos = *frame;
|
||||
TRACE("Frame %Ld to Time %Ld\n", *frame, *time);
|
||||
}
|
||||
|
||||
@@ -562,53 +559,47 @@ movReader::GetNextChunk(void *_cookie,
|
||||
{
|
||||
mov_cookie *cookie = (mov_cookie *)_cookie;
|
||||
|
||||
int64 start;
|
||||
uint32 size;
|
||||
bool keyframe;
|
||||
int64 start; uint32 size; bool keyframe;
|
||||
|
||||
if (!theFileReader->GetNextChunkInfo(cookie->stream, (cookie->frame_pos / cookie->frame_size), &start, &size, &keyframe)) {
|
||||
TRACE("%s LAST BUFFER : %d (%ld)\n",cookie->audio ? "AUDIO" : "VIDEO", cookie->stream, cookie->frame_pos);
|
||||
if (!theFileReader->GetNextChunkInfo(cookie->stream, cookie->frame_pos, &start, &size, &keyframe))
|
||||
return B_LAST_BUFFER_ERROR;
|
||||
}
|
||||
|
||||
if (cookie->buffer_size < size) {
|
||||
delete [] cookie->buffer;
|
||||
cookie->buffer_size = (size + 15) & ~15;
|
||||
cookie->buffer = new char [cookie->buffer_size];
|
||||
}
|
||||
|
||||
mediaHeader->start_time = bigtime_t(double(cookie->frame_pos) * 1000000.0 * double(cookie->frames_per_sec_scale)) / cookie->frames_per_sec_rate;
|
||||
|
||||
|
||||
if (cookie->audio) {
|
||||
TRACE("Audio");
|
||||
TRACE("Audio stream %d: chunk %ld expected start %lld Size %ld key %d\n",cookie->stream, cookie->frame_pos, start, size, keyframe);
|
||||
mediaHeader->type = B_MEDIA_ENCODED_AUDIO;
|
||||
mediaHeader->u.encoded_audio.buffer_flags = keyframe ? B_MEDIA_KEY_FRAME : 0;
|
||||
|
||||
// This will only work with raw audio I think.
|
||||
mediaHeader->start_time = (cookie->byte_pos * 1000000LL * cookie->bytes_per_sec_scale) / cookie->bytes_per_sec_rate;
|
||||
TRACE("Audio - Frames in Chunk %ld / Actual Start Time %Ld using byte_pos\n",theFileReader->getNoFramesInChunk(cookie->stream,cookie->frame_pos),mediaHeader->start_time);
|
||||
|
||||
// We should find the current frame position (ie first frame in chunk) then compute using fps
|
||||
cookie->frame_pos = theFileReader->getFirstFrameInChunk(cookie->stream,cookie->frame_pos);
|
||||
mediaHeader->start_time = (cookie->frame_pos * 1000000LL * (int64)cookie->frames_per_sec_scale) / cookie->frames_per_sec_rate;
|
||||
TRACE("Audio - Frames in Chunk %ld / Actual Start Time %Ld using frame_no %ld\n",theFileReader->getNoFramesInChunk(cookie->stream,cookie->frame_pos),mediaHeader->start_time, cookie->frame_pos);
|
||||
|
||||
cookie->byte_pos += size;
|
||||
} else {
|
||||
TRACE("Video");
|
||||
TRACE("Video stream %d: frame %ld start %lld Size %ld key %d\n",cookie->stream, cookie->frame_pos, start, size, keyframe);
|
||||
mediaHeader->start_time = (cookie->frame_pos * 1000000LL * (int64)cookie->frames_per_sec_scale) / cookie->frames_per_sec_rate;
|
||||
mediaHeader->type = B_MEDIA_ENCODED_VIDEO;
|
||||
mediaHeader->u.encoded_video.field_flags = keyframe ? B_MEDIA_KEY_FRAME : 0;
|
||||
mediaHeader->u.encoded_video.first_active_line = 0;
|
||||
mediaHeader->u.encoded_video.line_count = cookie->line_count;
|
||||
mediaHeader->u.encoded_video.field_number = 0;
|
||||
mediaHeader->u.encoded_video.field_sequence = cookie->frame_pos;
|
||||
}
|
||||
TRACE(" stream %d: frame %ld start time %.6f file pos %lld Size %ld key frame %s\n",cookie->stream, (cookie->frame_pos / cookie->frame_size), mediaHeader->start_time / 1000000.0, start, size, keyframe ? "true" : "false");
|
||||
|
||||
cookie->frame_pos += cookie->frame_size;
|
||||
|
||||
cookie->frame_pos++;
|
||||
TRACE("stream %d: start_time %.6f\n", cookie->stream, mediaHeader->start_time / 1000000.0);
|
||||
|
||||
*chunkBuffer = cookie->buffer;
|
||||
*chunkSize = size;
|
||||
|
||||
ssize_t bytesRead = theFileReader->Source()->ReadAt(start, cookie->buffer, size);
|
||||
if (bytesRead < B_OK)
|
||||
return bytesRead;
|
||||
|
||||
if (bytesRead < (ssize_t)size) {
|
||||
ERROR("Not enough bytes read asked for %ld got %ld\n", size, bytesRead);
|
||||
return B_LAST_BUFFER_ERROR;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
return (int)size == theFileReader->Source()->ReadAt(start, cookie->buffer, size) ? B_OK : B_LAST_BUFFER_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -69,7 +69,6 @@ MP4FileReader::IsEndOfData(off_t pPosition)
|
||||
if ((aAtomBase) && (aAtomBase->getAtomSize() > 8)) {
|
||||
MDATAtom *aMDATAtom = dynamic_cast<MDATAtom *>(aAtomBase);
|
||||
if (pPosition >= aMDATAtom->getAtomOffset() && pPosition <= aMDATAtom->getEOF()) {
|
||||
// printf("IsEndOfData %Ld,%Ld,%Ld\n",pPosition,aMDATAtom->getAtomOffset(),aMDATAtom->getEOF());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -635,7 +634,7 @@ MP4FileReader::GetNextChunkInfo(uint32 streamIndex, uint32 pFrameNo,
|
||||
*keyframe = IsKeyFrame(streamIndex, pFrameNo);
|
||||
}
|
||||
|
||||
// printf("frame %ld start %Ld, size %ld, eof %s, eod %s\n",pFrameNo,*start,*size, IsEndOfFile(*start + *size) ? "true" : "false", IsEndOfData(*start + *size) ? "true" : "false");
|
||||
// printf("start %Ld, size %ld, eof %s, eod %s\n",*start,*size, IsEndOfFile(*start + *size) ? "true" : "false", IsEndOfData(*start + *size) ? "true" : "false");
|
||||
|
||||
// TODO need a better method for detecting End of Data Note ChunkSize of 0 seems to be it.
|
||||
if (IsEndOfFile(*start + *size) || IsEndOfData(*start + *size)) {
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "WavReaderPlugin.h"
|
||||
#include "RawFormats.h"
|
||||
|
||||
#define TRACE_WAVE_READER
|
||||
//#define TRACE_WAVE_READER
|
||||
#ifdef TRACE_WAVE_READER
|
||||
#define TRACE printf
|
||||
#else
|
||||
@@ -137,11 +137,7 @@ WavReader::Sniff(int32 *streamCount)
|
||||
}
|
||||
|
||||
format_struct format;
|
||||
wave_format_ex wav_format;
|
||||
format_struct_extensible format_ext;
|
||||
mpeg1_wav_format mpeg1_format;
|
||||
mpeg3_wav_format mpeg3_format;
|
||||
|
||||
fact_struct fact;
|
||||
|
||||
// read all chunks and search for "fact", "fmt" (normal or extensible) and "data"
|
||||
@@ -150,9 +146,6 @@ WavReader::Sniff(int32 *streamCount)
|
||||
bool foundFmt = false;
|
||||
bool foundFmtExt = false;
|
||||
bool foundData = false;
|
||||
bool foundMPEG1 = false;
|
||||
bool foundMPEG3 = false;
|
||||
|
||||
while (pos + sizeof(chunk_struct) <= fFileSize) {
|
||||
chunk_struct chunk;
|
||||
if (sizeof(chunk) != Source()->ReadAt(pos, &chunk, sizeof(chunk))) {
|
||||
@@ -166,43 +159,12 @@ WavReader::Sniff(int32 *streamCount)
|
||||
}
|
||||
switch (UINT32(chunk.fourcc)) {
|
||||
case FOURCC('f','m','t',' '):
|
||||
// So what do we have a std format structure, a wav_format structure or a extended structure
|
||||
if (UINT32(chunk.len) >= sizeof(wav_format)) {
|
||||
// Read both format and wav format
|
||||
if (sizeof(format) != Source()->ReadAt(pos, &format, sizeof(format))) {
|
||||
ERROR("WavReader::Sniff: format chunk reading failed\n");
|
||||
break;
|
||||
}
|
||||
if (sizeof(wav_format) != Source()->ReadAt(pos, &wav_format, sizeof(wav_format))) {
|
||||
ERROR("WavReader::Sniff: format chunk reading failed\n");
|
||||
break;
|
||||
}
|
||||
foundFmt = true;
|
||||
|
||||
if (UINT16(wav_format.extra_size) == 12) {
|
||||
// MPEG3 WAV FORMAT Structure
|
||||
if (sizeof(mpeg3_format) != Source()->ReadAt(pos, &mpeg3_format, sizeof(mpeg3_format))) {
|
||||
ERROR("WavReader::Sniff: format chunk reading failed\n");
|
||||
break;
|
||||
}
|
||||
foundMPEG3 = true;
|
||||
}
|
||||
if (UINT16(wav_format.extra_size) == 22) {
|
||||
// MPEG1 WAV FORMAT Structure
|
||||
if (sizeof(mpeg1_format) != Source()->ReadAt(pos, &mpeg1_format, sizeof(mpeg1_format))) {
|
||||
ERROR("WavReader::Sniff: format chunk reading failed\n");
|
||||
break;
|
||||
}
|
||||
foundMPEG1 = true;
|
||||
}
|
||||
|
||||
} else if (UINT32(chunk.len) >= sizeof(format)) {
|
||||
if (UINT32(chunk.len) >= sizeof(format)) {
|
||||
if (sizeof(format) != Source()->ReadAt(pos, &format, sizeof(format))) {
|
||||
ERROR("WavReader::Sniff: format chunk reading failed\n");
|
||||
break;
|
||||
}
|
||||
foundFmt = true;
|
||||
|
||||
if (UINT32(chunk.len) >= sizeof(format_ext) && UINT16(format.format_tag) == 0xfffe) {
|
||||
if (sizeof(format_ext) != Source()->ReadAt(pos, &format_ext, sizeof(format_ext))) {
|
||||
ERROR("WavReader::Sniff: format extensible chunk reading failed\n");
|
||||
@@ -269,28 +231,6 @@ WavReader::Sniff(int32 *streamCount)
|
||||
if (foundFact) {
|
||||
TRACE(" sample_length %ld\n", UINT32(fact.sample_length));
|
||||
}
|
||||
|
||||
if (foundMPEG1) {
|
||||
TRACE(" layer %d\n", UINT16(mpeg1_format.head_layer));
|
||||
TRACE(" bitrate %ld\n", UINT32(mpeg1_format.head_bitrate));
|
||||
TRACE(" mode %d\n", UINT16(mpeg1_format.head_mode));
|
||||
TRACE(" mode ext %d\n", UINT16(mpeg1_format.head_mode_ext));
|
||||
TRACE(" emphisis %d\n", UINT16(mpeg1_format.head_emphasis));
|
||||
TRACE(" flags %d\n", UINT16(mpeg1_format.head_flags));
|
||||
TRACE(" pts low %ld\n", UINT32(mpeg1_format.pts_low));
|
||||
TRACE(" pts high %ld\n", UINT32(mpeg1_format.pts_high));
|
||||
}
|
||||
|
||||
if (foundMPEG3) {
|
||||
TRACE(" id %d\n", UINT16(mpeg3_format.id));
|
||||
TRACE(" flags %ld\n", UINT32(mpeg3_format.flags));
|
||||
TRACE(" block size %d\n", UINT16(mpeg3_format.block_size));
|
||||
TRACE(" frames per block %d\n", UINT16(mpeg3_format.frames_per_block));
|
||||
TRACE(" codec delay %d\n", UINT16(mpeg3_format.codec_delay));
|
||||
fBufferSize = mpeg3_format.block_size;
|
||||
} else {
|
||||
fBufferSize = BUFFER_SIZE;
|
||||
}
|
||||
|
||||
fMetaData.extra_size = 0;
|
||||
fMetaData.channels = UINT16(format.channels);
|
||||
@@ -358,7 +298,7 @@ WavReader::AllocateCookie(int32 streamNumber, void **cookie)
|
||||
data->position = 0;
|
||||
data->datasize = fDataSize;
|
||||
data->fps = fMetaData.samples_per_sec;
|
||||
data->buffersize = (fBufferSize / fMetaData.block_align) * fMetaData.block_align;
|
||||
data->buffersize = (BUFFER_SIZE / fMetaData.block_align) * fMetaData.block_align;
|
||||
data->buffer = malloc(data->buffersize);
|
||||
data->framecount = fFrameCount ? fFrameCount : (8 * fDataSize) / (fMetaData.channels * fMetaData.bits_per_sample);
|
||||
data->raw = fMetaData.format_tag == 0x0001;
|
||||
|
||||
@@ -71,7 +71,6 @@ private:
|
||||
|
||||
int64 fFrameCount;
|
||||
int32 fFrameRate;
|
||||
uint16 fBufferSize;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -56,40 +56,7 @@ struct wave_format_ex {
|
||||
uint16 block_align;
|
||||
uint16 bits_per_sample;
|
||||
uint16 extra_size;
|
||||
};
|
||||
|
||||
struct mpeg3_wav_format {
|
||||
uint16 format_tag;
|
||||
uint16 channels;
|
||||
uint32 samples_per_sec;
|
||||
uint32 avg_bytes_per_sec;
|
||||
uint16 block_align;
|
||||
uint16 bits_per_sample;
|
||||
uint16 extra_size;
|
||||
uint16 id;
|
||||
uint32 flags;
|
||||
uint16 block_size;
|
||||
uint16 frames_per_block;
|
||||
uint16 codec_delay;
|
||||
};
|
||||
|
||||
struct mpeg1_wav_format {
|
||||
uint16 format_tag;
|
||||
uint16 channels;
|
||||
uint32 samples_per_sec;
|
||||
uint32 avg_bytes_per_sec;
|
||||
uint16 block_align;
|
||||
uint16 bits_per_sample;
|
||||
uint16 extra_size;
|
||||
uint16 head_layer;
|
||||
uint32 head_bitrate;
|
||||
uint16 head_mode;
|
||||
uint16 head_mode_ext;
|
||||
uint16 head_emphasis;
|
||||
uint16 head_flags;
|
||||
uint32 pts_low;
|
||||
uint32 pts_high;
|
||||
};
|
||||
} _PACKED;
|
||||
|
||||
struct format_struct_extensible
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user