* 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:
@@ -27,8 +27,8 @@
|
|||||||
|
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
// Std Headers
|
#include <map>
|
||||||
#include <map.h>
|
|
||||||
|
|
||||||
struct ChunkIndex {
|
struct ChunkIndex {
|
||||||
uint32 stream;
|
uint32 stream;
|
||||||
|
|||||||
@@ -25,15 +25,15 @@
|
|||||||
#ifndef _MP4_ATOM_H
|
#ifndef _MP4_ATOM_H
|
||||||
#define _MP4_ATOM_H
|
#define _MP4_ATOM_H
|
||||||
|
|
||||||
|
#include "MP4Structs.h"
|
||||||
|
|
||||||
#include <File.h>
|
#include <File.h>
|
||||||
#include <MediaDefs.h>
|
#include <MediaDefs.h>
|
||||||
#include <MediaFormats.h>
|
#include <MediaFormats.h>
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
// Std Headers
|
#include <map>
|
||||||
#include <map.h>
|
|
||||||
|
|
||||||
#include "MP4Structs.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
AtomBase
|
AtomBase
|
||||||
|
|||||||
@@ -22,16 +22,20 @@
|
|||||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
#include <iostream.h>
|
|
||||||
|
|
||||||
#include <DataIO.h>
|
|
||||||
#include <SupportKit.h>
|
|
||||||
|
|
||||||
#include "MP4Parser.h"
|
#include "MP4Parser.h"
|
||||||
#include "MP4FileReader.h"
|
#include "MP4FileReader.h"
|
||||||
|
|
||||||
|
#include <DataIO.h>
|
||||||
|
#include <SupportKit.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
extern AtomBase *getAtom(BPositionIO *pStream);
|
extern AtomBase *getAtom(BPositionIO *pStream);
|
||||||
|
|
||||||
|
|
||||||
MP4FileReader::MP4FileReader(BPositionIO *pStream)
|
MP4FileReader::MP4FileReader(BPositionIO *pStream)
|
||||||
{
|
{
|
||||||
theStream = pStream;
|
theStream = pStream;
|
||||||
@@ -45,15 +49,18 @@ MP4FileReader::MP4FileReader(BPositionIO *pStream)
|
|||||||
theMVHDAtom = NULL;
|
theMVHDAtom = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MP4FileReader::~MP4FileReader()
|
MP4FileReader::~MP4FileReader()
|
||||||
{
|
{
|
||||||
theStream = NULL;
|
theStream = NULL;
|
||||||
theMVHDAtom = 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++) {
|
for (uint32 index=0;index<CountChildAtoms('mdat');index++) {
|
||||||
aAtomBase = GetChildAtom(uint32('mdat'),index);
|
aAtomBase = GetChildAtom(uint32('mdat'),index);
|
||||||
@@ -66,28 +73,36 @@ AtomBase *aAtomBase;
|
|||||||
return true;
|
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) {
|
if (childAtom) {
|
||||||
atomChildren[TotalChildren++] = pChildAtom;
|
atomChildren[TotalChildren++] = childAtom;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
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)) {
|
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) {
|
||||||
@@ -110,7 +125,9 @@ AtomBase *MP4FileReader::GetChildAtom(uint32 patomType, uint32 offset)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 MP4FileReader::CountChildAtoms(uint32 patomType)
|
|
||||||
|
uint32
|
||||||
|
MP4FileReader::CountChildAtoms(uint32 patomType)
|
||||||
{
|
{
|
||||||
uint32 count = 0;
|
uint32 count = 0;
|
||||||
|
|
||||||
@@ -120,9 +137,11 @@ uint32 MP4FileReader::CountChildAtoms(uint32 patomType)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
MVHDAtom *MP4FileReader::getMVHDAtom()
|
|
||||||
|
MVHDAtom*
|
||||||
|
MP4FileReader::getMVHDAtom()
|
||||||
{
|
{
|
||||||
AtomBase *aAtomBase;
|
AtomBase *aAtomBase;
|
||||||
|
|
||||||
if (theMVHDAtom == NULL) {
|
if (theMVHDAtom == NULL) {
|
||||||
aAtomBase = GetChildAtom(uint32('mvhd'));
|
aAtomBase = GetChildAtom(uint32('mvhd'));
|
||||||
@@ -133,9 +152,11 @@ AtomBase *aAtomBase;
|
|||||||
return theMVHDAtom;
|
return theMVHDAtom;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MP4FileReader::BuildSuperIndex()
|
|
||||||
|
void
|
||||||
|
MP4FileReader::BuildSuperIndex()
|
||||||
{
|
{
|
||||||
AtomBase *aAtomBase;
|
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);
|
||||||
@@ -155,137 +176,148 @@ AtomBase *aAtomBase;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 MP4FileReader::getMovieTimeScale()
|
|
||||||
|
uint32
|
||||||
|
MP4FileReader::getMovieTimeScale()
|
||||||
{
|
{
|
||||||
return getMVHDAtom()->getTimeScale();
|
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
|
// count the number of tracks in the file
|
||||||
return (CountChildAtoms(uint32('trak')));
|
return CountChildAtoms(uint32('trak'));
|
||||||
}
|
}
|
||||||
|
|
||||||
bigtime_t MP4FileReader::getVideoDuration(uint32 stream_index)
|
|
||||||
|
bigtime_t
|
||||||
|
MP4FileReader::getVideoDuration(uint32 streamIndex)
|
||||||
{
|
{
|
||||||
AtomBase *aAtomBase;
|
AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex);
|
||||||
|
|
||||||
aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
if (aAtomBase && dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo())
|
||||||
|
return dynamic_cast<TRAKAtom *>(aAtomBase)->Duration(1);
|
||||||
if ((aAtomBase) && (dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo())) {
|
|
||||||
return (dynamic_cast<TRAKAtom *>(aAtomBase)->Duration(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bigtime_t MP4FileReader::getAudioDuration(uint32 stream_index)
|
|
||||||
|
bigtime_t
|
||||||
|
MP4FileReader::getAudioDuration(uint32 streamIndex)
|
||||||
{
|
{
|
||||||
AtomBase *aAtomBase;
|
AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex);
|
||||||
|
|
||||||
aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
if (aAtomBase && dynamic_cast<TRAKAtom *>(aAtomBase)->IsAudio())
|
||||||
|
return dynamic_cast<TRAKAtom *>(aAtomBase)->Duration(1);
|
||||||
if ((aAtomBase) && (dynamic_cast<TRAKAtom *>(aAtomBase)->IsAudio())) {
|
|
||||||
return (dynamic_cast<TRAKAtom *>(aAtomBase)->Duration(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bigtime_t MP4FileReader::getMaxDuration()
|
|
||||||
|
bigtime_t
|
||||||
|
MP4FileReader::getMaxDuration()
|
||||||
{
|
{
|
||||||
AtomBase *aAtomBase;
|
AtomBase *aAtomBase;
|
||||||
int32 video_index,audio_index;
|
int32 videoIndex = -1;
|
||||||
video_index = -1;
|
int32 audioIndex = -1;
|
||||||
audio_index = -1;
|
|
||||||
|
|
||||||
// find the active video and audio tracks
|
// find the active video and audio tracks
|
||||||
for (uint32 i=0;i<getStreamCount();i++) {
|
for (uint32 i = 0; i < getStreamCount(); i++) {
|
||||||
aAtomBase = GetChildAtom(uint32('trak'),i);
|
aAtomBase = GetChildAtom(uint32('trak'), i);
|
||||||
|
|
||||||
if ((aAtomBase) && (dynamic_cast<TRAKAtom *>(aAtomBase)->IsActive())) {
|
if ((aAtomBase) && (dynamic_cast<TRAKAtom *>(aAtomBase)->IsActive())) {
|
||||||
if (dynamic_cast<TRAKAtom *>(aAtomBase)->IsAudio()) {
|
if (dynamic_cast<TRAKAtom *>(aAtomBase)->IsAudio()) {
|
||||||
audio_index = int32(i);
|
audioIndex = int32(i);
|
||||||
}
|
}
|
||||||
if (dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo()) {
|
if (dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo()) {
|
||||||
video_index = int32(i);
|
videoIndex = int32(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((video_index >= 0) && (audio_index >= 0)) {
|
if (videoIndex >= 0 && audioIndex >= 0) {
|
||||||
return MAX(getVideoDuration(video_index),getAudioDuration(audio_index));
|
return max_c(getVideoDuration(videoIndex),
|
||||||
|
getAudioDuration(audioIndex));
|
||||||
}
|
}
|
||||||
if ((video_index < 0) && (audio_index >= 0)) {
|
if (videoIndex < 0 && audioIndex >= 0) {
|
||||||
return getAudioDuration(audio_index);
|
return getAudioDuration(audioIndex);
|
||||||
}
|
}
|
||||||
if ((video_index >= 0) && (audio_index < 0)) {
|
if (videoIndex >= 0 && audioIndex < 0) {
|
||||||
return getVideoDuration(video_index);
|
return getVideoDuration(videoIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 MP4FileReader::getVideoFrameCount(uint32 stream_index)
|
|
||||||
|
uint32
|
||||||
|
MP4FileReader::getVideoFrameCount(uint32 streamIndex)
|
||||||
{
|
{
|
||||||
AtomBase *aAtomBase;
|
AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex);
|
||||||
|
|
||||||
aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
|
||||||
|
|
||||||
if ((aAtomBase) && (dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo())) {
|
|
||||||
|
|
||||||
|
if (aAtomBase && dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo())
|
||||||
return dynamic_cast<TRAKAtom *>(aAtomBase)->FrameCount();
|
return dynamic_cast<TRAKAtom *>(aAtomBase)->FrameCount();
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 MP4FileReader::getAudioFrameCount(uint32 stream_index)
|
|
||||||
|
uint32
|
||||||
|
MP4FileReader::getAudioFrameCount(uint32 streamIndex)
|
||||||
{
|
{
|
||||||
if (IsAudio(stream_index)) {
|
if (IsAudio(streamIndex)) {
|
||||||
return uint32(((getAudioDuration(stream_index) * AudioFormat(stream_index)->SampleRate) / 1000000L) + 0.5);
|
return uint32(((getAudioDuration(streamIndex)
|
||||||
|
* AudioFormat(streamIndex)->SampleRate) / 1000000L) + 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MP4FileReader::IsVideo(uint32 stream_index)
|
|
||||||
|
bool
|
||||||
|
MP4FileReader::IsVideo(uint32 streamIndex)
|
||||||
{
|
{
|
||||||
// Look for a trak with a vmhd atom
|
// Look for a 'trak' with a vmhd atom
|
||||||
|
|
||||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex);
|
||||||
|
if (aAtomBase)
|
||||||
|
return dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo();
|
||||||
|
|
||||||
if (aAtomBase) {
|
// No track
|
||||||
return (dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo());
|
|
||||||
}
|
|
||||||
|
|
||||||
// No trak
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MP4FileReader::IsAudio(uint32 stream_index)
|
|
||||||
|
bool
|
||||||
|
MP4FileReader::IsAudio(uint32 streamIndex)
|
||||||
{
|
{
|
||||||
// Look for a trak with a smhd atom
|
// Look for a 'trak' with a smhd atom
|
||||||
|
|
||||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex);
|
||||||
|
|
||||||
if (aAtomBase) {
|
if (aAtomBase)
|
||||||
return (dynamic_cast<TRAKAtom *>(aAtomBase)->IsAudio());
|
return dynamic_cast<TRAKAtom *>(aAtomBase)->IsAudio();
|
||||||
}
|
|
||||||
|
|
||||||
// No trak
|
// No track
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 MP4FileReader::getFirstFrameInChunk(uint32 stream_index, uint32 pChunkID)
|
|
||||||
|
uint32
|
||||||
|
MP4FileReader::getFirstFrameInChunk(uint32 streamIndex, uint32 pChunkID)
|
||||||
{
|
{
|
||||||
// Find Track
|
// Find Track
|
||||||
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);
|
||||||
|
|
||||||
@@ -295,7 +327,9 @@ uint32 MP4FileReader::getFirstFrameInChunk(uint32 stream_index, uint32 pChunkID)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 MP4FileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo)
|
|
||||||
|
uint32
|
||||||
|
MP4FileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo)
|
||||||
{
|
{
|
||||||
// Find Track
|
// Find Track
|
||||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||||
@@ -303,9 +337,8 @@ uint32 MP4FileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo)
|
|||||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||||
uint32 ChunkNo = 1;
|
uint32 ChunkNo = 1;
|
||||||
|
|
||||||
if (IsAudio(stream_index)) {
|
if (IsAudio(stream_index))
|
||||||
ChunkNo = pFrameNo;
|
ChunkNo = pFrameNo;
|
||||||
}
|
|
||||||
|
|
||||||
if (IsVideo(stream_index)) {
|
if (IsVideo(stream_index)) {
|
||||||
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
||||||
@@ -320,7 +353,9 @@ uint32 MP4FileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 MP4FileReader::getOffsetForFrame(uint32 stream_index, uint32 pFrameNo)
|
|
||||||
|
uint64
|
||||||
|
MP4FileReader::getOffsetForFrame(uint32 stream_index, uint32 pFrameNo)
|
||||||
{
|
{
|
||||||
// Find Track
|
// Find Track
|
||||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||||
@@ -336,7 +371,6 @@ uint64 MP4FileReader::getOffsetForFrame(uint32 stream_index, uint32 pFrameNo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (IsVideo(stream_index)) {
|
if (IsVideo(stream_index)) {
|
||||||
|
|
||||||
if (pFrameNo < aTrakAtom->FrameCount()) {
|
if (pFrameNo < aTrakAtom->FrameCount()) {
|
||||||
// Get Sample for Frame
|
// Get Sample for Frame
|
||||||
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
||||||
@@ -369,7 +403,9 @@ uint64 MP4FileReader::getOffsetForFrame(uint32 stream_index, uint32 pFrameNo)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t MP4FileReader::ParseFile()
|
|
||||||
|
status_t
|
||||||
|
MP4FileReader::ParseFile()
|
||||||
{
|
{
|
||||||
AtomBase *aChild;
|
AtomBase *aChild;
|
||||||
while (IsEndOfFile() == false) {
|
while (IsEndOfFile() == false) {
|
||||||
@@ -389,7 +425,9 @@ status_t MP4FileReader::ParseFile()
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mp4_main_header *MP4FileReader::MovMainHeader()
|
|
||||||
|
const mp4_main_header*
|
||||||
|
MP4FileReader::MovMainHeader()
|
||||||
{
|
{
|
||||||
// Fill In theMainHeader
|
// Fill In theMainHeader
|
||||||
// uint32 micro_sec_per_frame;
|
// uint32 micro_sec_per_frame;
|
||||||
@@ -409,10 +447,10 @@ const mp4_main_header *MP4FileReader::MovMainHeader()
|
|||||||
theMainHeader.flags = 0;
|
theMainHeader.flags = 0;
|
||||||
theMainHeader.initial_frames = 0;
|
theMainHeader.initial_frames = 0;
|
||||||
|
|
||||||
while ( videoStream < theMainHeader.streams ) {
|
while (videoStream < theMainHeader.streams) {
|
||||||
if (IsVideo(videoStream) && IsActive(videoStream)) {
|
if (IsVideo(videoStream) && IsActive(videoStream))
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
videoStream++;
|
videoStream++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,10 +474,11 @@ const mp4_main_header *MP4FileReader::MovMainHeader()
|
|||||||
return &theMainHeader;
|
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)) {
|
if (IsAudio(stream_index)) {
|
||||||
|
|
||||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||||
|
|
||||||
if (aAtomBase) {
|
if (aAtomBase) {
|
||||||
@@ -470,20 +509,19 @@ const AudioMetaData *MP4FileReader::AudioFormat(uint32 stream_index, size_t *
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const VideoMetaData *MP4FileReader::VideoFormat(uint32 stream_index)
|
|
||||||
|
const VideoMetaData*
|
||||||
|
MP4FileReader::VideoFormat(uint32 stream_index)
|
||||||
{
|
{
|
||||||
if (IsVideo(stream_index)) {
|
if (IsVideo(stream_index)) {
|
||||||
|
|
||||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
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);
|
||||||
|
|
||||||
VideoDescription aVideoDescription = aSTSDAtom->getAsVideo();
|
VideoDescription aVideoDescription = aSTSDAtom->getAsVideo();
|
||||||
|
|
||||||
theVideo.compression = aVideoDescription.codecid;
|
theVideo.compression = aVideoDescription.codecid;
|
||||||
@@ -516,7 +554,9 @@ const VideoMetaData *MP4FileReader::VideoFormat(uint32 stream_index)
|
|||||||
return NULL;
|
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
|
// Fill In a Stream Header
|
||||||
theStreamHeader.length = 0;
|
theStreamHeader.length = 0;
|
||||||
@@ -542,14 +582,15 @@ const mp4_stream_header *MP4FileReader::StreamFormat(uint32 stream_index)
|
|||||||
return &theStreamHeader;
|
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);
|
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||||
if (aAtomBase) {
|
if (aAtomBase) {
|
||||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||||
|
|
||||||
if (IsAudio(stream_index)) {
|
if (IsAudio(stream_index)) {
|
||||||
|
|
||||||
// We read audio in chunk by chunk so chunk size is chunk size
|
// We read audio in chunk by chunk so chunk size is chunk size
|
||||||
uint32 ChunkNo = pFrameNo;
|
uint32 ChunkNo = pFrameNo;
|
||||||
off_t Chunk_Start = aTrakAtom->getOffsetForChunk(ChunkNo);
|
off_t Chunk_Start = aTrakAtom->getOffsetForChunk(ChunkNo);
|
||||||
@@ -565,13 +606,14 @@ uint32 MP4FileReader::getChunkSize(uint32 stream_index, uint32 pFrameNo)
|
|||||||
return aTrakAtom->getSizeForSample(SampleNo);
|
return aTrakAtom->getSizeForSample(SampleNo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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);
|
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||||
if (aAtomBase) {
|
if (aAtomBase) {
|
||||||
@@ -584,7 +626,10 @@ bool MP4FileReader::IsKeyFrame(uint32 stream_index, uint32 pFrameNo)
|
|||||||
return false;
|
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);
|
*start = getOffsetForFrame(stream_index, pFrameNo);
|
||||||
*size = getChunkSize(stream_index, pFrameNo);
|
*size = getChunkSize(stream_index, pFrameNo);
|
||||||
@@ -594,10 +639,13 @@ bool MP4FileReader::GetNextChunkInfo(uint32 stream_index, uint32 pFrameNo, off_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
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);
|
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||||
if (aAtomBase) {
|
if (aAtomBase) {
|
||||||
@@ -608,14 +656,14 @@ bool MP4FileReader::IsActive(uint32 stream_index)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
|
||||||
bool MP4FileReader::IsSupported(BPositionIO *source)
|
|
||||||
{
|
|
||||||
AtomBase *aAtom;
|
|
||||||
|
|
||||||
aAtom = getAtom(source);
|
/* static */
|
||||||
if (aAtom) {
|
bool
|
||||||
return (aAtom->IsKnown());
|
MP4FileReader::IsSupported(BPositionIO *source)
|
||||||
}
|
{
|
||||||
|
AtomBase *aAtom = getAtom(source);
|
||||||
|
if (aAtom)
|
||||||
|
return aAtom->IsKnown();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
// Std Headers
|
// Std Headers
|
||||||
#include <map.h>
|
#include <map>
|
||||||
|
|
||||||
#include "MP4Atom.h"
|
#include "MP4Atom.h"
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,12 @@
|
|||||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
#ifndef MP4_STRUCTS_H
|
||||||
|
#define MP4_STRUCTS_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
#define AUDIO_NONE 'NONE'
|
#define AUDIO_NONE 'NONE'
|
||||||
#define AUDIO_RAW 'raw '
|
#define AUDIO_RAW 'raw '
|
||||||
@@ -33,8 +39,7 @@
|
|||||||
#define AUDIO_MPEG3_CBR 0x6D730055
|
#define AUDIO_MPEG3_CBR 0x6D730055
|
||||||
|
|
||||||
// this is all from the avi reader. we rework it for mp4
|
// 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 micro_sec_per_frame;
|
||||||
uint32 max_bytes_per_sec;
|
uint32 max_bytes_per_sec;
|
||||||
uint32 padding_granularity;
|
uint32 padding_granularity;
|
||||||
@@ -273,3 +278,5 @@ struct VideoDescription {
|
|||||||
uint8 *theVOL;
|
uint8 *theVOL;
|
||||||
size_t VOLSize;
|
size_t VOLSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // MP4_STRUCTS_H
|
||||||
|
|||||||
@@ -22,29 +22,33 @@
|
|||||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
* 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 "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
|
#define TRACE_MP4_READER
|
||||||
#ifdef TRACE_MP4_READER
|
#ifdef TRACE_MP4_READER
|
||||||
#define TRACE printf
|
# define TRACE printf
|
||||||
#else
|
#else
|
||||||
#define TRACE(a...)
|
# define TRACE(a...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ERROR(a...) fprintf(stderr, a)
|
#define ERROR(a...) fprintf(stderr, a)
|
||||||
|
|
||||||
struct mp4_cookie
|
|
||||||
{
|
struct mp4_cookie {
|
||||||
unsigned stream;
|
unsigned stream;
|
||||||
char * buffer;
|
char * buffer;
|
||||||
unsigned buffer_size;
|
unsigned buffer_size;
|
||||||
@@ -77,17 +81,20 @@ mp4Reader::mp4Reader()
|
|||||||
TRACE("mp4Reader::mp4Reader\n");
|
TRACE("mp4Reader::mp4Reader\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mp4Reader::~mp4Reader()
|
mp4Reader::~mp4Reader()
|
||||||
{
|
{
|
||||||
delete theFileReader;
|
delete theFileReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
mp4Reader::Copyright()
|
mp4Reader::Copyright()
|
||||||
{
|
{
|
||||||
return "MPEG4 & libMP4, " B_UTF8_COPYRIGHT " by David McPaul";
|
return "MPEG4 & libMP4, " B_UTF8_COPYRIGHT " by David McPaul";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
mp4Reader::Sniff(int32 *streamCount)
|
mp4Reader::Sniff(int32 *streamCount)
|
||||||
{
|
{
|
||||||
@@ -118,6 +125,7 @@ mp4Reader::Sniff(int32 *streamCount)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
mp4Reader::GetFileFormatInfo(media_file_format *mff)
|
mp4Reader::GetFileFormatInfo(media_file_format *mff)
|
||||||
{
|
{
|
||||||
@@ -133,6 +141,7 @@ mp4Reader::GetFileFormatInfo(media_file_format *mff)
|
|||||||
strcpy(mff->pretty_name, "MPEG-4 (MP4) file format");
|
strcpy(mff->pretty_name, "MPEG-4 (MP4) file format");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
mp4Reader::AllocateCookie(int32 streamNumber, void **_cookie)
|
mp4Reader::AllocateCookie(int32 streamNumber, void **_cookie)
|
||||||
{
|
{
|
||||||
@@ -180,40 +189,46 @@ mp4Reader::AllocateCookie(int32 streamNumber, void **_cookie)
|
|||||||
cookie->chunk_pos = 1;
|
cookie->chunk_pos = 1;
|
||||||
|
|
||||||
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;
|
||||||
cookie->bytes_per_sec_scale = stream_header->scale;
|
cookie->bytes_per_sec_scale = stream_header->scale;
|
||||||
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;
|
||||||
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) {
|
} 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->bytes_per_sec_scale = 1;
|
||||||
cookie->frames_per_sec_rate = stream_header->rate;
|
cookie->frames_per_sec_rate = stream_header->rate;
|
||||||
cookie->frames_per_sec_scale = 1;
|
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) {
|
} else if (audio_format->PacketSize) {
|
||||||
cookie->bytes_per_sec_rate = audio_format->PacketSize;
|
cookie->bytes_per_sec_rate = audio_format->PacketSize;
|
||||||
cookie->bytes_per_sec_scale = 1;
|
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;
|
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 {
|
} else {
|
||||||
cookie->bytes_per_sec_rate = 128000;
|
cookie->bytes_per_sec_rate = 128000;
|
||||||
cookie->bytes_per_sec_scale = 8;
|
cookie->bytes_per_sec_scale = 8;
|
||||||
cookie->frames_per_sec_rate = 16000;
|
cookie->frames_per_sec_rate = 16000;
|
||||||
cookie->frames_per_sec_scale = 1;
|
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) ||
|
if (audio_format->compression == AUDIO_NONE
|
||||||
(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))
|
||||||
format->type = B_MEDIA_RAW_AUDIO;
|
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.frame_rate = cookie->frames_per_sec_rate / cookie->frames_per_sec_scale;
|
||||||
format->u.raw_audio.channel_count = audio_format->NoOfChannels;
|
format->u.raw_audio.channel_count = audio_format->NoOfChannels;
|
||||||
@@ -477,9 +492,7 @@ mp4Reader::GetStreamInfo(void *_cookie, int64 *frameCount, bigtime_t *duration,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
mp4Reader::Seek(void *cookie,
|
mp4Reader::Seek(void *cookie, uint32 seekTo, int64 *frame, bigtime_t *time)
|
||||||
uint32 seekTo,
|
|
||||||
int64 *frame, bigtime_t *time)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
// We should seek to nearest keyframe requested
|
// We should seek to nearest keyframe requested
|
||||||
@@ -515,21 +528,23 @@ mp4Reader::Seek(void *cookie,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
mp4Reader::GetNextChunk(void *_cookie,
|
mp4Reader::GetNextChunk(void *_cookie, const void **chunkBuffer,
|
||||||
const void **chunkBuffer, size_t *chunkSize,
|
size_t *chunkSize, media_header *mediaHeader)
|
||||||
media_header *mediaHeader)
|
|
||||||
{
|
{
|
||||||
mp4_cookie *cookie = (mp4_cookie *)_cookie;
|
mp4_cookie *cookie = (mp4_cookie *)_cookie;
|
||||||
|
int64 start;
|
||||||
int64 start; uint32 size; bool keyframe;
|
uint32 size;
|
||||||
|
bool keyframe;
|
||||||
|
|
||||||
if (cookie->audio) {
|
if (cookie->audio) {
|
||||||
// use chunk position
|
// 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;
|
return B_LAST_BUFFER_ERROR;
|
||||||
} else {
|
} else {
|
||||||
// use frame position
|
// 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;
|
return B_LAST_BUFFER_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -571,7 +586,15 @@ mp4Reader::GetNextChunk(void *_cookie,
|
|||||||
|
|
||||||
*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)
|
||||||
|
return B_LAST_BUFFER_ERROR;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user