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

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

Merge "Transcoder: change src/dst to fd"

parents a838681e 308e91f5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#include <android-base/logging.h>
#include <media/MediaTrackTranscoder.h>
#include <media/MediaTrackTranscoderCallback.h>

namespace android {

+20 −45
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <android-base/logging.h>
#include <fcntl.h>
#include <media/MediaSampleReaderNDK.h>
#include <media/MediaSampleWriter.h>
#include <media/MediaTranscoder.h>
#include <media/PassthroughTrackTranscoder.h>
#include <media/VideoTrackTranscoder.h>
@@ -92,11 +93,10 @@ void MediaTranscoder::sendCallback(media_status_t status) {
        }

        // Transcoding is done and the callback to the client has been sent, so tear down the
        // pipeline but do it asynchronously to avoid deadlocks. If an error occurred then
        // automatically delete the output file.
        const bool deleteOutputFile = status != AMEDIA_OK;
        // pipeline but do it asynchronously to avoid deadlocks. If an error occurred, client
        // should clean up the file.
        std::thread asyncCancelThread{
                [self = shared_from_this(), deleteOutputFile] { self->cancel(deleteOutputFile); }};
                [self = shared_from_this()] { self->cancel(); }};
        asyncCancelThread.detach();
    }
}
@@ -115,6 +115,9 @@ void MediaTranscoder::onSampleWriterFinished(media_status_t status) {
    sendCallback(status);
}

MediaTranscoder::MediaTranscoder(const std::shared_ptr<CallbackInterface>& callbacks)
     : mCallbacks(callbacks) {}

