Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7f5f4281 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "transcoder: wait for actual encoder output format to start writer"

parents 63b79602 a2cc86bf
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -102,6 +102,12 @@ bool MediaTrackTranscoder::stop() {
    return false;
}

void MediaTrackTranscoder::notifyTrackFormatAvailable() {
    if (auto callbacks = mTranscoderCallback.lock()) {
        callbacks->onTrackFormatAvailable(this);
    }
}

std::shared_ptr<MediaSampleQueue> MediaTrackTranscoder::getOutputQueue() const {
    return mOutputQueue;
}
+31 −17
Original line number Diff line number Diff line
@@ -100,6 +100,36 @@ void MediaTranscoder::sendCallback(media_status_t status) {
    }
}

void MediaTranscoder::onTrackFormatAvailable(const MediaTrackTranscoder* transcoder) {
    LOG(INFO) << "TrackTranscoder " << transcoder << " format available.";

    std::scoped_lock lock{mTracksAddedMutex};

    // Ignore duplicate format change.
    if (mTracksAdded.count(transcoder) > 0) {
        return;
    }

    // Add track to the writer.
    const bool ok =
            mSampleWriter->addTrack(transcoder->getOutputQueue(), transcoder->getOutputFormat());
    if (!ok) {
        LOG(ERROR) << "Unable to add track to sample writer.";
        sendCallback(AMEDIA_ERROR_UNKNOWN);
        return;
    }

    mTracksAdded.insert(transcoder);
    if (mTracksAdded.size() == mTrackTranscoders.size()) {
        LOG(INFO) << "Starting sample writer.";
        bool started = mSampleWriter->start();
        if (!started) {
            LOG(ERROR) << "Unable to start sample writer.";
            sendCallback(AMEDIA_ERROR_UNKNOWN);
        }
    }
}

void MediaTranscoder::onTrackFinished(const MediaTrackTranscoder* transcoder) {
    LOG(DEBUG) << "TrackTranscoder " << transcoder << " finished";
}
@@ -267,25 +297,9 @@ media_status_t MediaTranscoder::start() {
        return AMEDIA_ERROR_INVALID_OPERATION;
    }

    // Add tracks to the writer.
    for (auto& transcoder : mTrackTranscoders) {
        const bool ok = mSampleWriter->addTrack(transcoder->getOutputQueue(),
                                                transcoder->getOutputFormat());
        if (!ok) {
            LOG(ERROR) << "Unable to add track to sample writer.";
            return AMEDIA_ERROR_UNKNOWN;
        }
    }

    bool started = mSampleWriter->start();
    if (!started) {
        LOG(ERROR) << "Unable to start sample writer.";
        return AMEDIA_ERROR_UNKNOWN;
    }

    // Start transcoders
    for (auto& transcoder : mTrackTranscoders) {
        started = transcoder->start();
        bool started = transcoder->start();
        if (!started) {
            LOG(ERROR) << "Unable to start track transcoder.";
            cancel();
+3 −0
Original line number Diff line number Diff line
@@ -96,6 +96,9 @@ media_status_t PassthroughTrackTranscoder::runTranscodeLoop() {
    MediaSampleInfo info;
    std::shared_ptr<MediaSample> sample;

    // Notify the track format as soon as we start. It's same as the source format.
    notifyTrackFormatAvailable();

    MediaSample::OnSampleReleasedCallback bufferReleaseCallback =
            [bufferPool = mBufferPool](MediaSample* sample) {
                bufferPool->returnBuffer(const_cast<uint8_t*>(sample->buffer));
+55 −1
Original line number Diff line number Diff line
@@ -86,6 +86,10 @@ struct AsyncCodecCallbackDispatch {
        VideoTrackTranscoder* transcoder = static_cast<VideoTrackTranscoder*>(userdata);
        const char* kCodecName = (codec == transcoder->mDecoder ? "Decoder" : "Encoder");
        LOG(DEBUG) << kCodecName << " format changed: " << AMediaFormat_toString(format);
        if (codec == transcoder->mEncoder.get()) {
            transcoder->mCodecMessageQueue.push(
                    [transcoder, format] { transcoder->updateTrackFormat(format); });
        }
    }

    static void onAsyncError(AMediaCodec* codec, void* userdata, media_status_t error,
@@ -311,6 +315,56 @@ void VideoTrackTranscoder::dequeueOutputSample(int32_t bufferIndex,
    }
}

void VideoTrackTranscoder::updateTrackFormat(AMediaFormat* outputFormat) {
    if (mActualOutputFormat != nullptr) {
        LOG(WARNING) << "Ignoring duplicate format change.";
        return;
    }

    AMediaFormat* formatCopy = AMediaFormat_new();
    if (!formatCopy || AMediaFormat_copy(formatCopy, outputFormat) != AMEDIA_OK) {
        LOG(ERROR) << "Unable to copy outputFormat";
        AMediaFormat_delete(formatCopy);
        mStatus = AMEDIA_ERROR_INVALID_PARAMETER;
        return;
    }

    // Generate the actual track format for muxer based on the encoder output format,
    // since many vital information comes in the encoder format (eg. CSD).
    // Transfer necessary fields from the user-configured track format (derived from
    // source track format and user transcoding request) where needed.

    // Transfer SAR settings:
    // If mDestinationFormat has SAR set, it means the original source has SAR specified
    // at container level. This is supposed to override any SAR settings in the bitstream,
    // thus should always be transferred to the container of the transcoded file.
    int32_t sarWidth, sarHeight;
    if (AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_SAR_WIDTH, &sarWidth) &&
        (sarWidth > 0) &&
        AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_SAR_HEIGHT, &sarHeight) &&
        (sarHeight > 0)) {
        AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_SAR_WIDTH, sarWidth);
        AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_SAR_HEIGHT, sarHeight);
    }
    // Transfer DAR settings.
    int32_t displayWidth, displayHeight;
    if (AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_DISPLAY_WIDTH,
                              &displayWidth) &&
        (displayWidth > 0) &&
        AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_DISPLAY_HEIGHT,
                              &displayHeight) &&
        (displayHeight > 0)) {
        AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_DISPLAY_WIDTH, displayWidth);
        AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_DISPLAY_HEIGHT, displayHeight);
    }

    // TODO: transfer other fields as required.

    mActualOutputFormat = std::shared_ptr<AMediaFormat>(formatCopy, &AMediaFormat_delete);

    notifyTrackFormatAvailable();
}

media_status_t VideoTrackTranscoder::runTranscodeLoop() {
    media_status_t status = AMEDIA_OK;

@@ -350,7 +404,7 @@ void VideoTrackTranscoder::abortTranscodeLoop() {
}

std::shared_ptr<AMediaFormat> VideoTrackTranscoder::getOutputFormat() const {
    return mDestinationFormat;
    return mActualOutputFormat;
}

}  // namespace android
+3 −0
Original line number Diff line number Diff line
@@ -94,6 +94,9 @@ protected:
          : mOutputQueue(std::make_shared<MediaSampleQueue>()),
            mTranscoderCallback(transcoderCallback){};

    // Called by subclasses when the actual track format becomes available.
    void notifyTrackFormatAvailable();

    // configureDestinationFormat needs to be implemented by subclasses, and gets called on an
    // external thread before start.
    virtual media_status_t configureDestinationFormat(
Loading