blob: 9197f7baeaa8e488ea382394c22c4dd9766c5705 [file] [log] [blame]
/*
* Copyright (C) 2014 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 CODEC_BASE_H_
#define CODEC_BASE_H_
#include <memory>
#include <stdint.h>
#define STRINGIFY_ENUMS
#include <media/hardware/CryptoAPI.h>
#include <media/hardware/HardwareAPI.h>
#include <media/IOMX.h>
#include <media/MediaCodecInfo.h>
#include <media/stagefright/foundation/AHandler.h>
#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/MediaErrors.h>
#include <system/graphics.h>
#include <utils/NativeHandle.h>
namespace android {
class BufferChannelBase;
struct BufferProducerWrapper;
class MediaCodecBuffer;
struct PersistentSurface;
struct RenderedFrameInfo;
class Surface;
struct ICrypto;
namespace hardware {
namespace cas {
namespace native {
namespace V1_0 {
struct IDescrambler;
}}}}
using hardware::cas::native::V1_0::IDescrambler;
struct CodecBase : public AHandler, /* static */ ColorUtils {
/**
* This interface defines events firing from CodecBase back to MediaCodec.
* All methods must not block.
*/
class CodecCallback {
public:
virtual ~CodecCallback() = default;
/**
* Notify MediaCodec for seeing an output EOS.
*
* @param err the underlying cause of the EOS. If the value is neither
* OK nor ERROR_END_OF_STREAM, the EOS is declared
* prematurely for that error.
*/
virtual void onEos(status_t err) = 0;
/**
* Notify MediaCodec that start operation is complete.
*/
virtual void onStartCompleted() = 0;
/**
* Notify MediaCodec that stop operation is complete.
*/
virtual void onStopCompleted() = 0;
/**
* Notify MediaCodec that release operation is complete.
*/
virtual void onReleaseCompleted() = 0;
/**
* Notify MediaCodec that flush operation is complete.
*/
virtual void onFlushCompleted() = 0;
/**
* Notify MediaCodec that an error is occurred.
*
* @param err an error code for the occurred error.
* @param actionCode an action code for severity of the error.
*/
virtual void onError(status_t err, enum ActionCode actionCode) = 0;
/**
* Notify MediaCodec that the underlying component is allocated.
*
* @param componentName the unique name of the component specified in
* MediaCodecList.
*/
virtual void onComponentAllocated(const char *componentName) = 0;
/**
* Notify MediaCodec that the underlying component is configured.
*
* @param inputFormat an input format at configure time.
* @param outputFormat an output format at configure time.
*/
virtual void onComponentConfigured(
const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat) = 0;
/**
* Notify MediaCodec that the input surface is created.
*
* @param inputFormat an input format at surface creation. Formats
* could change from the previous state as a result
* of creating a surface.
* @param outputFormat an output format at surface creation.
* @param inputSurface the created surface.
*/
virtual void onInputSurfaceCreated(
const sp<AMessage> &inputFormat,
const sp<AMessage> &outputFormat,
const sp<BufferProducerWrapper> &inputSurface) = 0;
/**
* Notify MediaCodec that the input surface creation is failed.
*
* @param err an error code of the cause.
*/
virtual void onInputSurfaceCreationFailed(status_t err) = 0;
/**
* Notify MediaCodec that the component accepted the provided input
* surface.
*
* @param inputFormat an input format at surface assignment. Formats
* could change from the previous state as a result
* of assigning a surface.
* @param outputFormat an output format at surface assignment.
*/
virtual void onInputSurfaceAccepted(
const sp<AMessage> &inputFormat,
const sp<AMessage> &outputFormat) = 0;
/**
* Notify MediaCodec that the component declined the provided input
* surface.
*
* @param err an error code of the cause.
*/
virtual void onInputSurfaceDeclined(status_t err) = 0;
/**
* Noitfy MediaCodec that the requested input EOS is sent to the input
* surface.
*
* @param err an error code returned from the surface. If there is no
* input surface, the value is INVALID_OPERATION.
*/
virtual void onSignaledInputEOS(status_t err) = 0;
/**
* Notify MediaCodec that output frames are rendered with information on
* those frames.
*
* @param done a list of rendered frames.
*/
virtual void onOutputFramesRendered(const std::list<RenderedFrameInfo> &done) = 0;
/**
* Notify MediaCodec that output buffers are changed.
*/
virtual void onOutputBuffersChanged() = 0;
};
/**
* This interface defines events firing from BufferChannelBase back to MediaCodec.
* All methods must not block.
*/
class BufferCallback {
public:
virtual ~BufferCallback() = default;
/**
* Notify MediaCodec that an input buffer is available with given index.
* When BufferChannelBase::getInputBufferArray() is not called,
* BufferChannelBase may report different buffers with the same index if
* MediaCodec already queued/discarded the buffer. After calling
* BufferChannelBase::getInputBufferArray(), the buffer and index match the
* returned array.
*/
virtual void onInputBufferAvailable(
size_t index, const sp<MediaCodecBuffer> &buffer) = 0;
/**
* Notify MediaCodec that an output buffer is available with given index.
* When BufferChannelBase::getOutputBufferArray() is not called,
* BufferChannelBase may report different buffers with the same index if
* MediaCodec already queued/discarded the buffer. After calling
* BufferChannelBase::getOutputBufferArray(), the buffer and index match the
* returned array.
*/
virtual void onOutputBufferAvailable(
size_t index, const sp<MediaCodecBuffer> &buffer) = 0;
};
enum {
kMaxCodecBufferSize = 8192 * 4096 * 4, // 8K RGBA
};
inline void setCallback(std::unique_ptr<CodecCallback> &&callback) {
mCallback = std::move(callback);
}
virtual std::shared_ptr<BufferChannelBase> getBufferChannel() = 0;
virtual void initiateAllocateComponent(const sp<AMessage> &msg) = 0;
virtual void initiateConfigureComponent(const sp<AMessage> &msg) = 0;
virtual void initiateCreateInputSurface() = 0;
virtual void initiateSetInputSurface(
const sp<PersistentSurface> &surface) = 0;
virtual void initiateStart() = 0;
virtual void initiateShutdown(bool keepComponentAllocated = false) = 0;
// require an explicit message handler
virtual void onMessageReceived(const sp<AMessage> &msg) = 0;
virtual status_t setSurface(const sp<Surface>& /*surface*/) { return INVALID_OPERATION; }
virtual void signalFlush() = 0;
virtual void signalResume() = 0;
virtual void signalRequestIDRFrame() = 0;
virtual void signalSetParameters(const sp<AMessage> &msg) = 0;
virtual void signalEndOfInputStream() = 0;
/*
* Codec-related defines
*/
protected:
CodecBase() = default;
virtual ~CodecBase() = default;
std::unique_ptr<CodecCallback> mCallback;
private:
DISALLOW_EVIL_CONSTRUCTORS(CodecBase);
};
/**
* A channel between MediaCodec and CodecBase object which manages buffer
* passing. Only MediaCodec is expected to call these methods, and
* underlying CodecBase implementation should define its own interface
* separately for itself.
*
* Concurrency assumptions:
*
* 1) Clients may access the object at multiple threads concurrently.
* 2) All methods do not call underlying CodecBase object while holding a lock.
* 3) Code inside critical section executes within 1ms.
*/
class BufferChannelBase {
public:
virtual ~BufferChannelBase() = default;
inline void setCallback(std::unique_ptr<CodecBase::BufferCallback> &&callback) {
mCallback = std::move(callback);
}
void setCrypto(const sp<ICrypto> &crypto);
void setDescrambler(const sp<IDescrambler> &descrambler);
/**
* Queue an input buffer into the buffer channel.
*
* @return OK if successful;
* -ENOENT if the buffer is not known (TODO: this should be
* handled gracefully in the future, here and below).
*/
virtual status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) = 0;
/**
* Queue a secure input buffer into the buffer channel.
*
* @return OK if successful;
* -ENOENT if the buffer is not known;
* -ENOSYS if mCrypto is not set so that decryption is not
* possible;
* other errors if decryption failed.
*/
virtual status_t queueSecureInputBuffer(
const sp<MediaCodecBuffer> &buffer,
bool secure,
const uint8_t *key,
const uint8_t *iv,
CryptoPlugin::Mode mode,
CryptoPlugin::Pattern pattern,
const CryptoPlugin::SubSample *subSamples,
size_t numSubSamples,
AString *errorDetailMsg) = 0;
/**
* Request buffer rendering at specified time.
*
* @param timestampNs nanosecond timestamp for rendering time.
* @return OK if successful;
* -ENOENT if the buffer is not known.
*/
virtual status_t renderOutputBuffer(
const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) = 0;
/**
* Discard a buffer to the underlying CodecBase object.
*
* TODO: remove once this operation can be handled by just clearing the
* reference.
*
* @return OK if successful;
* -ENOENT if the buffer is not known.
*/
virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) = 0;
/**
* Clear and fill array with input buffers.
*/
virtual void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) = 0;
/**
* Clear and fill array with output buffers.
*/
virtual void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) = 0;
protected:
std::unique_ptr<CodecBase::BufferCallback> mCallback;
sp<ICrypto> mCrypto;
sp<IDescrambler> mDescrambler;
};
} // namespace android
#endif // CODEC_BASE_H_