From a56f13bf8c875212c7868f88adaf44cfc086c896 Mon Sep 17 00:00:00 2001 From: ozzay Date: Thu, 29 May 2014 15:30:27 +0200 Subject: [PATCH] Added copy constructors for MP4 boxes --- lib/mp4.cpp | 105 ++++++++++++++++++++++++++++++++++++++++++++++++---- lib/mp4.h | 6 +++ 2 files changed, 104 insertions(+), 7 deletions(-) diff --git a/lib/mp4.cpp b/lib/mp4.cpp index cec0c5a6..0d031da3 100644 --- a/lib/mp4.cpp +++ b/lib/mp4.cpp @@ -7,6 +7,8 @@ #include "mp4_generic.h" #include "json.h" +#include "defines.h" + /// Contains all MP4 format related code. namespace MP4 { @@ -15,6 +17,7 @@ namespace MP4 { /// If the datapointer is NULL, manage is assumed to be true even if explicitly given as false. /// If managed, the pointer will be free'd upon destruction. Box::Box(char * datapointer, bool manage){ + data = datapointer; managed = manage; payloadOffset = 8; @@ -24,6 +27,31 @@ namespace MP4 { data_size = ntohl(((int*)data)[0]); } } + + Box::Box(const Box & rs){ + data = rs.data; + managed = false; + payloadOffset = rs.payloadOffset; + if (data == 0){ + clear(); + }else{ + data_size = ntohl(((int*)data)[0]); + } + } + + Box& Box::operator = (const Box & rs){ + clear(); + data = rs.data; + managed = false; + payloadOffset = rs.payloadOffset; + if (data == 0){ + clear(); + }else{ + data_size = ntohl(((int*)data)[0]); + } + return *this; + } + /// If managed, this will free the data pointer. Box::~Box(){ @@ -43,6 +71,72 @@ namespace MP4 { return !memcmp(boxType, data + 4, 4); } + /// Reads the first 8 bytes and returns + std::string readBoxType(FILE * newData){ + char retVal[8] = {0, 0, 0, 0, 'e', 'r', 'r', 'o'}; + long long unsigned int pos = ftell(newData); + fread(retVal,8,1,newData); + fseek (newData,pos,SEEK_SET); + return std::string(retVal+4,4); + } + + ///\todo make good working calcBoxSize with size and payloadoffset calculation + unsigned long int calcBoxSize(char readVal[16]){ + return (readVal[0] << 24) | (readVal[1] << 16) | (readVal[2] << 8) | (readVal[3]); + } + + bool skipBox(FILE * newData){ + char readVal[16]; + long long unsigned int pos = ftell(newData); + if (fread(readVal,4,1,newData)){ + uint64_t size = calcBoxSize(readVal); + if (size==1){ + if (fread(readVal+4,12,1,newData)){ + size = 0 + ntohl(((int*)readVal)[2]); + size <<= 32; + size += ntohl(((int*)readVal)[3]); + }else{ + return false; + } + }else if (size==0){ + fseek(newData, 0, SEEK_END); + } + DEBUG_MSG(DLVL_DEVEL,"skipping size 0x%0.8X",size); + if (fseek(newData, pos + size, SEEK_SET)==0){ + return true; + }else{ + return false; + } + }else{ + return false; + } + } + + bool Box::read(FILE* newData){ + char readVal[16]; + long long unsigned int pos = ftell(newData); + if (fread(readVal,4,1,newData)){ + payloadOffset = 8; + uint64_t size = calcBoxSize(readVal); + if (size==1){ + if (fread(readVal+4,12,1,newData)){ + size = 0 + ntohl(((int*)readVal)[2]); + size <<= 32; + size += ntohl(((int*)readVal)[3]); + payloadOffset = 16; + }else{ + return false; + } + } + fseek (newData,pos,SEEK_SET); + data = (char*)realloc(data, size); + data_size = size; + return (fread(data,size,1,newData) == 1); + }else{ + return false; + } + } + /// Reads out a whole box (if possible) from newData, copying to the internal data storage and removing from the input string. /// \returns True on success, false otherwise. bool Box::read(std::string & newData){ @@ -63,13 +157,9 @@ namespace MP4 { } } if (newData.size() >= size){ - void * ret = malloc(size); - if ( !ret){ - return false; - } - free(data); - data = (char*)ret; - memcpy(data, newData.c_str(), size); + data = (char*)realloc(data, size); + data_size = size; + memcpy(data, newData.data(), size); newData.erase(0, size); return true; } @@ -568,6 +658,7 @@ namespace MP4 { } fullBox::fullBox(){ + setVersion(0); } void fullBox::setVersion(char newVersion){ diff --git a/lib/mp4.h b/lib/mp4.h index 6c176069..ca025771 100644 --- a/lib/mp4.h +++ b/lib/mp4.h @@ -15,13 +15,19 @@ /// Contains all MP4 format related code. namespace MP4 { + std::string readBoxType(FILE * newData); + bool skipBox(FILE * newData); + class Box{ public: Box(char * datapointer = 0, bool manage = true); + Box(const Box & rs); + Box& operator = (const Box & rs); ~Box(); std::string getType(); bool isType(const char* boxType); + bool read(FILE* newData); bool read(std::string & newData); uint64_t boxedSize(); uint64_t payloadSize();