std::shared_ptr<MediaTranscoder> MediaTranscoder::create(
        const std::shared_ptr<CallbackInterface>& callbacks,
        const std::shared_ptr<Parcel>& pausedState) {
@@ -129,15 +132,9 @@ std::shared_ptr<MediaTranscoder> MediaTranscoder::create(
    return std::shared_ptr<MediaTranscoder>(new MediaTranscoder(callbacks));
}

media_status_t MediaTranscoder::configureSource(const char* path) {
    if (path == nullptr) {
        LOG(ERROR) << "Source path cannot be null";
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    const int fd = open(path, O_RDONLY);
    if (fd <= 0) {
        LOG(ERROR) << "Unable to open source path: " << path;
media_status_t MediaTranscoder::configureSource(int fd) {
    if (fd < 0) {
        LOG(ERROR) << "Invalid source fd: " << fd;
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

@@ -145,10 +142,9 @@ media_status_t MediaTranscoder::configureSource(const char* path) {
    lseek(fd, 0, SEEK_SET);

    mSampleReader = MediaSampleReaderNDK::createFromFd(fd, 0 /* offset */, fileSize);
    close(fd);

    if (mSampleReader == nullptr) {
        LOG(ERROR) << "Unable to parse source file: " << path;
        LOG(ERROR) << "Unable to parse source fd: " << fd;
        return AMEDIA_ERROR_UNSUPPORTED;
    }

@@ -239,35 +235,23 @@ media_status_t MediaTranscoder::configureTrackFormat(size_t trackIndex, AMediaFo
    return AMEDIA_OK;
}

media_status_t MediaTranscoder::configureDestination(const char* path) {
    if (path == nullptr || strlen(path) < 1) {
        LOG(ERROR) << "Invalid destination path: " << path;
        return AMEDIA_ERROR_INVALID_PARAMETER;
    } else if (mSampleWriter != nullptr) {
        LOG(ERROR) << "Destination is already configured.";
        return AMEDIA_ERROR_INVALID_OPERATION;
    }

    // Write-only, create file if non-existent, don't overwrite existing file.
    static constexpr int kOpenFlags = O_WRONLY | O_CREAT | O_EXCL;
    // User R+W permission.
    static constexpr int kFileMode = S_IRUSR | S_IWUSR;

    const int fd = open(path, kOpenFlags, kFileMode);
media_status_t MediaTranscoder::configureDestination(int fd) {
    if (fd < 0) {
        LOG(ERROR) << "Unable to open destination file \"" << path << "\" for writing: " << fd;
        LOG(ERROR) << "Invalid destination fd: " << fd;
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    mDestinationPath = std::string(path);
    if (mSampleWriter != nullptr) {
        LOG(ERROR) << "Destination is already configured.";
        return AMEDIA_ERROR_INVALID_OPERATION;
    }

    mSampleWriter = std::make_unique<MediaSampleWriter>();
    const bool initOk = mSampleWriter->init(
            fd, std::bind(&MediaTranscoder::onSampleWriterFinished, this, std::placeholders::_1));
    close(fd);

    if (!initOk) {
        LOG(ERROR) << "Unable to initialize sample writer with destination path " << path;
        LOG(ERROR) << "Unable to initialize sample writer with destination fd: " << fd;
        mSampleWriter.reset();
        return AMEDIA_ERROR_UNKNOWN;
    }
@@ -305,7 +289,7 @@ media_status_t MediaTranscoder::start() {
        started = transcoder->start();
        if (!started) {
            LOG(ERROR) << "Unable to start track transcoder.";
            cancel(true);
            cancel();
            return AMEDIA_ERROR_UNKNOWN;
        }
    }
@@ -323,7 +307,7 @@ media_status_t MediaTranscoder::resume() {
    return AMEDIA_ERROR_UNSUPPORTED;
}

media_status_t MediaTranscoder::cancel(bool deleteDestinationFile) {
media_status_t MediaTranscoder::cancel() {
    bool expected = false;
    if (!mCancelled.compare_exchange_strong(expected, true)) {
        // Already cancelled.
@@ -335,15 +319,6 @@ media_status_t MediaTranscoder::cancel(bool deleteDestinationFile) {
        transcoder->stop();
    }

    // TODO(chz): file deletion should be done by upper level from the content URI.
    if (deleteDestinationFile && !mDestinationPath.empty()) {
        int error = unlink(mDestinationPath.c_str());
        if (error) {
            LOG(ERROR) << "Unable to delete destination file " << mDestinationPath.c_str() << ": "
                       << error;
            return AMEDIA_ERROR_IO;
        }
    }
    return AMEDIA_OK;
}

+1 −22
Original line number Diff line number Diff line
@@ -30,28 +30,7 @@

namespace android {

class MediaTrackTranscoder;

/** Callback interface for MediaTrackTranscoder. */
class MediaTrackTranscoderCallback {
public:
    /**
     * Called when the MediaTrackTranscoder instance have finished transcoding all media samples
     * successfully.
     * @param transcoder The MediaTrackTranscoder that finished the transcoding.
     */
    virtual void onTrackFinished(const MediaTrackTranscoder* transcoder);

    /**
     * Called when the MediaTrackTranscoder instance encountered an error it could not recover from.
     * @param transcoder The MediaTrackTranscoder that encountered the error.
     * @param status The non-zero error code describing the encountered error.
     */
    virtual void onTrackError(const MediaTrackTranscoder* transcoder, media_status_t status);

protected:
    virtual ~MediaTrackTranscoderCallback() = default;
};
class MediaTrackTranscoderCallback;

/**
 * Base class for all track transcoders. MediaTrackTranscoder operates asynchronously on an internal
+48 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_MEDIA_TRACK_TRANSCODER_CALLBACK_H
#define ANDROID_MEDIA_TRACK_TRANSCODER_CALLBACK_H

#include <media/NdkMediaError.h>

namespace android {

class MediaTrackTranscoder;

/** Callback interface for MediaTrackTranscoder. */
class MediaTrackTranscoderCallback {
public:
    /**
     * Called when the MediaTrackTranscoder instance have finished transcoding all media samples
     * successfully.
     * @param transcoder The MediaTrackTranscoder that finished the transcoding.
     */
    virtual void onTrackFinished(const MediaTrackTranscoder* transcoder);

    /**
     * Called when the MediaTrackTranscoder instance encountered an error it could not recover from.
     * @param transcoder The MediaTrackTranscoder that encountered the error.
     * @param status The non-zero error code describing the encountered error.
     */
    virtual void onTrackError(const MediaTrackTranscoder* transcoder, media_status_t status);

protected:
    virtual ~MediaTrackTranscoderCallback() = default;
};

}  // namespace android
#endif  // ANDROID_MEDIA_TRACK_TRANSCODER_CALLBACK_H
+12 −17
Original line number Diff line number Diff line
@@ -19,9 +19,7 @@

#include <binder/Parcel.h>
#include <binder/Parcelable.h>
#include <media/MediaSampleReader.h>
#include <media/MediaSampleWriter.h>
#include <media/MediaTrackTranscoder.h>
#include <media/MediaTrackTranscoderCallback.h>
#include <media/NdkMediaError.h>
#include <media/NdkMediaFormat.h>

@@ -31,6 +29,9 @@

namespace android {

class MediaSampleReader;
class MediaSampleWriter;

class MediaTranscoder : public std::enable_shared_from_this<MediaTranscoder>,
                        public MediaTrackTranscoderCallback {
public:
@@ -68,8 +69,8 @@ public:
            const std::shared_ptr<CallbackInterface>& callbacks,
            const std::shared_ptr<Parcel>& pausedState = nullptr);

    /** Configures source from path. */
    media_status_t configureSource(const char* path);
    /** Configures source from path fd. */
    media_status_t configureSource(int fd);

    /** Gets the media formats of all tracks in the file. */
    std::vector<std::shared_ptr<AMediaFormat>> getTrackFormats() const;
@@ -83,8 +84,8 @@ public:
     */
    media_status_t configureTrackFormat(size_t trackIndex, AMediaFormat* trackFormat);

    /** Configures destination from path. */
    media_status_t configureDestination(const char* path);
    /** Configures destination from fd. */
    media_status_t configureDestination(int fd);

    /** Starts transcoding. No configurations can be made once the transcoder has started. */
    media_status_t start();
@@ -105,19 +106,14 @@ public:
    /** Resumes a paused transcoding. */
    media_status_t resume();

    /** Cancels the transcoding. Once canceled the transcoding can not be restarted. returns error
     * if file could not be deleted. */
    media_status_t cancel(bool deleteDestinationFile = true);
    /** Cancels the transcoding. Once canceled the transcoding can not be restarted. Client
     * will be responsible for cleaning up the abandoned file. */
    media_status_t cancel();

    virtual ~MediaTranscoder() = default;

private:
    MediaTranscoder(const std::shared_ptr<CallbackInterface>& callbacks)
          : mCallbacks(callbacks),
            mSampleReader(nullptr),
            mSampleWriter(nullptr),
            mSourceTrackFormats(),
            mTrackTranscoders() {}
    MediaTranscoder(const std::shared_ptr<CallbackInterface>& callbacks);

    // MediaTrackTranscoderCallback
    virtual void onTrackFinished(const MediaTrackTranscoder* transcoder) override;
@@ -133,7 +129,6 @@ private:
    std::vector<std::shared_ptr<AMediaFormat>> mSourceTrackFormats;
    std::vector<std::unique_ptr<MediaTrackTranscoder>> mTrackTranscoders;

    std::string mDestinationPath;
    std::atomic_bool mCallbackSent = false;
    std::atomic_bool mCancelled = false;
};
Loading