in native-codec/app/src/main/cpp/native-codec-jni.cpp [90:150]
void doCodecWork(workerdata *d) {
ssize_t bufidx = -1;
if (!d->sawInputEOS) {
bufidx = AMediaCodec_dequeueInputBuffer(d->codec, 2000);
LOGV("input buffer %zd", bufidx);
if (bufidx >= 0) {
size_t bufsize;
auto buf = AMediaCodec_getInputBuffer(d->codec, bufidx, &bufsize);
auto sampleSize = AMediaExtractor_readSampleData(d->ex, buf, bufsize);
if (sampleSize < 0) {
sampleSize = 0;
d->sawInputEOS = true;
LOGV("EOS");
}
auto presentationTimeUs = AMediaExtractor_getSampleTime(d->ex);
AMediaCodec_queueInputBuffer(d->codec, bufidx, 0, sampleSize, presentationTimeUs,
d->sawInputEOS ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0);
AMediaExtractor_advance(d->ex);
}
}
if (!d->sawOutputEOS) {
AMediaCodecBufferInfo info;
auto status = AMediaCodec_dequeueOutputBuffer(d->codec, &info, 0);
if (status >= 0) {
if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) {
LOGV("output EOS");
d->sawOutputEOS = true;
}
int64_t presentationNano = info.presentationTimeUs * 1000;
if (d->renderstart < 0) {
d->renderstart = systemnanotime() - presentationNano;
}
int64_t delay = (d->renderstart + presentationNano) - systemnanotime();
if (delay > 0) {
usleep(delay / 1000);
}
AMediaCodec_releaseOutputBuffer(d->codec, status, info.size != 0);
if (d->renderonce) {
d->renderonce = false;
return;
}
} else if (status == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) {
LOGV("output buffers changed");
} else if (status == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
auto format = AMediaCodec_getOutputFormat(d->codec);
LOGV("format changed to: %s", AMediaFormat_toString(format));
AMediaFormat_delete(format);
} else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
LOGV("no output buffer right now");
} else {
LOGV("unexpected info code: %zd", status);
}
}
if (!d->sawInputEOS || !d->sawOutputEOS) {
mlooper->post(kMsgCodecBuffer, d);
}
}