Loading media/libmediatranscoding/transcoder/MediaTrackTranscoder.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <android-base/logging.h> #include <media/MediaTrackTranscoder.h> #include <media/MediaTrackTranscoderCallback.h> namespace android { Loading media/libmediatranscoding/transcoder/MediaTranscoder.cpp +20 −45 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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(); } } Loading @@ -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) { Loading @@ -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; } Loading @@ -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; } Loading Loading @@ -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; } Loading Loading @@ -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; } } Loading @@ -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. Loading @@ -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; } Loading media/libmediatranscoding/transcoder/include/media/MediaTrackTranscoder.h +1 −22 Original line number Diff line number Diff line Loading @@ -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 Loading media/libmediatranscoding/transcoder/include/media/MediaTrackTranscoderCallback.h 0 → 100644 +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 media/libmediatranscoding/transcoder/include/media/MediaTranscoder.h +12 −17 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -31,6 +29,9 @@ namespace android { class MediaSampleReader; class MediaSampleWriter; class MediaTranscoder : public std::enable_shared_from_this<MediaTranscoder>, public MediaTrackTranscoderCallback { public: Loading Loading @@ -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; Loading @@ -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(); Loading @@ -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; Loading @@ -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 Loading
media/libmediatranscoding/transcoder/MediaTrackTranscoder.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <android-base/logging.h> #include <media/MediaTrackTranscoder.h> #include <media/MediaTrackTranscoderCallback.h> namespace android { Loading
media/libmediatranscoding/transcoder/MediaTranscoder.cpp +20 −45 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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(); } } Loading @@ -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) { Loading @@ -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; } Loading @@ -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; } Loading Loading @@ -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; } Loading Loading @@ -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; } } Loading @@ -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. Loading @@ -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; } Loading
media/libmediatranscoding/transcoder/include/media/MediaTrackTranscoder.h +1 −22 Original line number Diff line number Diff line Loading @@ -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 Loading
media/libmediatranscoding/transcoder/include/media/MediaTrackTranscoderCallback.h 0 → 100644 +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
media/libmediatranscoding/transcoder/include/media/MediaTranscoder.h +12 −17 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -31,6 +29,9 @@ namespace android { class MediaSampleReader; class MediaSampleWriter; class MediaTranscoder : public std::enable_shared_from_this<MediaTranscoder>, public MediaTrackTranscoderCallback { public: Loading Loading @@ -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; Loading @@ -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(); Loading @@ -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; Loading @@ -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