blob: 962f7d6049b4c9cdb3303da0a4a374c14c363e94 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ANDROID_V4L2_CODEC2_COMPONENTS_V4L2_DECODE_COMPONENT_H
#define ANDROID_V4L2_CODEC2_COMPONENTS_V4L2_DECODE_COMPONENT_H
#include <atomic>
#include <memory>
#include <C2Component.h>
#include <C2ComponentFactory.h>
#include <C2Work.h>
#include <base/memory/scoped_refptr.h>
#include <base/memory/weak_ptr.h>
#include <base/sequenced_task_runner.h>
#include <base/synchronization/waitable_event.h>
#include <base/threading/thread.h>
#include <v4l2_codec2/components/V4L2DecodeInterface.h>
#include <v4l2_codec2/components/VideoDecoder.h>
#include <v4l2_codec2/components/VideoFramePool.h>
namespace android {
class V4L2DecodeComponent : public C2Component,
public std::enable_shared_from_this<V4L2DecodeComponent> {
public:
static std::shared_ptr<C2Component> create(const std::string& name, c2_node_id_t id,
const std::shared_ptr<C2ReflectorHelper>& helper,
C2ComponentFactory::ComponentDeleter deleter);
V4L2DecodeComponent(const std::string& name, c2_node_id_t id,
const std::shared_ptr<C2ReflectorHelper>& helper,
const std::shared_ptr<V4L2DecodeInterface>& intfImpl);
~V4L2DecodeComponent() override;
// Implementation of C2Component.
c2_status_t start() override;
c2_status_t stop() override;
c2_status_t reset() override;
c2_status_t release() override;
c2_status_t setListener_vb(const std::shared_ptr<Listener>& listener,
c2_blocking_t mayBlock) override;
c2_status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override;
c2_status_t announce_nb(const std::vector<C2WorkOutline>& items) override;
c2_status_t flush_sm(flush_mode_t mode,
std::list<std::unique_ptr<C2Work>>* const flushedWork) override;
c2_status_t drain_nb(drain_mode_t mode) override;
std::shared_ptr<C2ComponentInterface> intf() override;
private:
// The C2Component state machine.
enum class ComponentState {
STOPPED,
RUNNING,
RELEASED,
ERROR,
};
static const char* ComponentStateToString(ComponentState state);
// Handle C2Component's public methods on |mDecoderTaskRunner|.
void startTask(c2_status_t* status, ::base::WaitableEvent* done);
void stopTask();
void releaseTask();
void queueTask(std::unique_ptr<C2Work> work);
void flushTask();
void drainTask();
void setListenerTask(const std::shared_ptr<Listener>& listener, ::base::WaitableEvent* done);
// Try to process pending works at |mPendingWorks|. Paused when |mIsDraining| is set.
void pumpPendingWorks();
// Get the buffer pool.
std::unique_ptr<VideoFramePool> getVideoFramePool(const ui::Size& size,
HalPixelFormat pixelFormat,
size_t numBuffers);
// Detect and report works with no-show frame, only used at VP8 and VP9.
void detectNoShowFrameWorksAndReportIfFinished(const C2WorkOrdinalStruct& currOrdinal);
// Finish callbacks of each method.
void onOutputFrameReady(std::unique_ptr<VideoFrame> frame);
void onDecodeDone(int32_t bitstreamId, VideoDecoder::DecodeStatus status);
void onDrainDone(VideoDecoder::DecodeStatus status);
void onFlushDone();
// Try to process decoding works at |mPendingWorks|.
void pumpReportWork();
// Report finished work.
bool reportWorkIfFinished(int32_t bitstreamId);
bool reportEOSWork();
void reportAbandonedWorks();
bool reportWork(std::unique_ptr<C2Work> work);
// Report error when any error occurs.
void reportError(c2_status_t error);
static std::atomic<int32_t> sConcurrentInstances;
// The pointer of component interface implementation.
std::shared_ptr<V4L2DecodeInterface> mIntfImpl;
// The pointer of component interface.
const std::shared_ptr<C2ComponentInterface> mIntf;
// The pointer of component listener.
std::shared_ptr<Listener> mListener;
std::unique_ptr<VideoDecoder> mDecoder;
// The queue of works that haven't processed and sent to |mDecoder|.
std::queue<std::unique_ptr<C2Work>> mPendingWorks;
// The works whose input buffers are sent to |mDecoder|. The key is the
// bitstream ID of work's input buffer.
std::map<int32_t, std::unique_ptr<C2Work>> mWorksAtDecoder;
// The bitstream ID of the works that output frames have been returned from |mDecoder|.
// The order is display order.
std::queue<int32_t> mOutputBitstreamIds;
// Set to true when decoding the protected playback.
bool mIsSecure = false;
// The component state.
std::atomic<ComponentState> mComponentState{ComponentState::STOPPED};
// Whether we are currently draining the component. This is set when the component is processing
// the drain request, and unset either after reportEOSWork() (EOS is outputted), or
// reportAbandonedWorks() (drain is cancelled and works are abandoned).
bool mIsDraining = false;
// The mutex lock to synchronize start/stop/reset/release calls.
std::mutex mStartStopLock;
// The color aspects parameter for current decoded output buffers.
std::shared_ptr<C2StreamColorAspectsInfo::output> mCurrentColorAspects;
// The flag of pending color aspects change. This should be set once we have parsed color
// aspects from bitstream by parseCodedColorAspects(), at the same time recorded input frame
// index into |mPendingColorAspectsChangeFrameIndex|.
// When this flag is true and the corresponding frame index is not less than
// |mPendingColorAspectsChangeFrameIndex| for the output buffer in onOutputBufferDone(), update
// |mCurrentColorAspects| from component interface and reset the flag.
bool mPendingColorAspectsChange = false;
// The record of frame index to update color aspects. Details as above.
uint64_t mPendingColorAspectsChangeFrameIndex;
// The device task runner and its sequence checker. We should interact with
// |mDevice| on this.
::base::Thread mDecoderThread{"V4L2DecodeComponentDecoderThread"};
scoped_refptr<::base::SequencedTaskRunner> mDecoderTaskRunner;
::base::WeakPtrFactory<V4L2DecodeComponent> mWeakThisFactory{this};
::base::WeakPtr<V4L2DecodeComponent> mWeakThis;
};
} // namespace android
#endif // ANDROID_V4L2_CODEC2_COMPONENTS_V4L2_DECODE_COMPONENT_H