Merge "Convert renderscript from using ACC to LLVM for its compiler."
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 27d0f50..6064fc4 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -61,6 +61,12 @@
FILE *mFile;
off_t mOffset;
off_t mMdatOffset;
+ uint8_t *mMoovBoxBuffer;
+ off_t mMoovBoxBufferOffset;
+ bool mWriteMoovBoxToMemory;
+ off_t mFreeBoxOffset;
+ bool mStreamableFile;
+ off_t mEstimatedMoovBoxSize;
uint32_t mInterleaveDurationUs;
Mutex mLock;
@@ -75,6 +81,8 @@
off_t addSample_l(MediaBuffer *buffer);
off_t addLengthPrefixedSample_l(MediaBuffer *buffer);
+ inline size_t write(const void *ptr, size_t size, size_t nmemb, FILE* stream);
+
MPEG4Writer(const MPEG4Writer &);
MPEG4Writer &operator=(const MPEG4Writer &);
};
diff --git a/include/ui/android_native_buffer.h b/include/ui/android_native_buffer.h
index 9c92af8..402843e 100644
--- a/include/ui/android_native_buffer.h
+++ b/include/ui/android_native_buffer.h
@@ -33,6 +33,15 @@
common.version = sizeof(android_native_buffer_t);
memset(common.reserved, 0, sizeof(common.reserved));
}
+
+ // Implement the methods that sp<android_native_buffer_t> expects so that it
+ // can be used to automatically refcount android_native_buffer_t's.
+ void incStrong(const void* id) const {
+ common.incRef(const_cast<android_native_base_t*>(&common));
+ }
+ void decStrong(const void* id) const {
+ common.decRef(const_cast<android_native_base_t*>(&common));
+ }
#endif
struct android_native_base_t common;
diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h
index 471c3c7..49bfa2b 100644
--- a/include/ui/egl/android_natives.h
+++ b/include/ui/egl/android_natives.h
@@ -98,6 +98,15 @@
common.version = sizeof(android_native_window_t);
memset(common.reserved, 0, sizeof(common.reserved));
}
+
+ // Implement the methods that sp<android_native_window_t> expects so that it
+ // can be used to automatically refcount android_native_window_t's.
+ void incStrong(const void* id) const {
+ common.incRef(const_cast<android_native_base_t*>(&common));
+ }
+ void decStrong(const void* id) const {
+ common.decRef(const_cast<android_native_base_t*>(&common));
+ }
#endif
struct android_native_base_t common;
@@ -291,6 +300,15 @@
template <typename NATIVE_TYPE, typename TYPE, typename REF>
class EGLNativeBase : public NATIVE_TYPE, public REF
{
+public:
+ // Disambiguate between the incStrong in REF and NATIVE_TYPE
+ void incStrong(const void* id) const {
+ REF::incStrong(id);
+ }
+ void decStrong(const void* id) const {
+ REF::decStrong(id);
+ }
+
protected:
typedef EGLNativeBase<NATIVE_TYPE, TYPE, REF> BASE;
EGLNativeBase() : NATIVE_TYPE(), REF() {
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 57db7e4..12e8fe6 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -32,6 +32,7 @@
#include <media/stagefright/OMXCodec.h>
#include <camera/ICamera.h>
#include <camera/Camera.h>
+#include <camera/CameraParameters.h>
#include <surfaceflinger/ISurface.h>
#include <utils/Errors.h>
#include <sys/types.h>
@@ -88,6 +89,12 @@
}
status_t StagefrightRecorder::setVideoSize(int width, int height) {
+ if (width <= 0 || height <= 0) {
+ LOGE("Invalid video size: %dx%d", width, height);
+ return BAD_VALUE;
+ }
+
+ // Additional check on the dimension will be performed later
mVideoWidth = width;
mVideoHeight = height;
@@ -95,6 +102,12 @@
}
status_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) {
+ if (frames_per_second <= 0 || frames_per_second > 30) {
+ LOGE("Invalid video frame rate: %d", frames_per_second);
+ return BAD_VALUE;
+ }
+
+ // Additional check on the frame rate will be performed later
mFrameRate = frames_per_second;
return OK;
@@ -152,9 +165,9 @@
// Attempt to parse an int64 literal optionally surrounded by whitespace,
// returns true on success, false otherwise.
-static bool safe_strtoi64(const char *s, int32_t *val) {
+static bool safe_strtoi64(const char *s, int64_t *val) {
char *end;
- *val = static_cast<int32_t>(strtoll(s, &end, 10));
+ *val = strtoll(s, &end, 10);
if (end == s || errno == ERANGE) {
return false;
@@ -171,6 +184,18 @@
return *end == '\0';
}
+// Return true if the value is in [0, 0x007FFFFFFF]
+static bool safe_strtoi32(const char *s, int32_t *val) {
+ int64_t temp;
+ if (safe_strtoi64(s, &temp)) {
+ if (temp >= 0 && temp <= 0x007FFFFFFF) {
+ *val = static_cast<int32_t>(temp);
+ return true;
+ }
+ }
+ return false;
+}
+
// Trim both leading and trailing whitespace from the given string.
static void TrimString(String8 *s) {
size_t num_bytes = s->bytes();
@@ -191,85 +216,129 @@
status_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) {
LOGV("setParamAudioSamplingRate: %d", sampleRate);
+ if (sampleRate <= 0) {
+ LOGE("Invalid audio sampling rate: %d", sampleRate);
+ return BAD_VALUE;
+ }
+
+ // Additional check on the sample rate will be performed later.
mSampleRate = sampleRate;
return OK;
}
status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) {
LOGV("setParamAudioNumberOfChannels: %d", channels);
+ if (channels <= 0 || channels >= 3) {
+ LOGE("Invalid number of audio channels: %d", channels);
+ }
+
+ // Additional check on the number of channels will be performed later.
mAudioChannels = channels;
return OK;
}
status_t StagefrightRecorder::setParamAudioEncodingBitRate(int32_t bitRate) {
LOGV("setParamAudioEncodingBitRate: %d", bitRate);
+ if (bitRate <= 0) {
+ LOGE("Invalid audio encoding bit rate: %d", bitRate);
+ return BAD_VALUE;
+ }
+
+ // The target bit rate may not be exactly the same as the requested.
+ // It depends on many factors, such as rate control, and the bit rate
+ // range that a specific encoder supports. The mismatch between the
+ // the target and requested bit rate will NOT be treated as an error.
mAudioBitRate = bitRate;
return OK;
}
status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) {
LOGV("setParamVideoEncodingBitRate: %d", bitRate);
+ if (bitRate <= 0) {
+ LOGE("Invalid video encoding bit rate: %d", bitRate);
+ return BAD_VALUE;
+ }
+
+ // The target bit rate may not be exactly the same as the requested.
+ // It depends on many factors, such as rate control, and the bit rate
+ // range that a specific encoder supports. The mismatch between the
+ // the target and requested bit rate will NOT be treated as an error.
mVideoBitRate = bitRate;
return OK;
}
-status_t StagefrightRecorder::setParamMaxDurationOrFileSize(int32_t limit,
+status_t StagefrightRecorder::setParamMaxDurationOrFileSize(int64_t limit,
bool limit_is_duration) {
LOGV("setParamMaxDurationOrFileSize: limit (%d) for %s",
limit, limit_is_duration?"duration":"size");
+ if (limit_is_duration) { // limit is in ms
+ if (limit <= 1000) { // XXX: 1 second
+ LOGE("Max file duration is too short: %lld us", limit);
+ }
+ mMaxFileDurationUs = limit * 1000LL;
+ } else {
+ if (limit <= 1024) { // XXX: 1 kB
+ LOGE("Max file size is too small: %lld bytes", limit);
+ }
+ mMaxFileSizeBytes = limit;
+ }
return OK;
}
status_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) {
LOGV("setParamInterleaveDuration: %d", durationUs);
+ if (durationUs <= 20000) { // XXX: 20 ms
+ LOGE("Audio/video interleave duration is too small: %d us", durationUs);
+ return BAD_VALUE;
+ }
mInterleaveDurationUs = durationUs;
return OK;
}
+
status_t StagefrightRecorder::setParameter(
const String8 &key, const String8 &value) {
LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
if (key == "max-duration") {
- int32_t max_duration_ms;
+ int64_t max_duration_ms;
if (safe_strtoi64(value.string(), &max_duration_ms)) {
return setParamMaxDurationOrFileSize(
max_duration_ms, true /* limit_is_duration */);
}
} else if (key == "max-filesize") {
- int32_t max_filesize_bytes;
+ int64_t max_filesize_bytes;
if (safe_strtoi64(value.string(), &max_filesize_bytes)) {
return setParamMaxDurationOrFileSize(
max_filesize_bytes, false /* limit is filesize */);
}
} else if (key == "audio-param-sampling-rate") {
int32_t sampling_rate;
- if (safe_strtoi64(value.string(), &sampling_rate)) {
+ if (safe_strtoi32(value.string(), &sampling_rate)) {
return setParamAudioSamplingRate(sampling_rate);
}
} else if (key == "audio-param-number-of-channels") {
int32_t number_of_channels;
- if (safe_strtoi64(value.string(), &number_of_channels)) {
+ if (safe_strtoi32(value.string(), &number_of_channels)) {
return setParamAudioNumberOfChannels(number_of_channels);
}
} else if (key == "audio-param-encoding-bitrate") {
int32_t audio_bitrate;
- if (safe_strtoi64(value.string(), &audio_bitrate)) {
+ if (safe_strtoi32(value.string(), &audio_bitrate)) {
return setParamAudioEncodingBitRate(audio_bitrate);
}
} else if (key == "video-param-encoding-bitrate") {
int32_t video_bitrate;
- if (safe_strtoi64(value.string(), &video_bitrate)) {
+ if (safe_strtoi32(value.string(), &video_bitrate)) {
return setParamVideoEncodingBitRate(video_bitrate);
}
} else if (key == "param-interleave-duration-us") {
int32_t durationUs;
- if (safe_strtoi64(value.string(), &durationUs)) {
+ if (safe_strtoi32(value.string(), &durationUs)) {
return setParamInterleaveDuration(durationUs);
}
} else {
LOGE("setParameter: failed to find key %s", key.string());
- return BAD_VALUE;
}
- return OK;
+ return BAD_VALUE;
}
status_t StagefrightRecorder::setParameters(const String8 ¶ms) {
@@ -332,6 +401,10 @@
case OUTPUT_FORMAT_AMR_WB:
return startAMRRecording();
+ case OUTPUT_FORMAT_AAC_ADIF:
+ case OUTPUT_FORMAT_AAC_ADTS:
+ return startAACRecording();
+
default:
return UNKNOWN_ERROR;
}
@@ -377,6 +450,7 @@
encMeta->setInt32(kKeyMaxInputSize, maxInputSize);
encMeta->setInt32(kKeyChannelCount, mAudioChannels);
encMeta->setInt32(kKeySampleRate, mSampleRate);
+ encMeta->setInt32(kKeyBitRate, mAudioBitRate);
OMXClient client;
CHECK_EQ(client.connect(), OK);
@@ -388,18 +462,55 @@
return audioEncoder;
}
+status_t StagefrightRecorder::startAACRecording() {
+ CHECK(mOutputFormat == OUTPUT_FORMAT_AAC_ADIF ||
+ mOutputFormat == OUTPUT_FORMAT_AAC_ADTS);
+
+ CHECK(mAudioEncoder == AUDIO_ENCODER_AAC);
+ CHECK(mAudioSource != AUDIO_SOURCE_LIST_END);
+ CHECK(mOutputFd >= 0);
+
+ CHECK(0 == "AACWriter is not implemented yet");
+
+ return OK;
+}
+
status_t StagefrightRecorder::startAMRRecording() {
- if (mAudioSource == AUDIO_SOURCE_LIST_END
- || mVideoSource != VIDEO_SOURCE_LIST_END) {
+ CHECK(mOutputFormat == OUTPUT_FORMAT_AMR_NB ||
+ mOutputFormat == OUTPUT_FORMAT_AMR_WB);
+
+ if (mOutputFormat == OUTPUT_FORMAT_AMR_NB) {
+ if (mAudioEncoder != AUDIO_ENCODER_DEFAULT &&
+ mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
+ LOGE("Invalid encoder %d used for AMRNB recording",
+ mAudioEncoder);
+ return UNKNOWN_ERROR;
+ }
+ if (mSampleRate != 8000) {
+ LOGE("Invalid sampling rate %d used for AMRNB recording",
+ mSampleRate);
+ return UNKNOWN_ERROR;
+ }
+ } else { // mOutputFormat must be OUTPUT_FORMAT_AMR_WB
+ if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
+ LOGE("Invlaid encoder %d used for AMRWB recording",
+ mAudioEncoder);
+ return UNKNOWN_ERROR;
+ }
+ if (mSampleRate != 16000) {
+ LOGE("Invalid sample rate %d used for AMRWB recording",
+ mSampleRate);
+ return UNKNOWN_ERROR;
+ }
+ }
+ if (mAudioChannels != 1) {
+ LOGE("Invalid number of audio channels %d used for amr recording",
+ mAudioChannels);
return UNKNOWN_ERROR;
}
- if (mOutputFormat == OUTPUT_FORMAT_AMR_NB
- && mAudioEncoder != AUDIO_ENCODER_DEFAULT
- && mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
- return UNKNOWN_ERROR;
- } else if (mOutputFormat == OUTPUT_FORMAT_AMR_WB
- && mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
+ if (mAudioSource >= AUDIO_SOURCE_LIST_END) {
+ LOGE("Invalid audio source: %d", mAudioSource);
return UNKNOWN_ERROR;
}
@@ -444,6 +555,36 @@
|| mVideoSource == VIDEO_SOURCE_CAMERA) {
CHECK(mCamera != NULL);
+ if (mCamera == 0) {
+ mCamera = Camera::connect(0);
+ }
+ CHECK(mCamera != NULL);
+
+ // Set the actual video recording frame size
+ CameraParameters params(mCamera->getParameters());
+ params.setPreviewSize(mVideoWidth, mVideoHeight);
+ params.setPreviewFrameRate(mFrameRate);
+ String8 s = params.flatten();
+ CHECK_EQ(OK, mCamera->setParameters(s));
+ CameraParameters newCameraParams(mCamera->getParameters());
+
+ // Check on video frame size
+ int frameWidth = 0, frameHeight = 0;
+ newCameraParams.getPreviewSize(&frameWidth, &frameHeight);
+ if (frameWidth < 0 || frameWidth != mVideoWidth ||
+ frameHeight < 0 || frameHeight != mVideoHeight) {
+ LOGE("Failed to set the video frame size to %dx%d",
+ mVideoWidth, mVideoHeight);
+ return UNKNOWN_ERROR;
+ }
+
+ // Check on video frame rate
+ int frameRate = newCameraParams.getPreviewFrameRate();
+ if (frameRate < 0 || (frameRate - mFrameRate) != 0) {
+ LOGE("Failed to set frame rate to %d", mFrameRate);
+ return UNKNOWN_ERROR;
+ }
+
sp<CameraSource> cameraSource =
CameraSource::CreateFromCamera(mCamera);
@@ -452,6 +593,9 @@
cameraSource->setPreviewSurface(mPreviewSurface);
sp<MetaData> enc_meta = new MetaData;
+ enc_meta->setInt32(kKeyBitRate, mVideoBitRate);
+ enc_meta->setInt32(kKeySampleRate, mFrameRate); // XXX: kKeySampleRate?
+
switch (mVideoEncoder) {
case VIDEO_ENCODER_H263:
enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
@@ -491,7 +635,12 @@
mWriter->addSource(encoder);
}
- ((MPEG4Writer *)mWriter.get())->setInterleaveDuration(mInterleaveDurationUs);
+ {
+ // MPEGWriter specific handling
+ MPEG4Writer *writer = ((MPEG4Writer *) mWriter.get()); // mWriter is an MPEGWriter
+ writer->setInterleaveDuration(mInterleaveDurationUs);
+ }
+
mWriter->start();
return OK;
}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 3b99e91..b7d554b 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -75,6 +75,8 @@
int32_t mAudioChannels;
int32_t mSampleRate;
int32_t mInterleaveDurationUs;
+ int64_t mMaxFileSizeBytes;
+ int64_t mMaxFileDurationUs;
String8 mParams;
int mOutputFd;
@@ -82,6 +84,7 @@
status_t startMPEG4Recording();
status_t startAMRRecording();
+ status_t startAACRecording();
sp<MediaSource> createAudioSource();
status_t setParameter(const String8 &key, const String8 &value);
status_t setParamVideoEncodingBitRate(int32_t bitRate);
@@ -89,7 +92,7 @@
status_t setParamAudioNumberOfChannels(int32_t channles);
status_t setParamAudioSamplingRate(int32_t sampleRate);
status_t setParamInterleaveDuration(int32_t durationUs);
- status_t setParamMaxDurationOrFileSize(int32_t limit, bool limit_is_duration);
+ status_t setParamMaxDurationOrFileSize(int64_t limit, bool limit_is_duration);
StagefrightRecorder(const StagefrightRecorder &);
StagefrightRecorder &operator=(const StagefrightRecorder &);
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index fd792ee..19cccf7 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -113,6 +113,7 @@
: mFile(fopen(filename, "wb")),
mOffset(0),
mMdatOffset(0),
+ mEstimatedMoovBoxSize(0),
mInterleaveDurationUs(500000) {
CHECK(mFile != NULL);
}
@@ -121,6 +122,7 @@
: mFile(fdopen(fd, "wb")),
mOffset(0),
mMdatOffset(0),
+ mEstimatedMoovBoxSize(0),
mInterleaveDurationUs(500000) {
CHECK(mFile != NULL);
}
@@ -147,15 +149,33 @@
return UNKNOWN_ERROR;
}
+ mStreamableFile = true;
+ mWriteMoovBoxToMemory = false;
+ mMoovBoxBuffer = NULL;
+ mMoovBoxBufferOffset = 0;
+
beginBox("ftyp");
writeFourcc("isom");
writeInt32(0);
writeFourcc("isom");
endBox();
- mMdatOffset = mOffset;
- write("\x00\x00\x00\x01mdat????????", 16);
+ mFreeBoxOffset = mOffset;
+ if (mEstimatedMoovBoxSize == 0) {
+ // XXX: Estimate the moov box size
+ // based on max file size or duration limit
+ mEstimatedMoovBoxSize = 0x0F00;
+ }
+ CHECK(mEstimatedMoovBoxSize >= 8);
+ fseeko(mFile, mFreeBoxOffset, SEEK_SET);
+ writeInt32(mEstimatedMoovBoxSize);
+ write("free", 4);
+
+ mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
+ mOffset = mMdatOffset;
+ fseeko(mFile, mMdatOffset, SEEK_SET);
+ write("\x00\x00\x00\x01mdat????????", 16);
for (List<Track *>::iterator it = mTracks.begin();
it != mTracks.end(); ++it) {
status_t err = (*it)->start();
@@ -189,14 +209,20 @@
}
}
+
// Fix up the size of the 'mdat' chunk.
- fseek(mFile, mMdatOffset + 8, SEEK_SET);
+ fseeko(mFile, mMdatOffset + 8, SEEK_SET);
int64_t size = mOffset - mMdatOffset;
size = hton64(size);
fwrite(&size, 1, 8, mFile);
- fseek(mFile, mOffset, SEEK_SET);
+ fseeko(mFile, mOffset, SEEK_SET);
time_t now = time(NULL);
+ const off_t moovOffset = mOffset;
+ mWriteMoovBoxToMemory = true;
+ mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
+ mMoovBoxBufferOffset = 0;
+ CHECK(mMoovBoxBuffer != NULL);
beginBox("moov");
@@ -236,8 +262,30 @@
}
endBox(); // moov
+ mWriteMoovBoxToMemory = false;
+ if (mStreamableFile) {
+ CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize);
+
+ // Moov box
+ fseeko(mFile, mFreeBoxOffset, SEEK_SET);
+ mOffset = mFreeBoxOffset;
+ write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile);
+
+ // Free box
+ mFreeBoxOffset = mStreamableFile? mOffset: mFreeBoxOffset;
+ fseeko(mFile, mFreeBoxOffset, SEEK_SET);
+ writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
+ write("free", 4);
+
+ // Free temp memory
+ free(mMoovBoxBuffer);
+ mMoovBoxBuffer = NULL;
+ mMoovBoxBufferOffset = 0;
+ }
+
CHECK(mBoxes.empty());
+ fflush(mFile);
fclose(mFile);
mFile = NULL;
}
@@ -317,10 +365,41 @@
return old_offset;
}
+size_t MPEG4Writer::write(
+ const void *ptr, size_t size, size_t nmemb, FILE *stream) {
+
+ const size_t bytes = size * nmemb;
+ if (mWriteMoovBoxToMemory) {
+ if (8 + mMoovBoxBufferOffset + bytes > mEstimatedMoovBoxSize) {
+ for (List<off_t>::iterator it = mBoxes.begin();
+ it != mBoxes.end(); ++it) {
+ (*it) += mOffset;
+ }
+ fseeko(mFile, mOffset, SEEK_SET);
+ fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream);
+ fwrite(ptr, size, nmemb, stream);
+ mOffset += (bytes + mMoovBoxBufferOffset);
+ free(mMoovBoxBuffer);
+ mMoovBoxBuffer = NULL;
+ mMoovBoxBufferOffset = 0;
+ mWriteMoovBoxToMemory = false;
+ mStreamableFile = false;
+ } else {
+ memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
+ mMoovBoxBufferOffset += bytes;
+ }
+ } else {
+ fwrite(ptr, size, nmemb, stream);
+ mOffset += bytes;
+ }
+ return bytes;
+}
+
void MPEG4Writer::beginBox(const char *fourcc) {
CHECK_EQ(strlen(fourcc), 4);
- mBoxes.push_back(mOffset);
+ mBoxes.push_back(mWriteMoovBoxToMemory?
+ mMoovBoxBufferOffset: mOffset);
writeInt32(0);
writeFourcc(fourcc);
@@ -332,51 +411,48 @@
off_t offset = *--mBoxes.end();
mBoxes.erase(--mBoxes.end());
- fseek(mFile, offset, SEEK_SET);
- writeInt32(mOffset - offset);
- mOffset -= 4;
- fseek(mFile, mOffset, SEEK_SET);
+ if (mWriteMoovBoxToMemory) {
+ int32_t x = htonl(mMoovBoxBufferOffset - offset);
+ memcpy(mMoovBoxBuffer + offset, &x, 4);
+ } else {
+ fseeko(mFile, offset, SEEK_SET);
+ writeInt32(mOffset - offset);
+ mOffset -= 4;
+ fseeko(mFile, mOffset, SEEK_SET);
+ }
}
void MPEG4Writer::writeInt8(int8_t x) {
- fwrite(&x, 1, 1, mFile);
- ++mOffset;
+ write(&x, 1, 1, mFile);
}
void MPEG4Writer::writeInt16(int16_t x) {
x = htons(x);
- fwrite(&x, 1, 2, mFile);
- mOffset += 2;
+ write(&x, 1, 2, mFile);
}
void MPEG4Writer::writeInt32(int32_t x) {
x = htonl(x);
- fwrite(&x, 1, 4, mFile);
- mOffset += 4;
+ write(&x, 1, 4, mFile);
}
void MPEG4Writer::writeInt64(int64_t x) {
x = hton64(x);
- fwrite(&x, 1, 8, mFile);
- mOffset += 8;
+ write(&x, 1, 8, mFile);
}
void MPEG4Writer::writeCString(const char *s) {
size_t n = strlen(s);
-
- fwrite(s, 1, n + 1, mFile);
- mOffset += n + 1;
+ write(s, 1, n + 1, mFile);
}
void MPEG4Writer::writeFourcc(const char *s) {
CHECK_EQ(strlen(s), 4);
- fwrite(s, 1, 4, mFile);
- mOffset += 4;
+ write(s, 1, 4, mFile);
}
void MPEG4Writer::write(const void *data, size_t size) {
- fwrite(data, 1, size, mFile);
- mOffset += size;
+ write(data, 1, size, mFile);
}
bool MPEG4Writer::reachedEOS() {