use qcom decoder in replay framereader

sync
Test User 1 month ago
parent d4693d6542
commit 0d6aa7afc4
  1. 65
      tools/replay/framereader.cc
  2. 27
      tools/replay/framereader.h

@ -8,6 +8,7 @@
#include "common/util.h" #include "common/util.h"
#include "third_party/libyuv/include/libyuv.h" #include "third_party/libyuv/include/libyuv.h"
#include "tools/replay/util.h" #include "tools/replay/util.h"
#include "system/hardware/hw.h"
#ifdef __APPLE__ #ifdef __APPLE__
#define HW_DEVICE_TYPE AV_HWDEVICE_TYPE_VIDEOTOOLBOX #define HW_DEVICE_TYPE AV_HWDEVICE_TYPE_VIDEOTOOLBOX
@ -37,7 +38,13 @@ struct DecoderManager {
return it->second.get(); return it->second.get();
} }
auto decoder = std::make_unique<VideoDecoder>(); std::unique_ptr<VideoDecoder> decoder;
if (Hardware::TICI() && hw_decoder) {
decoder = std::make_unique<QcomVideoDecoder>();
} else {
decoder = std::make_unique<FFmpegVideoDecoder>();
}
if (!decoder->open(codecpar, hw_decoder)) { if (!decoder->open(codecpar, hw_decoder)) {
decoder.reset(nullptr); decoder.reset(nullptr);
} }
@ -114,19 +121,19 @@ bool FrameReader::get(int idx, VisionBuf *buf) {
// class VideoDecoder // class VideoDecoder
VideoDecoder::VideoDecoder() { FFmpegVideoDecoder::FFmpegVideoDecoder() {
av_frame_ = av_frame_alloc(); av_frame_ = av_frame_alloc();
hw_frame_ = av_frame_alloc(); hw_frame_ = av_frame_alloc();
} }
VideoDecoder::~VideoDecoder() { FFmpegVideoDecoder::~FFmpegVideoDecoder() {
if (hw_device_ctx) av_buffer_unref(&hw_device_ctx); if (hw_device_ctx) av_buffer_unref(&hw_device_ctx);
if (decoder_ctx) avcodec_free_context(&decoder_ctx); if (decoder_ctx) avcodec_free_context(&decoder_ctx);
av_frame_free(&av_frame_); av_frame_free(&av_frame_);
av_frame_free(&hw_frame_); av_frame_free(&hw_frame_);
} }
bool VideoDecoder::open(AVCodecParameters *codecpar, bool hw_decoder) { bool FFmpegVideoDecoder::open(AVCodecParameters *codecpar, bool hw_decoder) {
const AVCodec *decoder = avcodec_find_decoder(codecpar->codec_id); const AVCodec *decoder = avcodec_find_decoder(codecpar->codec_id);
if (!decoder) return false; if (!decoder) return false;
@ -149,7 +156,7 @@ bool VideoDecoder::open(AVCodecParameters *codecpar, bool hw_decoder) {
return true; return true;
} }
bool VideoDecoder::initHardwareDecoder(AVHWDeviceType hw_device_type) { bool FFmpegVideoDecoder::initHardwareDecoder(AVHWDeviceType hw_device_type) {
const AVCodecHWConfig *config = nullptr; const AVCodecHWConfig *config = nullptr;
for (int i = 0; (config = avcodec_get_hw_config(decoder_ctx->codec, i)) != nullptr; i++) { for (int i = 0; (config = avcodec_get_hw_config(decoder_ctx->codec, i)) != nullptr; i++) {
if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX && config->device_type == hw_device_type) { if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX && config->device_type == hw_device_type) {
@ -175,7 +182,7 @@ bool VideoDecoder::initHardwareDecoder(AVHWDeviceType hw_device_type) {
return true; return true;
} }
bool VideoDecoder::decode(FrameReader *reader, int idx, VisionBuf *buf) { bool FFmpegVideoDecoder::decode(FrameReader *reader, int idx, VisionBuf *buf) {
int current_idx = idx; int current_idx = idx;
if (idx != reader->prev_idx + 1) { if (idx != reader->prev_idx + 1) {
// seeking to the nearest key frame // seeking to the nearest key frame
@ -219,7 +226,7 @@ bool VideoDecoder::decode(FrameReader *reader, int idx, VisionBuf *buf) {
return false; return false;
} }
AVFrame *VideoDecoder::decodeFrame(AVPacket *pkt) { AVFrame *FFmpegVideoDecoder::decodeFrame(AVPacket *pkt) {
int ret = avcodec_send_packet(decoder_ctx, pkt); int ret = avcodec_send_packet(decoder_ctx, pkt);
if (ret < 0) { if (ret < 0) {
rError("Error sending a packet for decoding: %d", ret); rError("Error sending a packet for decoding: %d", ret);
@ -239,7 +246,7 @@ AVFrame *VideoDecoder::decodeFrame(AVPacket *pkt) {
return (av_frame_->format == hw_pix_fmt) ? hw_frame_ : av_frame_; return (av_frame_->format == hw_pix_fmt) ? hw_frame_ : av_frame_;
} }
bool VideoDecoder::copyBuffer(AVFrame *f, VisionBuf *buf) { bool FFmpegVideoDecoder::copyBuffer(AVFrame *f, VisionBuf *buf) {
if (hw_pix_fmt == HW_PIX_FMT) { if (hw_pix_fmt == HW_PIX_FMT) {
for (int i = 0; i < height/2; i++) { for (int i = 0; i < height/2; i++) {
memcpy(buf->y + (i*2 + 0)*buf->stride, f->data[0] + (i*2 + 0)*f->linesize[0], width); memcpy(buf->y + (i*2 + 0)*buf->stride, f->data[0] + (i*2 + 0)*f->linesize[0], width);
@ -256,3 +263,45 @@ bool VideoDecoder::copyBuffer(AVFrame *f, VisionBuf *buf) {
} }
return true; return true;
} }
bool QcomVideoDecoder::open(AVCodecParameters *codecpar, bool hw_decoder) {
if (codecpar->codec_id != AV_CODEC_ID_HEVC) {
rError("Hardware decoder only supports HEVC codec");
return false;
}
width = codecpar->width;
height = codecpar->height;
msm_vidc.init(VIDEO_DEVICE, width, height, V4L2_PIX_FMT_HEVC);
return true;
}
bool QcomVideoDecoder::decode(FrameReader *reader, int idx, VisionBuf *buf) {
int from_idx = idx;
if (idx != reader->prev_idx + 1) {
// seeking to the nearest key frame
for (int i = idx; i >= 0; --i) {
if (reader->packets_info[i].flags & AV_PKT_FLAG_KEY) {
from_idx = i;
break;
}
}
auto pos = reader->packets_info[from_idx].pos;
int ret = avformat_seek_file(reader->input_ctx, 0, pos, pos, pos, AVSEEK_FLAG_BYTE);
if (ret < 0) {
rError("Failed to seek to byte position %lld: %d", pos, AVERROR(ret));
return false;
}
}
reader->prev_idx = idx;
bool result = false;
AVPacket pkt;
msm_vidc.avctx = reader->input_ctx;
for (int i = from_idx; i <= idx; ++i) {
if (av_read_frame(reader->input_ctx, &pkt) == 0) {
result = msm_vidc.decodeFrame(&pkt, buf) && (i == idx);
av_packet_unref(&pkt);
}
}
return result;
}

@ -6,6 +6,7 @@
#include "msgq/visionipc/visionbuf.h" #include "msgq/visionipc/visionbuf.h"
#include "tools/replay/filereader.h" #include "tools/replay/filereader.h"
#include "tools/replay/util.h" #include "tools/replay/util.h"
#include "tools/replay/qcom/decoder.h"
extern "C" { extern "C" {
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
@ -40,11 +41,18 @@ public:
class VideoDecoder { class VideoDecoder {
public: public:
VideoDecoder(); virtual ~VideoDecoder() = default;
~VideoDecoder(); virtual bool open(AVCodecParameters *codecpar, bool hw_decoder) = 0;
bool open(AVCodecParameters *codecpar, bool hw_decoder); virtual bool decode(FrameReader *reader, int idx, VisionBuf *buf) = 0;
bool decode(FrameReader *reader, int idx, VisionBuf *buf);
int width = 0, height = 0; int width = 0, height = 0;
};
class FFmpegVideoDecoder : public VideoDecoder {
public:
FFmpegVideoDecoder();
~FFmpegVideoDecoder() override;
bool open(AVCodecParameters *codecpar, bool hw_decoder) override;
bool decode(FrameReader *reader, int idx, VisionBuf *buf) override;
private: private:
bool initHardwareDecoder(AVHWDeviceType hw_device_type); bool initHardwareDecoder(AVHWDeviceType hw_device_type);
@ -56,3 +64,14 @@ private:
AVPixelFormat hw_pix_fmt = AV_PIX_FMT_NONE; AVPixelFormat hw_pix_fmt = AV_PIX_FMT_NONE;
AVBufferRef *hw_device_ctx = nullptr; AVBufferRef *hw_device_ctx = nullptr;
}; };
class QcomVideoDecoder : public VideoDecoder {
public:
QcomVideoDecoder() {};
~QcomVideoDecoder() override {};
bool open(AVCodecParameters *codecpar, bool hw_decoder) override;
bool decode(FrameReader *reader, int idx, VisionBuf *buf) override;
private:
MsmVidc msm_vidc = MsmVidc();
};

Loading…
Cancel
Save