Merge "Fix no sound with FDR-AX100 recorded 4k video"

gugelfrei
TreeHugger Robot 6 years ago committed by Android (Google) Code Review
commit 1cbc9f57f3

@ -68,6 +68,7 @@ enum {
};
class MPEG4Source : public MediaTrack {
static const size_t kMaxPcmFrameSize = 8192;
public:
// Caller retains ownership of both "dataSource" and "sampleTable".
MPEG4Source(MetaDataBase &format,
@ -127,7 +128,7 @@ private:
bool mIsAVC;
bool mIsHEVC;
bool mIsAC4;
bool mIsPcm;
size_t mNALLengthSize;
bool mStarted;
@ -332,6 +333,11 @@ static const char *FourCC2MIME(uint32_t fourcc) {
return MEDIA_MIMETYPE_VIDEO_HEVC;
case FOURCC('a', 'c', '-', '4'):
return MEDIA_MIMETYPE_AUDIO_AC4;
case FOURCC('t', 'w', 'o', 's'):
case FOURCC('s', 'o', 'w', 't'):
return MEDIA_MIMETYPE_AUDIO_RAW;
default:
ALOGW("Unknown fourcc: %c%c%c%c",
(fourcc >> 24) & 0xff,
@ -1488,6 +1494,8 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
case FOURCC('e', 'n', 'c', 'a'):
case FOURCC('s', 'a', 'm', 'r'):
case FOURCC('s', 'a', 'w', 'b'):
case FOURCC('t', 'w', 'o', 's'):
case FOURCC('s', 'o', 'w', 't'):
{
if (mIsQT && chunk_type == FOURCC('m', 'p', '4', 'a')
&& depth >= 1 && mPath[depth - 1] == FOURCC('w', 'a', 'v', 'e')) {
@ -1557,6 +1565,13 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
// if the chunk type is enca, we'll get the type from the frma box later
mLastTrack->meta.setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RAW, FourCC2MIME(chunk_type))) {
mLastTrack->meta.setInt32(kKeyBitsPerSample, sample_size);
if (chunk_type == FOURCC('t', 'w', 'o', 's')) {
mLastTrack->meta.setInt32(kKeyPcmBigEndian, 1);
}
}
}
ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
chunk, num_channels, sample_size, sample_rate);
@ -4106,6 +4121,7 @@ MPEG4Source::MPEG4Source(
mIsAVC(false),
mIsHEVC(false),
mIsAC4(false),
mIsPcm(false),
mNALLengthSize(0),
mStarted(false),
mGroup(NULL),
@ -4168,6 +4184,27 @@ MPEG4Source::MPEG4Source(
mNALLengthSize = 1 + (ptr[14 + 7] & 3);
}
mIsPcm = !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW);
if (mIsPcm) {
int32_t numChannels = 0;
int32_t bitsPerSample = 0;
CHECK(mFormat.findInt32(kKeyBitsPerSample, &bitsPerSample));
CHECK(mFormat.findInt32(kKeyChannelCount, &numChannels));
int32_t bytesPerSample = bitsPerSample >> 3;
int32_t pcmSampleSize = bytesPerSample * numChannels;
size_t maxSampleSize;
status_t err = mSampleTable->getMaxSampleSize(&maxSampleSize);
if (err != OK || maxSampleSize != static_cast<size_t>(pcmSampleSize) || bitsPerSample != 16) {
// Not supported
mIsPcm = false;
} else {
mFormat.setInt32(kKeyMaxInputSize, pcmSampleSize * kMaxPcmFrameSize);
}
}
CHECK(format.findInt32(kKeyTrackID, &mTrackId));
}
@ -5082,34 +5119,78 @@ status_t MPEG4Source::read(
if ((!mIsAVC && !mIsHEVC && !mIsAC4) || mWantsNALFragments) {
if (newBuffer) {
ssize_t num_bytes_read =
mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
if (mIsPcm) {
// The twos' PCM block reader assumes that all samples has the same size.
if (num_bytes_read < (ssize_t)size) {
mBuffer->release();
mBuffer = NULL;
uint32_t samplesToRead = mSampleTable->getLastSampleIndexInChunk()
- mCurrentSampleIndex + 1;
if (samplesToRead > kMaxPcmFrameSize) {
samplesToRead = kMaxPcmFrameSize;
}
return ERROR_IO;
}
ALOGV("Reading %d PCM frames of size %zu at index %d to stop of chunk at %d",
samplesToRead, size, mCurrentSampleIndex,
mSampleTable->getLastSampleIndexInChunk());
CHECK(mBuffer != NULL);
mBuffer->set_range(0, size);
mBuffer->meta_data().clear();
mBuffer->meta_data().setInt64(
kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
mBuffer->meta_data().setInt64(
kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
size_t totalSize = samplesToRead * size;
uint8_t* buf = (uint8_t *)mBuffer->data();
ssize_t bytesRead = mDataSource->readAt(offset, buf, totalSize);
if (bytesRead < (ssize_t)totalSize) {
mBuffer->release();
mBuffer = NULL;
if (targetSampleTimeUs >= 0) {
mBuffer->meta_data().setInt64(
kKeyTargetTime, targetSampleTimeUs);
}
return ERROR_IO;
}
if (isSyncSample) {
mBuffer->meta_data().clear();
mBuffer->meta_data().setInt64(kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
}
++mCurrentSampleIndex;
int32_t byteOrder;
mFormat.findInt32(kKeyPcmBigEndian, &byteOrder);
if (byteOrder == 1) {
// Big-endian -> little-endian
uint16_t *dstData = (uint16_t *)buf;
uint16_t *srcData = (uint16_t *)buf;
for (size_t j = 0; j < bytesRead / sizeof(uint16_t); j++) {
dstData[j] = ntohs(srcData[j]);
}
}
mCurrentSampleIndex += samplesToRead;
mBuffer->set_range(0, totalSize);
} else {
ssize_t num_bytes_read =
mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
if (num_bytes_read < (ssize_t)size) {
mBuffer->release();
mBuffer = NULL;
return ERROR_IO;
}
CHECK(mBuffer != NULL);
mBuffer->set_range(0, size);
mBuffer->meta_data().clear();
mBuffer->meta_data().setInt64(
kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
mBuffer->meta_data().setInt64(
kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
if (targetSampleTimeUs >= 0) {
mBuffer->meta_data().setInt64(
kKeyTargetTime, targetSampleTimeUs);
}
if (isSyncSample) {
mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
}
++mCurrentSampleIndex;
}
}
if (!mIsAVC && !mIsHEVC && !mIsAC4) {

@ -36,6 +36,11 @@ struct SampleIterator {
uint32_t getSampleTime() const { return mCurrentSampleTime; }
uint32_t getSampleDuration() const { return mCurrentSampleDuration; }
uint32_t getLastSampleIndexInChunk() const {
return mCurrentSampleIndex + mSamplesPerChunk -
((mCurrentSampleIndex - mFirstChunkSampleIndex) % mSamplesPerChunk) - 1;
}
status_t getSampleSizeDirect(
uint32_t sampleIndex, size_t *size);

@ -946,6 +946,11 @@ status_t SampleTable::getSampleSize_l(
sampleIndex, sampleSize);
}
uint32_t SampleTable::getLastSampleIndexInChunk() {
Mutex::Autolock autoLock(mLock);
return mSampleIterator->getLastSampleIndexInChunk();
}
status_t SampleTable::getMetaDataForSample(
uint32_t sampleIndex,
off64_t *offset,

@ -69,6 +69,9 @@ public:
bool *isSyncSample = NULL,
uint32_t *sampleDuration = NULL);
// call only after getMetaDataForSample has been called successfully.
uint32_t getLastSampleIndexInChunk();
enum {
kFlagBefore,
kFlagAfter,

@ -53,6 +53,7 @@ enum {
kKeyFrameRate = 'frmR', // int32_t (video frame rate fps)
kKeyBitRate = 'brte', // int32_t (bps)
kKeyMaxBitRate = 'mxBr', // int32_t (bps)
kKeyBitsPerSample = 'bits', // int32_t (bits per sample)
kKeyStreamHeader = 'stHd', // raw data
kKeyESDS = 'esds', // raw data
kKeyAACProfile = 'aacp', // int32_t
@ -225,6 +226,7 @@ enum {
kKeyExifOffset = 'exof', // int64_t, Exif data offset
kKeyExifSize = 'exsz', // int64_t, Exif data size
kKeyIsExif = 'exif', // bool (int32_t) buffer contains exif data block
kKeyPcmBigEndian = 'pcmb', // bool (int32_t)
};
enum {

Loading…
Cancel
Save