视频解码中的调用关系图如下:

10-14 11:37:43.461 1561 27622 E C02B32/av_codec_service/HCODEC: [264][dec.avc][Running][OnQueueInputBuffer 865] wrong ownership: buffer id=3, owner=omx 10-14 11:37:43.461 1561 27622 E C02B32/av_codec_service/HCODEC: [264][dec.avc][Running][OnQueueInputBuffer 865] wrong ownership: buffer id=3, owner=omx 10-14 11:37:43.462 1561 27622 E C02B32/av_codec_service/HCODEC: [264][dec.avc][Running][OnQueueInputBuffer 865] wrong ownership: buffer id=3, owner=omx
根据日志结果在此时间段有多次传入索引为3的buffer数据。分析发现此时间段内并没有接收到系统的回调,就将这几帧buffer给push传入,导致前面几帧push失败。
不可同时向解码器push多次同一index和buffer,正常情况下再次向同一个缓冲区填充数据传入队列需要等待解码器消费完数据并被释放后发起OH_AVCodecOnNeedInputBuffer回调,用该回调的index和buffer指针成为参数来填充数据以此实现轮转。
对解码器的输入队列进行上锁操作,在输入队列中有数据并要将其传入解码器时确保锁保护共享资源访问,获得锁后从解码输入队列中获取回调得到的index和buffer缓冲区出队列,后释放锁,填充帧数据到buffer后使用PushInputBuffer送入解码器解码。
void Player::VideoDecInputThread()
{
while (true) {
CHECK_AND_BREAK_LOG(isStarted_, "Decoder input thread out");
std::unique_lock<std::mutex> lock(videoDecContext_->inputMutex);
bool condRet = videoDecContext_->inputCond.wait_for(
lock, 5s, [this]() { return !isStarted_ || !videoDecContext_->inputBufferInfoQueue.empty(); });
CHECK_AND_BREAK_LOG(isStarted_, "Work done, thread out");
CHECK_AND_CONTINUE_LOG(!videoDecContext_->inputBufferInfoQueue.empty(),
"Buffer queue is empty, continue, cond ret: %{public}d", condRet);
CodecBufferInfo bufferInfo = videoDecContext_->inputBufferInfoQueue.front();
videoDecContext_->inputBufferInfoQueue.pop();
videoDecContext_->inputFrameCount++;
lock.unlock();
demuxer_->ReadSample(demuxer_->GetVideoTrackId(), reinterpret_cast<OH_AVBuffer *>(bufferInfo.buffer),
bufferInfo.attr);
int32_t ret = videoDecoder_->PushInputBuffer(bufferInfo);
AVCODEC_SAMPLE_LOGW("PushInputBuffer info index:"
"%{public}u framecount: %{public}u, pts: %{public}" PRId64,
bufferInfo.bufferIndex, videoDecContext_->inputFrameCount, bufferInfo.attr.pts);
CHECK_AND_BREAK_LOG(ret == AVCODEC_SAMPLE_ERR_OK, "Push data failed, thread out");
CHECK_AND_BREAK_LOG(!(bufferInfo.attr.flags & AVCODEC_BUFFER_FLAGS_EOS), "Catch EOS, thread out");
}
} index输出如下图所示:

完整demo可参考AVCodecVideo。