diff --git a/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/ffmpeg_base_decoder.cpp b/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/ffmpeg_base_decoder.cpp index 48d1b8e1c3f5f6a1d152fc8af83e9d2acf88abb7..1b339ae1bab1666ba59e0bfc2060a478d48d1303 100644 --- a/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/ffmpeg_base_decoder.cpp +++ b/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/ffmpeg_base_decoder.cpp @@ -17,6 +17,7 @@ #include "avcodec_common.h" #include "ffmpeg_converter.h" #include "avcodec_audio_common.h" +#include namespace { constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_AUDIO, "AvCodec-FfmpegBaseDecoder"}; @@ -29,6 +30,11 @@ static std::vector supportedSampleFormats OHOS::MediaAVCodec::AudioSampleFormat::SAMPLE_S32LE, OHOS::MediaAVCodec::AudioSampleFormat::SAMPLE_F32LE }; +static std::set invalidStatus = { + OHOS::Media::Status::ERROR_NOT_ENOUGH_DATA, + OHOS::Media::Status::ERROR_UNKNOWN, + OHOS::Media::Status::ERROR_NO_MEMORY +}; } // namespace namespace OHOS { @@ -160,7 +166,9 @@ Status FfmpegBaseDecoder::ReceiveBuffer(std::shared_ptr &outBuffer) } CheckFormatChange(); status = ReceiveFrameSucc(outBuffer); - dataCallback_->OnOutputBufferDone(outBuffer); + if (invalidStatus.find(status) == invalidStatus.end()) { + dataCallback_->OnOutputBufferDone(outBuffer); + } } else if (ret == AVERROR_EOF) { AVCODEC_LOGI("eos received"); outBuffer->flag_ = MediaAVCodec::AVCODEC_BUFFER_FLAG_EOS; @@ -224,9 +232,6 @@ Status FfmpegBaseDecoder::ReceiveFrameSucc(std::shared_ptr &outBuffer) avCodecContext_->channel_layout = FFMpegConverter::ConvertOHAudioChannelLayoutToFFMpeg(layout); av_channel_layout_from_mask(&avCodecContext_->ch_layout, avCodecContext_->channel_layout); } - AVCODEC_LOGI("recode output description,layout:%{public}s channels:%{public}d nb_channels:%{public}d", - FFMpegConverter::ConvertOHAudioChannelLayoutToString(layout).data(), - avCodecContext_->channels, avCodecContext_->ch_layout.nb_channels); format_->SetData(Tag::AUDIO_CHANNEL_LAYOUT, layout); if (InitResample() != Status::OK) { currentFrameFormatChanged_ = false; @@ -256,6 +261,10 @@ Status FfmpegBaseDecoder::ReceiveFrameSucc(std::shared_ptr &outBuffer) ioInfoMem->Write(outFrame->data[0], outputSize, 0); outBuffer->pts_ = cachedFrame_->pts; outBuffer->duration_ = static_cast(cachedFrame_->nb_samples * durationTime_); + if (avCodecContext_->codec->id == AV_CODEC_ID_AAC && !(outBuffer->pts_ + outBuffer->duration_ > 0)) { + AVCODEC_LOGI("drop this output, pts_ + duration_= %{public}" PRIu64 ".", outBuffer->pts_ + outBuffer->duration_); + return Status::ERROR_NOT_ENOUGH_DATA; + } format_->SetData(Tag::AUDIO_SAMPLE_PER_FRAME, outFrame->nb_samples); ioInfoMem->SetSize(outputSize); if (needResample_) { @@ -385,6 +394,11 @@ Status FfmpegBaseDecoder::InitResample() AVCODEC_LOGI("ffmpeg default sample_fmt :%{public}" PRId32, avCodecContext_->sample_fmt); AVCODEC_LOGI("need sample_fmt :%{public}" PRId32, destFmt_); AVCODEC_LOGI("frameSize :%{public}" PRId32, avCodecContext_->frame_size); + auto layout = FFMpegConverter::ConvertFFToOHAudioChannelLayoutV2(avCodecContext_->channel_layout, + avCodecContext_->channels); + AVCODEC_LOGI("recode output description,layout:%{public}s channels:%{public}d nb_channels:%{public}d", + FFMpegConverter::ConvertOHAudioChannelLayoutToString(layout).data(), + avCodecContext_->channels, avCodecContext_->ch_layout.nb_channels); if ((!needResample_ && avCodecContext_->sample_fmt != destFmt_) || (needResample_ && currentFrameFormatChanged_)) { ResamplePara resamplePara; diff --git a/services/media_engine/plugins/ffmpeg_adapter/audio_encoder/aac/ffmpeg_aac_encoder_plugin.cpp b/services/media_engine/plugins/ffmpeg_adapter/audio_encoder/aac/ffmpeg_aac_encoder_plugin.cpp index cbd9225cd7c5f91c517a4dadbfd81cc3e1a2cafb..3969430edb21a4bceb012044c58718c6408c5861 100644 --- a/services/media_engine/plugins/ffmpeg_adapter/audio_encoder/aac/ffmpeg_aac_encoder_plugin.cpp +++ b/services/media_engine/plugins/ffmpeg_adapter/audio_encoder/aac/ffmpeg_aac_encoder_plugin.cpp @@ -48,6 +48,7 @@ constexpr int32_t NS_PER_US = 1000; constexpr int32_t AAC_FRAME_SIZE = 1024; constexpr int32_t CORRECTION_SAMPLE_RATE = 8000; constexpr int32_t CORRECTION_BIT_RATE = 70000; +constexpr int64_t US_PER_SECOND = 1000000; constexpr int32_t CORRECTION_CHANNEL_COUNT = 2; constexpr float Q_SCALE = 1.2f; static std::map sampleFreqMap = {{96000, 0}, {88200, 1}, {64000, 2}, {48000, 3}, {44100, 4}, @@ -223,6 +224,8 @@ Status FFmpegAACEncoderPlugin::Start() status = OpenContext(); CHECK_AND_RETURN_RET_LOG(status == Status::OK, status, "Open context failed, status = %{public}d", status); + initPadding_ = avCodecContext_->initial_padding; + MEDIA_LOG_I("initPadding_: %{public}d", initPadding_); status = InitFrame(); CHECK_AND_RETURN_RET_LOG(status == Status::OK, status, "Init frame failed, status = %{public}d", status); @@ -311,7 +314,8 @@ Status FFmpegAACEncoderPlugin::ReceivePacketSucc(std::shared_ptr &outB outBuffer->duration_ = ConvertTimeFromFFmpeg(avPacket_->duration, avCodecContext_->time_base) / NS_PER_US; // adjust ffmpeg duration with sample rate if (ptsMode_ == GENERATE_ENCODE_PTS_BY_INPUT_MODE && isFirstOutputPts_) { - outBuffer->pts_ = prevPts_; + outBuffer->pts_ = prevPts_ - (initPadding_ * US_PER_SECOND / sampleRate_); + MEDIA_LOG_I("corrected outBuffer->pts_: %{public}" PRIu64 ".", outBuffer->pts_); isFirstOutputPts_ = false; } else if (prevPts_ < 0) { outBuffer->pts_ = prevPts_ + outBuffer->duration_; @@ -358,12 +362,13 @@ Status FFmpegAACEncoderPlugin::SendOutputBuffer(std::shared_ptr &outpu if (outputBuffer->flag_ & BUFFER_FLAG_EOS) { if (!isEosFlush_) { avcodec_send_frame(avCodecContext_.get(), NULL); - outputBuffer->flag_ = MediaAVCodec::AVCODEC_BUFFER_FLAG_NONE; } Status tmp = ReceiveBuffer(outputBuffer); - MEDIA_LOG_I("output eos, flag:%{public}d", outputBuffer->flag_); + if (tmp != Status::END_OF_STREAM) { + outputBuffer->flag_ = MediaAVCodec::AVCODEC_BUFFER_FLAG_NONE; + } dataCallback_->OnOutputBufferDone(outBuffer_); - status = ((tmp == Status::OK&& !isEosFlush_) ? Status::ERROR_AGAIN : Status::OK); + status = ((tmp == Status::OK) ? Status::ERROR_AGAIN : Status::OK); isEosFlush_ = true; } return status; @@ -517,7 +522,6 @@ Status FFmpegAACEncoderPlugin::InitContext() MEDIA_LOG_I("flags:%{public}d global_quality:%{public}d", avCodecContext_->flags, avCodecContext_->global_quality); } - avCodecContext_->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; if (needResample_) { avCodecContext_->sample_fmt = avCodec_->sample_fmts[0]; } diff --git a/services/media_engine/plugins/ffmpeg_adapter/audio_encoder/aac/ffmpeg_aac_encoder_plugin.h b/services/media_engine/plugins/ffmpeg_adapter/audio_encoder/aac/ffmpeg_aac_encoder_plugin.h index 735511a86ca65c1d2413011499471a71a7e95a74..d34591c05bff638cda121ba8e992c871470d79cc 100644 --- a/services/media_engine/plugins/ffmpeg_adapter/audio_encoder/aac/ffmpeg_aac_encoder_plugin.h +++ b/services/media_engine/plugins/ffmpeg_adapter/audio_encoder/aac/ffmpeg_aac_encoder_plugin.h @@ -147,6 +147,7 @@ private: int32_t maxOutputSize_; FILE *outfile; bool isEosFlush_ = false; + int32_t initPadding_ = 0; }; } // namespace Ffmpeg } // namespace Plugins