OggWriter: Support format without CSD for opus

If format doesn't contain CSD, then look for it when writing sample
data.
When CSD is present in both Format and sample data, the one in format
is used like MPEG4Writer.

Bug: 131747486
Bug: 134509194
Test: poc from bug

Change-Id: If2cab79d540688283afb4d74a6b043ea2e089ef0
gugelfrei
Harish Mahendrakar 5 years ago committed by Ray Essick
parent 50f9a1320b
commit 16f2fa2d5e

@ -52,6 +52,7 @@ namespace android {
OggWriter::OggWriter(int fd)
: mFd(dup(fd)),
mHaveAllCodecSpecificData(false),
mInitCheck(mFd < 0 ? NO_INIT : OK) {
// empty
}
@ -115,17 +116,26 @@ status_t OggWriter::addSource(const sp<MediaSource>& source) {
mSampleRate = sampleRate;
uint32_t type;
const void *header_data;
size_t packet_size;
const void *header_data = NULL;
size_t packet_size = 0;
if (!source->getFormat()->findData(kKeyOpusHeader, &type, &header_data, &packet_size)) {
ALOGE("opus header not found");
return UNKNOWN_ERROR;
ALOGV("opus header not found in format");
} else if (header_data && packet_size) {
writeOggHeaderPackets((unsigned char *)header_data, packet_size);
} else {
ALOGD("ignoring incomplete opus header data in format");
}
mSource = source;
return OK;
}
status_t OggWriter::writeOggHeaderPackets(unsigned char *buf, size_t size) {
ogg_packet op;
ogg_page og;
op.packet = (unsigned char *)header_data;
op.bytes = packet_size;
op.packet = buf;
op.bytes = size;
op.b_o_s = 1;
op.e_o_s = 0;
op.granulepos = 0;
@ -169,8 +179,8 @@ status_t OggWriter::addSource(const sp<MediaSource>& source) {
write(mFd, og.body, og.body_len);
}
mSource = source;
free(comments);
mHaveAllCodecSpecificData = true;
return OK;
}
@ -301,12 +311,35 @@ status_t OggWriter::threadFunc() {
&& isCodecSpecific)
|| IsOpusHeader((uint8_t*)buffer->data() + buffer->range_offset(),
buffer->range_length())) {
ALOGV("Drop codec specific info buffer");
if (mHaveAllCodecSpecificData == false) {
size_t opusHeadSize = 0;
size_t codecDelayBufSize = 0;
size_t seekPreRollBufSize = 0;
void *opusHeadBuf = NULL;
void *codecDelayBuf = NULL;
void *seekPreRollBuf = NULL;
GetOpusHeaderBuffers((uint8_t*)buffer->data() + buffer->range_offset(),
buffer->range_length(), &opusHeadBuf,
&opusHeadSize, &codecDelayBuf,
&codecDelayBufSize, &seekPreRollBuf,
&seekPreRollBufSize);
writeOggHeaderPackets((unsigned char *)opusHeadBuf, opusHeadSize);
} else {
ALOGV("ignoring later copy of CSD contained in info buffer");
}
buffer->release();
buffer = nullptr;
continue;
}
if (mHaveAllCodecSpecificData == false) {
ALOGE("Did not get valid opus header before first sample data");
buffer->release();
buffer = nullptr;
err = ERROR_MALFORMED;
break;
}
int64_t timestampUs;
CHECK(buffer->meta_data().findInt64(kKeyTime, &timestampUs));
if (timestampUs > mEstimatedDurationUs) {

@ -43,6 +43,7 @@ protected:
private:
int mFd;
bool mHaveAllCodecSpecificData;
status_t mInitCheck;
sp<MediaSource> mSource;
bool mStarted = false;
@ -66,6 +67,8 @@ private:
OggWriter(const OggWriter&);
OggWriter& operator=(const OggWriter&);
status_t writeOggHeaderPackets(unsigned char *buf, size_t size);
};
} // namespace android

Loading…
Cancel
Save