transcoder: initial version of pause/resume
- Add pause/resume in TranscoderWrapper, save paused state on pause
and use it to create new transcoder on resume.
Misc fixes:
- TranscoderWrapper::stop should only cancel transcoder if the stop
is for the currently running job. Scheduler could call stop to
cancel a job any time.
- Don't hold TranscoderWrapper lock when running event runnable. If
the runnable calls back into scheduler, and scheduler may call
transcoder again and deadlock.
- Don't report abort as error if the transcoder is cancelled explicitly.
- Push decoder/encoder start as msgs, so that they could be skipped too
if the job is cancelled shortly after starts.
Tests:
Add tests for cancel/pause/resume with real transcoder.
bug: 154734285
bug: 154733948
test: unit testing
Change-Id: I2b7d3da69df53b92ab351db455310799ba0e0e8f
diff --git a/media/libmediatranscoding/transcoder/MediaTranscoder.cpp b/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
index 69932f4..bde1cf6 100644
--- a/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "MediaTranscoder"
#include <android-base/logging.h>
+#include <binder/Parcel.h>
#include <fcntl.h>
#include <media/MediaSampleReaderNDK.h>
#include <media/MediaSampleWriter.h>
@@ -84,6 +85,17 @@
}
void MediaTranscoder::sendCallback(media_status_t status) {
+ // If the transcoder is already cancelled explicitly, don't send any error callbacks.
+ // Tracks and sample writer will report errors for abort. However, currently we can't
+ // tell it apart from real errors. Ideally we still want to report real errors back
+ // to client, as there is a small chance that explicit abort and the real error come
+ // at around the same time, we should report that if abort has a specific error code.
+ // On the other hand, if the transcoder actually finished (status is AMEDIA_OK) at around
+ // the same time of the abort, we should still report the finish back to the client.
+ if (mCancelled && status != AMEDIA_OK) {
+ return;
+ }
+
bool expected = false;
if (mCallbackSent.compare_exchange_strong(expected, true)) {
if (status == AMEDIA_OK) {
@@ -149,11 +161,11 @@
std::shared_ptr<MediaTranscoder> MediaTranscoder::create(
const std::shared_ptr<CallbackInterface>& callbacks,
- const std::shared_ptr<Parcel>& pausedState) {
+ const std::shared_ptr<const Parcel>& pausedState) {
if (pausedState != nullptr) {
- LOG(ERROR) << "Initializing from paused state is currently not supported.";
- return nullptr;
- } else if (callbacks == nullptr) {
+ LOG(INFO) << "Initializing from paused state.";
+ }
+ if (callbacks == nullptr) {
LOG(ERROR) << "Callbacks cannot be null";
return nullptr;
}
@@ -309,15 +321,15 @@
return AMEDIA_OK;
}
-media_status_t MediaTranscoder::pause(std::shared_ptr<const Parcelable>* pausedState) {
- (void)pausedState;
- LOG(ERROR) << "Pause is not currently supported";
- return AMEDIA_ERROR_UNSUPPORTED;
+media_status_t MediaTranscoder::pause(std::shared_ptr<const Parcel>* pausedState) {
+ // TODO: write internal states to parcel.
+ *pausedState = std::make_shared<Parcel>();
+ return cancel();
}
media_status_t MediaTranscoder::resume() {
- LOG(ERROR) << "Resume is not currently supported";
- return AMEDIA_ERROR_UNSUPPORTED;
+ // TODO: restore internal states from parcel.
+ return start();
}
media_status_t MediaTranscoder::cancel() {