* GCC 4 build fixes

* Some minor cleanup towards our style guide, but this could need
  much more work.
* Better error reporting in GetNextChunk() in case of an read error.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17541 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2006-05-22 18:08:13 +00:00
parent 3ad603ace4
commit 42c1d42429
6 changed files with 273 additions and 195 deletions

View File

@ -27,8 +27,8 @@
#include <SupportDefs.h>
// Std Headers
#include <map.h>
#include <map>
struct ChunkIndex {
uint32 stream;

View File

@ -25,15 +25,15 @@
#ifndef _MP4_ATOM_H
#define _MP4_ATOM_H
#include "MP4Structs.h"
#include <File.h>
#include <MediaDefs.h>
#include <MediaFormats.h>
#include <SupportDefs.h>
// Std Headers
#include <map.h>
#include <map>
#include "MP4Structs.h"
/*
AtomBase

View File

@ -22,38 +22,45 @@
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream.h>
#include <DataIO.h>
#include <SupportKit.h>
#include "MP4Parser.h"
#include "MP4FileReader.h"
#include <DataIO.h>
#include <SupportKit.h>
#include <iostream>
extern AtomBase *getAtom(BPositionIO *pStream);
MP4FileReader::MP4FileReader(BPositionIO *pStream)
{
theStream = pStream;
// Find Size of Stream, need to rethink this for non seekable streams
theStream->Seek(0,SEEK_END);
StreamSize = theStream->Position();
theStream->Seek(0,SEEK_SET);
TotalChildren = 0;
theMVHDAtom = NULL;
}
MP4FileReader::~MP4FileReader()
{
theStream = NULL;
theMVHDAtom = NULL;
}
bool MP4FileReader::IsEndOfData(off_t pPosition)
bool
MP4FileReader::IsEndOfData(off_t pPosition)
{
AtomBase *aAtomBase;
AtomBase* aAtomBase;
for (uint32 index=0;index<CountChildAtoms('mdat');index++) {
aAtomBase = GetChildAtom(uint32('mdat'),index);
@ -62,32 +69,40 @@ AtomBase *aAtomBase;
return pPosition >= aMdatAtom->getEOF();
}
}
return true;
}
bool MP4FileReader::IsEndOfFile(off_t pPosition)
bool
MP4FileReader::IsEndOfFile(off_t position)
{
return (pPosition >= StreamSize);
return (position >= StreamSize);
}
bool MP4FileReader::IsEndOfFile()
bool
MP4FileReader::IsEndOfFile()
{
return (theStream->Position() >= StreamSize);
return theStream->Position() >= StreamSize;
}
bool MP4FileReader::AddChild(AtomBase *pChildAtom)
bool
MP4FileReader::AddChild(AtomBase *childAtom)
{
if (pChildAtom) {
atomChildren[TotalChildren++] = pChildAtom;
if (childAtom) {
atomChildren[TotalChildren++] = childAtom;
return true;
}
return false;
}
AtomBase *MP4FileReader::GetChildAtom(uint32 patomType, uint32 offset)
AtomBase *
MP4FileReader::GetChildAtom(uint32 patomType, uint32 offset)
{
for (uint32 i=0;i<TotalChildren;i++) {
for (uint32 i = 0; i < TotalChildren; i++) {
if (atomChildren[i]->IsType(patomType)) {
// found match, skip if offset non zero.
if (offset == 0) {
@ -110,7 +125,9 @@ AtomBase *MP4FileReader::GetChildAtom(uint32 patomType, uint32 offset)
return NULL;
}
uint32 MP4FileReader::CountChildAtoms(uint32 patomType)
uint32
MP4FileReader::CountChildAtoms(uint32 patomType)
{
uint32 count = 0;
@ -120,9 +137,11 @@ uint32 MP4FileReader::CountChildAtoms(uint32 patomType)
return count;
}
MVHDAtom *MP4FileReader::getMVHDAtom()
MVHDAtom*
MP4FileReader::getMVHDAtom()
{
AtomBase *aAtomBase;
AtomBase *aAtomBase;
if (theMVHDAtom == NULL) {
aAtomBase = GetChildAtom(uint32('mvhd'));
@ -133,9 +152,11 @@ AtomBase *aAtomBase;
return theMVHDAtom;
}
void MP4FileReader::BuildSuperIndex()
void
MP4FileReader::BuildSuperIndex()
{
AtomBase *aAtomBase;
AtomBase *aAtomBase;
for (uint32 stream=0;stream<getStreamCount();stream++) {
aAtomBase = GetChildAtom(uint32('trak'),stream);
@ -146,7 +167,7 @@ AtomBase *aAtomBase;
}
}
}
// Add end of file to index
aAtomBase = GetChildAtom(uint32('mdat'),0);
if (aAtomBase) {
@ -155,147 +176,160 @@ AtomBase *aAtomBase;
}
}
uint32 MP4FileReader::getMovieTimeScale()
uint32
MP4FileReader::getMovieTimeScale()
{
return getMVHDAtom()->getTimeScale();
}
bigtime_t MP4FileReader::getMovieDuration()
bigtime_t
MP4FileReader::getMovieDuration()
{
return ((bigtime_t(getMVHDAtom()->getDuration()) * 1000000L) / getMovieTimeScale());
return (bigtime_t(getMVHDAtom()->getDuration()) * 1000000L)
/ getMovieTimeScale();
}
uint32 MP4FileReader::getStreamCount()
uint32
MP4FileReader::getStreamCount()
{
// count the number of tracks in the file
return (CountChildAtoms(uint32('trak')));
return CountChildAtoms(uint32('trak'));
}
bigtime_t MP4FileReader::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));
}
bigtime_t
MP4FileReader::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 MP4FileReader::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));
}
bigtime_t
MP4FileReader::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 MP4FileReader::getMaxDuration()
bigtime_t
MP4FileReader::getMaxDuration()
{
AtomBase *aAtomBase;
int32 video_index,audio_index;
video_index = -1;
audio_index = -1;
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);
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);
audioIndex = int32(i);
}
if (dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo()) {
video_index = int32(i);
videoIndex = int32(i);
}
}
}
if ((video_index >= 0) && (audio_index >= 0)) {
return MAX(getVideoDuration(video_index),getAudioDuration(audio_index));
if (videoIndex >= 0 && audioIndex >= 0) {
return max_c(getVideoDuration(videoIndex),
getAudioDuration(audioIndex));
}
if ((video_index < 0) && (audio_index >= 0)) {
return getAudioDuration(audio_index);
if (videoIndex < 0 && audioIndex >= 0) {
return getAudioDuration(audioIndex);
}
if ((video_index >= 0) && (audio_index < 0)) {
return getVideoDuration(video_index);
if (videoIndex >= 0 && audioIndex < 0) {
return getVideoDuration(videoIndex);
}
return 0;
}
uint32 MP4FileReader::getVideoFrameCount(uint32 stream_index)
uint32
MP4FileReader::getVideoFrameCount(uint32 streamIndex)
{
AtomBase *aAtomBase;
aAtomBase = GetChildAtom(uint32('trak'),stream_index);
if ((aAtomBase) && (dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo())) {
AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex);
if (aAtomBase && dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo())
return dynamic_cast<TRAKAtom *>(aAtomBase)->FrameCount();
}
return 1;
}
uint32 MP4FileReader::getAudioFrameCount(uint32 stream_index)
uint32
MP4FileReader::getAudioFrameCount(uint32 streamIndex)
{
if (IsAudio(stream_index)) {
return uint32(((getAudioDuration(stream_index) * AudioFormat(stream_index)->SampleRate) / 1000000L) + 0.5);
if (IsAudio(streamIndex)) {
return uint32(((getAudioDuration(streamIndex)
* AudioFormat(streamIndex)->SampleRate) / 1000000L) + 0.5);
}
return 0;
}
bool MP4FileReader::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
bool
MP4FileReader::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 MP4FileReader::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
bool
MP4FileReader::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 MP4FileReader::getFirstFrameInChunk(uint32 stream_index, uint32 pChunkID)
uint32
MP4FileReader::getFirstFrameInChunk(uint32 streamIndex, uint32 pChunkID)
{
// Find Track
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex);
if (aAtomBase) {
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
return aTrakAtom->getFirstSampleInChunk(pChunkID);
}
return 0;
}
uint32 MP4FileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo)
uint32
MP4FileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo)
{
// Find Track
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
@ -303,10 +337,9 @@ uint32 MP4FileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo)
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
uint32 ChunkNo = 1;
if (IsAudio(stream_index)) {
ChunkNo = pFrameNo;
}
if (IsAudio(stream_index))
ChunkNo = pFrameNo;
if (IsVideo(stream_index)) {
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
@ -320,7 +353,9 @@ uint32 MP4FileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo)
return 0;
}
uint64 MP4FileReader::getOffsetForFrame(uint32 stream_index, uint32 pFrameNo)
uint64
MP4FileReader::getOffsetForFrame(uint32 stream_index, uint32 pFrameNo)
{
// Find Track
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
@ -336,7 +371,6 @@ uint64 MP4FileReader::getOffsetForFrame(uint32 stream_index, uint32 pFrameNo)
}
if (IsVideo(stream_index)) {
if (pFrameNo < aTrakAtom->FrameCount()) {
// Get Sample for Frame
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
@ -365,11 +399,13 @@ uint64 MP4FileReader::getOffsetForFrame(uint32 stream_index, uint32 pFrameNo)
}
}
}
return 0;
}
status_t MP4FileReader::ParseFile()
status_t
MP4FileReader::ParseFile()
{
AtomBase *aChild;
while (IsEndOfFile() == false) {
@ -389,7 +425,9 @@ status_t MP4FileReader::ParseFile()
return B_OK;
}
const mp4_main_header *MP4FileReader::MovMainHeader()
const mp4_main_header*
MP4FileReader::MovMainHeader()
{
// Fill In theMainHeader
// uint32 micro_sec_per_frame;
@ -409,10 +447,10 @@ const mp4_main_header *MP4FileReader::MovMainHeader()
theMainHeader.flags = 0;
theMainHeader.initial_frames = 0;
while ( videoStream < theMainHeader.streams ) {
if (IsVideo(videoStream) && IsActive(videoStream)) {
while (videoStream < theMainHeader.streams) {
if (IsVideo(videoStream) && IsActive(videoStream))
break;
}
videoStream++;
}
@ -429,17 +467,18 @@ const mp4_main_header *MP4FileReader::MovMainHeader()
theMainHeader.suggested_buffer_size = theMainHeader.width * theMainHeader.height * VideoFormat(videoStream)->bit_count / 8;
theMainHeader.micro_sec_per_frame = uint32(1000000.0 / VideoFormat(videoStream)->FrameRate);
}
theMainHeader.padding_granularity = 0;
theMainHeader.max_bytes_per_sec = 0;
return &theMainHeader;
}
const AudioMetaData *MP4FileReader::AudioFormat(uint32 stream_index, size_t *size = 0)
const AudioMetaData *
MP4FileReader::AudioFormat(uint32 stream_index, size_t *size)
{
if (IsAudio(stream_index)) {
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
if (aAtomBase) {
@ -470,22 +509,21 @@ const AudioMetaData *MP4FileReader::AudioFormat(uint32 stream_index, size_t *
return NULL;
}
const VideoMetaData *MP4FileReader::VideoFormat(uint32 stream_index)
const VideoMetaData*
MP4FileReader::VideoFormat(uint32 stream_index)
{
if (IsVideo(stream_index)) {
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
if (aAtomBase) {
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
aAtomBase = aTrakAtom->GetChildAtom(uint32('stsd'),0);
if (aAtomBase) {
STSDAtom *aSTSDAtom = dynamic_cast<STSDAtom *>(aAtomBase);
VideoDescription aVideoDescription = aSTSDAtom->getAsVideo();
theVideo.compression = aVideoDescription.codecid;
theVideo.width = aVideoDescription.theVideoSampleEntry.Width;
@ -506,17 +544,19 @@ const VideoMetaData *MP4FileReader::VideoFormat(uint32 stream_index)
STTSAtom *aSTTSAtom = dynamic_cast<STTSAtom *>(aAtomBase);
theVideo.FrameRate = ((aSTTSAtom->getSUMCounts() * 1000000.0L) / aTrakAtom->Duration(1));
return &theVideo;
}
}
}
}
return NULL;
}
const mp4_stream_header *MP4FileReader::StreamFormat(uint32 stream_index)
const mp4_stream_header*
MP4FileReader::StreamFormat(uint32 stream_index)
{
// Fill In a Stream Header
theStreamHeader.length = 0;
@ -530,7 +570,7 @@ const mp4_stream_header *MP4FileReader::StreamFormat(uint32 stream_index)
theStreamHeader.scale = 1000000L;
theStreamHeader.length = getVideoFrameCount(stream_index);
}
if (IsAudio(stream_index)) {
theStreamHeader.rate = uint32(AudioFormat(stream_index)->SampleRate);
theStreamHeader.scale = 1;
@ -538,26 +578,27 @@ const mp4_stream_header *MP4FileReader::StreamFormat(uint32 stream_index)
theStreamHeader.sample_size = AudioFormat(stream_index)->SampleSize;
theStreamHeader.suggested_buffer_size = theStreamHeader.rate * theStreamHeader.sample_size;
}
return &theStreamHeader;
}
uint32 MP4FileReader::getChunkSize(uint32 stream_index, uint32 pFrameNo)
uint32
MP4FileReader::getChunkSize(uint32 stream_index, uint32 pFrameNo)
{
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
if (aAtomBase) {
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
if (IsAudio(stream_index)) {
// We read audio in chunk by chunk so chunk size is chunk size
uint32 ChunkNo = pFrameNo;
off_t Chunk_Start = aTrakAtom->getOffsetForChunk(ChunkNo);
uint32 ChunkSize = theChunkSuperIndex.getChunkSize(stream_index,ChunkNo,Chunk_Start);
return ChunkSize;
}
if (IsVideo(stream_index)) {
if (pFrameNo < aTrakAtom->FrameCount()) {
// We read video in Sample by Sample so we use get Sample Size
@ -565,18 +606,19 @@ uint32 MP4FileReader::getChunkSize(uint32 stream_index, uint32 pFrameNo)
return aTrakAtom->getSizeForSample(SampleNo);
}
}
}
return 0;
}
bool MP4FileReader::IsKeyFrame(uint32 stream_index, uint32 pFrameNo)
bool
MP4FileReader::IsKeyFrame(uint32 stream_index, uint32 pFrameNo)
{
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
if (aAtomBase) {
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
return aTrakAtom->IsSyncSample(SampleNo);
}
@ -584,38 +626,44 @@ bool MP4FileReader::IsKeyFrame(uint32 stream_index, uint32 pFrameNo)
return false;
}
bool MP4FileReader::GetNextChunkInfo(uint32 stream_index, uint32 pFrameNo, off_t *start, uint32 *size, bool *keyframe)
bool
MP4FileReader::GetNextChunkInfo(uint32 stream_index, uint32 pFrameNo,
off_t *start, uint32 *size, bool *keyframe)
{
*start = getOffsetForFrame(stream_index, pFrameNo);
*size = getChunkSize(stream_index, pFrameNo);
if ((*start > 0) && (*size > 0)) {
*keyframe = IsKeyFrame(stream_index, pFrameNo);
}
// TODO need a better method for detecting End of Data Note ChunkSize of 0 seems to be it.
return ((*start > 0) && (*size > 0) && !(IsEndOfFile(*start + *size)) && !(IsEndOfData(*start + *size)));
return *start > 0 && *size > 0 && !IsEndOfFile(*start + *size)
&& !IsEndOfData(*start + *size);
}
bool MP4FileReader::IsActive(uint32 stream_index)
bool
MP4FileReader::IsActive(uint32 stream_index)
{
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
if (aAtomBase) {
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
return aTrakAtom->IsActive();
}
return false;
}
/* static */
bool MP4FileReader::IsSupported(BPositionIO *source)
bool
MP4FileReader::IsSupported(BPositionIO *source)
{
AtomBase *aAtom;
aAtom = getAtom(source);
if (aAtom) {
return (aAtom->IsKnown());
}
AtomBase *aAtom = getAtom(source);
if (aAtom)
return aAtom->IsKnown();
return false;
}

View File

@ -31,7 +31,7 @@
#include <SupportDefs.h>
// Std Headers
#include <map.h>
#include <map>
#include "MP4Atom.h"

View File

@ -22,6 +22,12 @@
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MP4_STRUCTS_H
#define MP4_STRUCTS_H
#include <SupportDefs.h>
#define AUDIO_NONE 'NONE'
#define AUDIO_RAW 'raw '
@ -33,8 +39,7 @@
#define AUDIO_MPEG3_CBR 0x6D730055
// this is all from the avi reader. we rework it for mp4
struct mp4_main_header
{
struct mp4_main_header {
uint32 micro_sec_per_frame;
uint32 max_bytes_per_sec;
uint32 padding_granularity;
@ -273,3 +278,5 @@ struct VideoDescription {
uint8 *theVOL;
size_t VOLSize;
};
#endif // MP4_STRUCTS_H

View File

@ -22,29 +22,33 @@
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <DataIO.h>
#include <StopWatch.h>
#include <ByteOrder.h>
#include <InterfaceDefs.h>
#include <MediaFormats.h>
#include "RawFormats.h"
#include "mp4_reader.h"
#include "RawFormats.h"
#include <ByteOrder.h>
#include <DataIO.h>
#include <InterfaceDefs.h>
#include <MediaFormats.h>
#include <StopWatch.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRACE_MP4_READER
#ifdef TRACE_MP4_READER
#define TRACE printf
# define TRACE printf
#else
#define TRACE(a...)
# define TRACE(a...)
#endif
#define ERROR(a...) fprintf(stderr, a)
struct mp4_cookie
{
struct mp4_cookie {
unsigned stream;
char * buffer;
unsigned buffer_size;
@ -77,17 +81,20 @@ mp4Reader::mp4Reader()
TRACE("mp4Reader::mp4Reader\n");
}
mp4Reader::~mp4Reader()
{
delete theFileReader;
}
const char *
mp4Reader::Copyright()
{
return "MPEG4 & libMP4, " B_UTF8_COPYRIGHT " by David McPaul";
}
status_t
mp4Reader::Sniff(int32 *streamCount)
{
@ -118,13 +125,14 @@ mp4Reader::Sniff(int32 *streamCount)
return B_OK;
}
void
mp4Reader::GetFileFormatInfo(media_file_format *mff)
{
mff->capabilities = media_file_format::B_READABLE
| media_file_format::B_KNOWS_ENCODED_VIDEO
| media_file_format::B_KNOWS_ENCODED_AUDIO
| media_file_format::B_IMPERFECTLY_SEEKABLE;
mff->capabilities = media_file_format::B_READABLE
| media_file_format::B_KNOWS_ENCODED_VIDEO
| media_file_format::B_KNOWS_ENCODED_AUDIO
| media_file_format::B_IMPERFECTLY_SEEKABLE;
mff->family = B_QUICKTIME_FORMAT_FAMILY;
mff->version = 100;
strcpy(mff->mime_type, "video/quicktime");
@ -133,6 +141,7 @@ mp4Reader::GetFileFormatInfo(media_file_format *mff)
strcpy(mff->pretty_name, "MPEG-4 (MP4) file format");
}
status_t
mp4Reader::AllocateCookie(int32 streamNumber, void **_cookie)
{
@ -180,40 +189,46 @@ mp4Reader::AllocateCookie(int32 streamNumber, void **_cookie)
cookie->chunk_pos = 1;
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;
cookie->bytes_per_sec_scale = stream_header->scale;
cookie->frames_per_sec_rate = stream_header->rate;
cookie->frames_per_sec_scale = stream_header->scale;
TRACE("bytes_per_sec_rate %ld, bytes_per_sec_scale %ld (using both)\n", cookie->bytes_per_sec_rate, cookie->bytes_per_sec_scale);
TRACE("bytes_per_sec_rate %ld, bytes_per_sec_scale %ld (using both)\n",
cookie->bytes_per_sec_rate, cookie->bytes_per_sec_scale);
} else if (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;
cookie->bytes_per_sec_scale = 1;
cookie->frames_per_sec_rate = stream_header->rate;
cookie->frames_per_sec_scale = 1;
TRACE("bytes_per_sec_rate %ld, bytes_per_sec_scale %ld (using rate)\n", cookie->bytes_per_sec_rate, cookie->bytes_per_sec_scale);
TRACE("bytes_per_sec_rate %ld, bytes_per_sec_scale %ld (using rate)\n",
cookie->bytes_per_sec_rate, cookie->bytes_per_sec_scale);
} else if (audio_format->PacketSize) {
cookie->bytes_per_sec_rate = audio_format->PacketSize;
cookie->bytes_per_sec_scale = 1;
cookie->frames_per_sec_rate = audio_format->PacketSize * 8 / audio_format->SampleSize / audio_format->NoOfChannels;
cookie->frames_per_sec_rate = audio_format->PacketSize * 8
/ audio_format->SampleSize / audio_format->NoOfChannels;
cookie->frames_per_sec_scale = 1;
TRACE("bytes_per_sec_rate %ld, bytes_per_sec_scale %ld (using PacketSize)\n", cookie->bytes_per_sec_rate, cookie->bytes_per_sec_scale);
TRACE("bytes_per_sec_rate %ld, bytes_per_sec_scale %ld (using PacketSize)\n",
cookie->bytes_per_sec_rate, cookie->bytes_per_sec_scale);
} else {
cookie->bytes_per_sec_rate = 128000;
cookie->bytes_per_sec_scale = 8;
cookie->frames_per_sec_rate = 16000;
cookie->frames_per_sec_scale = 1;
TRACE("bytes_per_sec_rate %ld, bytes_per_sec_scale %ld (using fallback)\n", cookie->bytes_per_sec_rate, cookie->bytes_per_sec_scale);
TRACE("bytes_per_sec_rate %ld, bytes_per_sec_scale %ld (using fallback)\n",
cookie->bytes_per_sec_rate, cookie->bytes_per_sec_scale);
}
if ((audio_format->compression == AUDIO_NONE) ||
(audio_format->compression == AUDIO_RAW) ||
(audio_format->compression == AUDIO_TWOS1) ||
(audio_format->compression == AUDIO_TWOS2)) {
if (audio_format->compression == AUDIO_NONE
|| audio_format->compression == AUDIO_RAW
|| audio_format->compression == AUDIO_TWOS1
|| audio_format->compression == AUDIO_TWOS2) {
description.family = B_BEOS_FORMAT_FAMILY;
description.u.beos.format = B_BEOS_FORMAT_RAW_AUDIO;
if (B_OK != formats.GetFormatFor(description, format)) {
if (B_OK != formats.GetFormatFor(description, format))
format->type = B_MEDIA_RAW_AUDIO;
}
format->u.raw_audio.frame_rate = cookie->frames_per_sec_rate / cookie->frames_per_sec_scale;
format->u.raw_audio.channel_count = audio_format->NoOfChannels;
@ -463,7 +478,7 @@ mp4Reader::FreeCookie(void *_cookie)
status_t
mp4Reader::GetStreamInfo(void *_cookie, int64 *frameCount, bigtime_t *duration,
media_format *format, const void **infoBuffer, size_t *infoSize)
media_format *format, const void **infoBuffer, size_t *infoSize)
{
mp4_cookie *cookie = (mp4_cookie *)_cookie;
@ -477,9 +492,7 @@ mp4Reader::GetStreamInfo(void *_cookie, int64 *frameCount, bigtime_t *duration,
status_t
mp4Reader::Seek(void *cookie,
uint32 seekTo,
int64 *frame, bigtime_t *time)
mp4Reader::Seek(void *cookie, uint32 seekTo, int64 *frame, bigtime_t *time)
{
// We should seek to nearest keyframe requested
@ -515,21 +528,23 @@ mp4Reader::Seek(void *cookie,
status_t
mp4Reader::GetNextChunk(void *_cookie,
const void **chunkBuffer, size_t *chunkSize,
media_header *mediaHeader)
mp4Reader::GetNextChunk(void *_cookie, const void **chunkBuffer,
size_t *chunkSize, media_header *mediaHeader)
{
mp4_cookie *cookie = (mp4_cookie *)_cookie;
int64 start; uint32 size; bool keyframe;
int64 start;
uint32 size;
bool keyframe;
if (cookie->audio) {
// use chunk position
if (!theFileReader->GetNextChunkInfo(cookie->stream, cookie->chunk_pos, &start, &size, &keyframe))
if (!theFileReader->GetNextChunkInfo(cookie->stream, cookie->chunk_pos,
&start, &size, &keyframe))
return B_LAST_BUFFER_ERROR;
} else {
// use frame position
if (!theFileReader->GetNextChunkInfo(cookie->stream, cookie->frame_pos, &start, &size, &keyframe))
if (!theFileReader->GetNextChunkInfo(cookie->stream, cookie->frame_pos,
&start, &size, &keyframe))
return B_LAST_BUFFER_ERROR;
}
@ -571,7 +586,15 @@ mp4Reader::GetNextChunk(void *_cookie,
*chunkBuffer = cookie->buffer;
*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)
return B_LAST_BUFFER_ERROR;
return B_OK;
}