blob: 2ecb3bdc8deb536c297f6043107bb77eac03bf9a [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_DECODER_H
#define ANDROID_V4L2_CODEC2_COMPONENTS_V4L2_DECODER_H
#include <stdint.h>
#include <memory>
#include <optional>
#include <base/callback.h>
#include <base/memory/weak_ptr.h>
#include <ui/Rect.h>
#include <ui/Size.h>
#include <v4l2_codec2/common/V4L2Device.h>
#include <v4l2_codec2/common/VideoTypes.h>
#include <v4l2_codec2/components/VideoDecoder.h>
#include <v4l2_codec2/components/VideoFrame.h>
#include <v4l2_codec2/components/VideoFramePool.h>
namespace android {
class V4L2Decoder : public VideoDecoder {
public:
static std::unique_ptr<VideoDecoder> Create(
const VideoCodec& codec, const size_t inputBufferSize, const size_t minNumOutputBuffers,
GetPoolCB getPoolCB, OutputCB outputCb, ErrorCB errorCb,
scoped_refptr<::base::SequencedTaskRunner> taskRunner);
~V4L2Decoder() override;
void decode(std::unique_ptr<ConstBitstreamBuffer> buffer, DecodeCB decodeCb) override;
void drain(DecodeCB drainCb) override;
void flush() override;
private:
enum class State {
Idle, // Not received any decode buffer after initialized, flushed, or drained.
Decoding,
Draining,
Error,
};
static const char* StateToString(State state);
struct DecodeRequest {
DecodeRequest(std::unique_ptr<ConstBitstreamBuffer> buffer, DecodeCB decodeCb)
: buffer(std::move(buffer)), decodeCb(std::move(decodeCb)) {}
DecodeRequest(DecodeRequest&&) = default;
~DecodeRequest() = default;
std::unique_ptr<ConstBitstreamBuffer> buffer; // nullptr means Drain
DecodeCB decodeCb;
};
V4L2Decoder(scoped_refptr<::base::SequencedTaskRunner> taskRunner);
bool start(const VideoCodec& codec, const size_t inputBufferSize,
const size_t minNumOutputBuffers, GetPoolCB getPoolCb, OutputCB outputCb,
ErrorCB errorCb);
bool setupInputFormat(const uint32_t inputPixelFormat, const size_t inputBufferSize);
void pumpDecodeRequest();
void serviceDeviceTask(bool event);
bool dequeueResolutionChangeEvent();
bool changeResolution();
bool setupOutputFormat(const ui::Size& size);
void tryFetchVideoFrame();
void onVideoFrameReady(std::optional<VideoFramePool::FrameWithBlockId> frameWithBlockId);
std::optional<size_t> getNumOutputBuffers();
std::optional<struct v4l2_format> getFormatInfo();
Rect getVisibleRect(const ui::Size& codedSize);
bool sendV4L2DecoderCmd(bool start);
void setState(State newState);
void onError();
std::unique_ptr<VideoFramePool> mVideoFramePool;
scoped_refptr<V4L2Device> mDevice;
scoped_refptr<V4L2Queue> mInputQueue;
scoped_refptr<V4L2Queue> mOutputQueue;
std::queue<DecodeRequest> mDecodeRequests;
std::map<int32_t, DecodeCB> mPendingDecodeCbs;
size_t mMinNumOutputBuffers = 0;
GetPoolCB mGetPoolCb;
OutputCB mOutputCb;
DecodeCB mDrainCb;
ErrorCB mErrorCb;
ui::Size mCodedSize;
Rect mVisibleRect;
std::map<size_t, std::unique_ptr<VideoFrame>> mFrameAtDevice;
// Block IDs can be arbitrarily large, but we only have a limited number of
// buffers. This maintains an association between a block ID and a specific
// V4L2 buffer index.
std::map<size_t, size_t> mBlockIdToV4L2Id;
State mState = State::Idle;
scoped_refptr<::base::SequencedTaskRunner> mTaskRunner;
::base::WeakPtr<V4L2Decoder> mWeakThis;
::base::WeakPtrFactory<V4L2Decoder> mWeakThisFactory{this};
};
} // namespace android
#endif // ANDROID_V4L2_CODEC2_COMPONENTS_V4L2_DECODER_H