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