提交 d792d942 编写于 作者: B BohaoWu

Reduce PR.

上级 d27a0f3b
......@@ -9,5 +9,4 @@ if (${CUDA_VERSION} LESS 10.0)
return()
elseif (${CUDA_VERSION} LESS 10.1) # CUDA 10.0
add_subdirectory(hwvideoframe)
add_subdirectory(nvdec-extractframe)
endif()
cmake_minimum_required(VERSION 3.2)
project(hw-extract)
include(cuda)
include(configure)
execute_process(COMMAND wget -q https://paddle-serving.bj.bcebos.com/external_code/libpreprocess.tar.gz)
execute_process(COMMAND mv libpreprocess.tar.gz ${CMAKE_SOURCE_DIR}/core/preprocess/nvdec-extractframe/)
execute_process(COMMAND tar -xf ${CMAKE_SOURCE_DIR}/core/preprocess/nvdec-extractframe/libpreprocess.tar.gz -C ${CMAKE_SOURCE_DIR}/core/preprocess/nvdec-extractframe/)
#C flags
set(CMAKE_C_FLAGS " -g -pipe -W -Wall -fPIC -Wmissing-field-initializers")
#C++ flags.
set(CMAKE_CXX_FLAGS " -g -pipe -W -Wall -fPIC -std=c++11 -Wmissing-field-initializers")
add_subdirectory(cuda)
set(CMAKE_CUDA_FLAGS "-ccbin -Xcompiler -fPIC --std=c++11")
set(CUDA_NVCC_FLAGS "-Xcompiler -fPIC --std=c++11")
set(EXTRA_LIBS ${EXTRA_LIBS} hwgpu)
set(CUDA_LIBRARIES ${CUDA_TOOLKIT_ROOT_DIR}/lib64)
#release headers
include_directories(*.h)
include_directories(*.hpp)
include_directories(include/*.h)
include_directories(include/*.hpp)
include_directories(.)
include_directories(./include)
include_directories(./codessdkinclude/include)
include_directories(./ffmpeginclude/include)
# include_directories(./pybind11/include)
include_directories({PYTHON_INCLUDE_DIR})
include_directories(./Utils)
include_directories(${CUDA_TOOLKIT_INCLUDE})
# Preprocessor libs.
file(GLOB LIB_FILES ${CMAKE_SOURCE_DIR}/core/preprocess/nvdec-extractframe/lib/*.so)
file(GLOB CUDA_LIB_FILES ${CUDA_LIBRARIES}/*.so)
file(GLOB NVJPEG_LIBS ${CMAKE_SOURCE_DIR}/core/preprocess/nvdec-extractframe/lib/libnvjpeg.*)
file(GLOB SOURCE_FILES src/*.cpp NvDecoder/*.cpp pybind/*.cpp)
#.so
add_library(hwextract SHARED ${SOURCE_FILES})
target_link_libraries(hwextract ${CMAKE_SOURCE_DIR}/core/preprocess/nvdec-extractframe/lib/libnvjpeg.so)
target_link_libraries(hwextract ${EXTRA_LIBS})
target_link_libraries(hwextract ${LIB_FILES})
target_link_libraries(hwextract ${CUDA_LIB_FILES})
# execute_process(COMMAND rm ${CMAKE_SOURCE_DIR}/core/preprocess/nvdec-extractframe/preprocesslib.zip)
# hw-frame-extract
hw-frame-extract is a CV preprocessing library based on cuda. The project uses GPU for extracting frame from video. It speeds up the processing speed while increasing the utilization rate of the GPU.
## Preprocess API
Hwvideoframe provides a variety of cutting frame methods for different kind of video:
- class HwExtractFrameJpeg
- `init_handler(gpu_index)`
- gpu_index (int):Index of gpu.
- `extract_frame(file_path, n)`
- file_path (string): Video path.
- n (int): Cut n frames in one second.
- class HwExtractFrameBGRARaw
- `init_handler(gpu_index)`
- gpu_index (int):Index of gpu.
- `extract_frame(file_path, n)`
- file_path (string): Video path.
- n (int): Cut n frames in one second.
- class HwFrameResult
- `height()`
- Return height of frame.
- `width()`
- Return width of frame.
- `len()`
- Return len of frame.
- `free_memory()`
- Free memory of frames.
## Quick start
[After compiling from code](https://github.com/PaddlePaddle/Serving/blob/develop/doc/COMPILE.md),this project will be stored in reader。
## How to Test
Test file:Serving/python/paddle_serving_app/reader/test_preprocess.py
// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
//
// 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.
#include <string>
#include "ExtractFrameBase.h"
#ifndef CORE_PREPROCESS_NVDEC_EXTRACTFRAME_INCLUDE_EXTRACTFRAMEBGRARAW_H_
#define CORE_PREPROCESS_NVDEC_EXTRACTFRAME_INCLUDE_EXTRACTFRAMEBGRARAW_H_
namespace baidu {
namespace xvision {
class ExtractFrameBGRARaw : public ExtractFrameBase {
/**
* @name:
* ExtractFrameBGRARaw
* @author:
* chengang06@baidu.com
* @main feature:
* extract video and output bgr raw data
* @example:
*
**/
public:
explicit ExtractFrameBGRARaw(int gpu_index) : ExtractFrameBase(gpu_index) {}
ExtractFrameBGRARaw() {}
/**
* @Name:
* extract_frame
* @Feature:
* extract video frame frames from video file,
* @params
* file_path: video local path
* n: n frames per second
* @returns
* IMGDataList
**/
IMGDataList extract_frame(const std::string &file_path, int n = 1);
};
} // namespace xvision
} // namespace baidu
#endif // CORE_PREPROCESS_NVDEC_EXTRACTFRAME_INCLUDE_EXTRACTFRAMEBGRARAW_H_
// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
//
// 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.
#include <cuda.h>
#include <list>
#include <memory>
#include <string>
#include "NvDecoder/NvDecoder.h"
#include "Utils/FFmpegDemuxer.h"
#include "cuda/ColorSpace.h"
#ifndef CORE_PREPROCESS_NVDEC_EXTRACTFRAME_INCLUDE_EXTRACTFRAMEBASE_H_
#define CORE_PREPROCESS_NVDEC_EXTRACTFRAME_INCLUDE_EXTRACTFRAMEBASE_H_
namespace baidu {
namespace xvision {
class FrameResult {
/**
* @name:
* FrameResult
* @author:
* chengang06@baidu.com
* @main feature:
* store image info
* @example:
* None
**/
public:
// constructor
FrameResult() {
_height = 0;
_width = 0;
_p_frame = nullptr;
_cols = 0;
_rows = 0;
_thick = 0;
}
/*
FrameResult deepcopy() const {
FrameResult tmp;
std::cout << "copy constructor called" << std::endl;
tmp.set_height(_height);
tmp.set_width(_width);
tmp.set_cols(_cols);
tmp.set_rows(_rows);
tmp.set_thick(_thick);
auto frame_tmp = new uint8_t(this -> get_frame_buff_len());
std::copy(this -> get_frame(), this -> get_frame() + this ->
get_frame_buff_len(), frame_tmp);
tmp.set_frame_buffer(frame_tmp);
}
*/
// attributes
size_t rows() const { return _rows; }
size_t cols() const { return _cols; }
size_t thick() const { return _thick; }
size_t height() const { return _height; }
size_t width() const { return _width; }
size_t len() const { return _rows * _cols * _thick; }
void set_rows(const size_t rows) { _rows = rows; }
void set_cols(const size_t cols) { _cols = cols; }
void set_thick(const size_t thick) { _thick = thick; }
void set_width(const size_t width) { _width = width; }
void set_height(const size_t height) { _height = height; }
// free buffer data manually
void free_memory() {
if (_p_frame) {
delete[] _p_frame;
_p_frame = nullptr;
}
_height = 0;
_width = 0;
_rows = 0;
_cols = 0;
_thick = 0;
}
// set frame buffer
void set_frame_buffer(uint8_t* buff) {
if (_p_frame) {
delete[] _p_frame;
_p_frame = nullptr;
}
_p_frame = buff;
}
// get frame buffer
uint8_t* get_frame() const { return _p_frame; }
size_t get_frame_buff_len() const { return _rows * _cols * _thick; }
virtual ~FrameResult() {}
private:
uint8_t* _p_frame;
size_t _height, _width; // pic width and height
size_t _rows, _cols, _thick; // buffer sizes
};
typedef std::list<FrameResult> IMGDataList;
class ExtractFrameBase {
/**
* @name:
* ExtractFrameBase
* @author:
* chengang06@baidu.com
* @main feature:
* base class for extract frame
* @example:
*
**/
public:
explicit ExtractFrameBase(int gpu_index) {
this->gpu_index = gpu_index;
p_cu_context = nullptr;
}
ExtractFrameBase() {
gpu_index = 0;
p_cu_context = nullptr;
}
virtual int init();
virtual IMGDataList extract_frame(const std::string& file_path,
int n = 1) = 0;
virtual ~ExtractFrameBase() {
if (p_cu_context != nullptr) {
cuCtxDestroy(p_cu_context);
}
}
/**
* @name select_frame
* @param, frame_rate, double like 25.00,
* @param, pre_frame_time, int_64, last selected frame timestamp
* @param, cur_frame_time, int_64, current frame timestamp
* @param, fps, extract frame num per seconds
* @param, mode, 0, use time stamp to select frame, 1, use framerate to select
*frame
**/
static bool select_frame(const double frame_rate,
const int64_t pre_frame_time,
const int64_t cur_frame_time,
const size_t frame_index,
const double fps,
const int mode);
protected:
int gpu_index; // gpu index
CUcontext p_cu_context;
};
} // namespace xvision
} // namespace baidu
#endif // CORE_PREPROCESS_NVDEC_EXTRACTFRAME_INCLUDE_EXTRACTFRAMEBASE_H_
// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
//
// 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.
#include <nvjpeg.h>
#include <string>
#include "ExtractFrameBase.h"
#ifndef CORE_PREPROCESS_NVDEC_EXTRACTFRAME_INCLUDE_EXTRACTFRAMEJPEG_H_
#define CORE_PREPROCESS_NVDEC_EXTRACTFRAME_INCLUDE_EXTRACTFRAMEJPEG_H_
namespace baidu {
namespace xvision {
class ExtractFrameJpeg : public ExtractFrameBase {
/**
* @name:
* ExtractFrameJpeg
* @author:
* chengang06@baidu.com
* @main feature:
* extract video and output jpeg format data
* @example:
*
**/
public:
explicit ExtractFrameJpeg(int gpu_index) : ExtractFrameBase(gpu_index) {}
ExtractFrameJpeg() {}
/**
* @Name:
* extract_frame
* @Feature:
* extract video frame frames from video file,
* @params
* file_path: video local path
* n: n frames per second
* @returns
* IMGDataList
**/
IMGDataList extract_frame(const std::string& file_path, int n = 1);
int init();
virtual ~ExtractFrameJpeg() {
if (_nv_enc_params) {
nvjpegEncoderParamsDestroy(_nv_enc_params);
}
if (_nv_enc_state) {
nvjpegEncoderStateDestroy(_nv_enc_state);
}
if (_nv_jpeg_handler) {
nvjpegDestroy(_nv_jpeg_handler);
}
if (_cuda_stream) {
cudaStreamDestroy(_cuda_stream);
}
}
private:
/**
* @Name:
* jpeg_encode
* @Feature:
* use cuda to encode jpeg picture
* @params
* p_image, rgba raw pointer, can be memory on gpu card
* width, height: image size info
* FrameResult result, output, jpeg picture
* @returns
*
**/
int jpeg_encode(uint8_t* p_image,
int width,
int height,
const FrameResult& result);
nvjpegHandle_t _nv_jpeg_handler;
nvjpegEncoderState_t _nv_enc_state;
nvjpegEncoderParams_t _nv_enc_params;
cudaStream_t _cuda_stream;
};
} // namespace xvision
} // namespace baidu
#endif // CORE_PREPROCESS_NVDEC_EXTRACTFRAME_INCLUDE_EXTRACTFRAMEJPEG_H_
// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
//
// 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.
#include <pybind11/buffer_info.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include "ExtractFrameBGRARaw.h"
#include "ExtractFrameJpeg.h"
simplelogger::Logger* logger =
simplelogger::LoggerFactory::CreateConsoleLogger();
PYBIND11_MODULE(libhwextract, m) {
pybind11::class_<baidu::xvision::ExtractFrameJpeg>(m, "HwExtractFrameJpeg")
.def(pybind11::init<int>())
.def("init_handler", &baidu::xvision::ExtractFrameJpeg::init)
.def("extract_frame", &baidu::xvision::ExtractFrameJpeg::extract_frame);
pybind11::class_<baidu::xvision::ExtractFrameBGRARaw>(m,
"HwExtractFrameBGRARaw")
.def(pybind11::init<int>())
.def("init_handler", &baidu::xvision::ExtractFrameBGRARaw::init)
.def("extract_frame",
&baidu::xvision::ExtractFrameBGRARaw::extract_frame);
pybind11::class_<baidu::xvision::FrameResult>(
m, "HwFrameResult", pybind11::buffer_protocol())
.def(pybind11::init())
.def("height", &baidu::xvision::FrameResult::height)
.def("width", &baidu::xvision::FrameResult::width)
.def("len", &baidu::xvision::FrameResult::len)
.def("free_memory",
&baidu::xvision::FrameResult::free_memory) // for gcc 4.8.2 , this
// must be called ,both
// in cpp or python
// .def("__copy__", [](const baidu::xvision::FrameResult &self){return
// self.deepcopy();})
// .def("__deepcopy__", [](const baidu::xvision::FrameResult &self,
// pybind11::dict){return baidu::xvision::FrameResult(self);}, "memo"_a)
.def_buffer([](baidu::xvision::FrameResult& m) -> pybind11::buffer_info {
return pybind11::buffer_info(
m.get_frame(),
sizeof(uint8_t),
pybind11::format_descriptor<uint8_t>::format(),
2,
{m.rows(), m.cols()},
{sizeof(uint8_t) * m.cols(), sizeof(uint8_t)});
});
}
// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
//
// 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.
#include "ExtractFrameBGRARaw.h"
#include <nppi.h>
#include <memory>
#include <string>
baidu::xvision::IMGDataList baidu::xvision::ExtractFrameBGRARaw::extract_frame(
const std::string &file_path, int n) {
FFmpegDemuxer demuxer(file_path.c_str());
NvDecoder nvdec(
p_cu_context, true, FFmpeg2NvCodecId(demuxer.GetVideoCodec()));
size_t n_width = demuxer.GetWidth();
size_t n_height = demuxer.GetHeight();
double frame_rate = demuxer.GetFrameRate();
size_t n_frame_size = n_height * n_width * 4;
uint8_t *p_video = nullptr;
uint8_t **pp_frame = nullptr;
CUdeviceptr p_tmp_image = 0;
cuMemAlloc(&p_tmp_image, n_frame_size);
int n_video_bytes = 0;
int frame_count = -1;
int frame_returned = 0;
int64_t cur_frame_time(0), pre_frame_time(0), pts(0);
int64_t *p_timestamp = nullptr;
if (n == 0) {
n = 1000;
}
IMGDataList result_list;
do {
demuxer.Demux(&p_video, &n_video_bytes, &pts);
nvdec.Decode(p_video,
n_video_bytes,
&pp_frame,
&frame_returned,
0,
&p_timestamp,
pts);
for (auto i = 0; i < frame_returned; ++i) {
cur_frame_time = p_timestamp[i];
frame_count += 1;
if (!select_frame(
frame_rate, pre_frame_time, cur_frame_time, frame_count, n, 0)) {
continue;
}
pre_frame_time = cur_frame_time;
FrameResult fm_tmp;
fm_tmp.set_rows(n_height);
fm_tmp.set_cols(n_width);
fm_tmp.set_thick(4);
fm_tmp.set_frame_buffer(new uint8_t[n_frame_size]);
fm_tmp.set_height(n_height);
fm_tmp.set_width(n_width);
result_list.push_back(fm_tmp);
if (nvdec.GetBitDepth() == 8) {
if (nvdec.GetOutputFormat() == cudaVideoSurfaceFormat_YUV444) {
YUV444ToColor32<BGRA32>(reinterpret_cast<uint8_t *>(pp_frame[i]),
nvdec.GetWidth(),
reinterpret_cast<uint8_t *>(p_tmp_image),
4 * nvdec.GetWidth(),
nvdec.GetWidth(),
nvdec.GetHeight());
} else {
Nv12ToColor32<BGRA32>(reinterpret_cast<uint8_t *>(pp_frame[i]),
nvdec.GetWidth(),
reinterpret_cast<uint8_t *>(p_tmp_image),
4 * nvdec.GetWidth(),
nvdec.GetWidth(),
nvdec.GetHeight());
}
GetImage(p_tmp_image,
fm_tmp.get_frame(),
nvdec.GetWidth(),
4 * nvdec.GetHeight());
} else {
if (nvdec.GetOutputFormat() == cudaVideoSurfaceFormat_YUV444_16Bit) {
YUV444P16ToColor32<BGRA32>(reinterpret_cast<uint8_t *>(pp_frame[i]),
2 * nvdec.GetWidth(),
reinterpret_cast<uint8_t *>(p_tmp_image),
4 * nvdec.GetWidth(),
nvdec.GetWidth(),
nvdec.GetHeight());
} else {
P016ToColor32<BGRA32>(reinterpret_cast<uint8_t *>(pp_frame[i]),
nvdec.GetWidth(),
reinterpret_cast<uint8_t *>(p_tmp_image),
4 * nvdec.GetWidth(),
nvdec.GetWidth(),
nvdec.GetHeight());
}
GetImage(p_tmp_image,
fm_tmp.get_frame(),
nvdec.GetWidth(),
4 * nvdec.GetHeight());
}
/*GetImage((CUdeviceptr) pp_frame[i], reinterpret_cast<uint8_t
*>(fm_tmp.p_frame.get()),
nvdec.GetWidth(),
nvdec.GetHeight() + (nvdec.GetChromaHeight() *
nvdec.GetNumChromaPlanes()));*/
}
} while (n_video_bytes);
cuMemFree(p_tmp_image);
return result_list;
}
// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
//
// 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.
#include "ExtractFrameBase.h"
#include <cmath>
int baidu::xvision::ExtractFrameBase::init() {
ck(cuInit(0));
int gpu_sum = 0;
ck(cuDeviceGetCount(&gpu_sum));
if (gpu_sum < 0 || gpu_sum < this->gpu_index) {
return -1;
}
createCudaContext(&p_cu_context, gpu_index, 0);
return 0;
}
bool baidu::xvision::ExtractFrameBase::select_frame(
const double frame_rate,
const int64_t pre_frame_time,
const int64_t cur_frame_time,
const size_t frame_index,
const double fps,
const int mode) {
// TODO(Zelda): select frame function flattens ffmpeg FPS filter
bool ret = false;
int gap_time = 1000 / fps;
int64_t pre_frame_timestamp_in_sec = pre_frame_time / gap_time;
int64_t cur_frame_timestamp_in_sec = cur_frame_time / gap_time;
int i_frame_rate = std::round(
frame_rate); // frame to int, 24.9999 will be 25, 24.02 will be 24
int frame_gap = i_frame_rate / fps; // frame gap, 24.99 will be 24
if (frame_index == 0) {
ret = true;
}
switch (mode) {
case 0: // recommended , same as ffmpeg fps filter, round:inf
if (pre_frame_timestamp_in_sec != cur_frame_timestamp_in_sec) {
ret = true;
}
break;
case 1:
if (frame_index % frame_gap == 0) {
ret = true;
}
break;
default:
ret = false;
break;
}
return ret;
}
// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
//
// 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.
#include "ExtractFrameJpeg.h"
#include <nppi.h>
#include <memory>
#include <string>
int baidu::xvision::ExtractFrameJpeg::init() {
auto result = ExtractFrameBase::init();
if (result != 0) {
return result;
}
auto cuda_init = cudaStreamCreate(&_cuda_stream);
if (cuda_init != ::cudaError::cudaSuccess) {
return -2;
}
_nv_jpeg_handler = nullptr;
_nv_enc_state = nullptr;
_nv_enc_params = nullptr;
nvjpegStatus_t stats = nvjpegCreateSimple(&_nv_jpeg_handler);
// nvjpeg initialization error return -2
if (stats != nvjpegStatus_t::NVJPEG_STATUS_SUCCESS) {
return -2;
}
stats = nvjpegEncoderParamsCreate(
_nv_jpeg_handler, &_nv_enc_params, _cuda_stream);
if (stats != nvjpegStatus_t::NVJPEG_STATUS_SUCCESS) {
return -2;
}
// high quality
stats = nvjpegEncoderParamsSetQuality(_nv_enc_params, 100, _cuda_stream);
if (stats != nvjpegStatus_t::NVJPEG_STATUS_SUCCESS) {
return -2;
}
stats =
nvjpegEncoderStateCreate(_nv_jpeg_handler, &_nv_enc_state, _cuda_stream);
if (stats != nvjpegStatus_t::NVJPEG_STATUS_SUCCESS) {
return -2;
}
stats = nvjpegEncoderParamsSetSamplingFactors(
_nv_enc_params, NVJPEG_CSS_444, _cuda_stream);
if (stats != nvjpegStatus_t::NVJPEG_STATUS_SUCCESS) {
return -2;
}
return 0;
}
baidu::xvision::IMGDataList baidu::xvision::ExtractFrameJpeg::extract_frame(
const std::string &file_path, int n) {
FFmpegDemuxer demuxer(file_path.c_str());
NvDecoder nvdec(
p_cu_context, true, FFmpeg2NvCodecId(demuxer.GetVideoCodec()));
int n_width = demuxer.GetWidth();
int n_height = demuxer.GetHeight();
double frame_rate = demuxer.GetFrameRate();
int n_frame_size = n_width * n_height * 4; // rgbp depth 3 uint_8
uint8_t *p_video = nullptr;
uint8_t **pp_frame = nullptr;
int64_t *p_timestamp = nullptr;
CUdeviceptr p_tmp_image = 0;
cuMemAlloc(&p_tmp_image, n_frame_size);
int n_video_bytes = 0;
int frame_count = -1;
int frame_returned = 0;
int64_t pts = 0;
int64_t pre_frame_time = 0;
int64_t cur_frame_time = 0;
if (n == 0) {
n = 1000;
}
IMGDataList result_list;
do {
demuxer.Demux(&p_video, &n_video_bytes, &pts);
nvdec.Decode(p_video,
n_video_bytes,
&pp_frame,
&frame_returned,
0,
&p_timestamp,
pts);
for (auto i = 0; i < frame_returned; ++i) {
cur_frame_time = p_timestamp[i];
frame_count += 1;
if (!select_frame(
frame_rate, pre_frame_time, cur_frame_time, frame_count, n, 0)) {
continue;
}
pre_frame_time = cur_frame_time;
FrameResult fm_tmp;
fm_tmp.set_height(nvdec.GetHeight());
fm_tmp.set_width(nvdec.GetWidth());
if (nvdec.GetBitDepth() == 8) {
if (nvdec.GetOutputFormat() == cudaVideoSurfaceFormat_YUV444) {
YUV444ToColorPlanar<RGBA32>(reinterpret_cast<uint8_t *>(pp_frame[i]),
nvdec.GetWidth(),
reinterpret_cast<uint8_t *>(p_tmp_image),
nvdec.GetWidth(),
nvdec.GetWidth(),
nvdec.GetHeight());
} else {
Nv12ToColorPlanar<RGBA32>(reinterpret_cast<uint8_t *>(pp_frame[i]),
nvdec.GetWidth(),
reinterpret_cast<uint8_t *>(p_tmp_image),
nvdec.GetWidth(),
nvdec.GetWidth(),
nvdec.GetHeight());
}
} else {
if (nvdec.GetOutputFormat() == cudaVideoSurfaceFormat_YUV444_16Bit)
YUV444P16ToColorPlanar<RGBA32>(
reinterpret_cast<uint8_t *>(pp_frame[i]),
2 * nvdec.GetWidth(),
reinterpret_cast<uint8_t *>(p_tmp_image),
nvdec.GetWidth(),
nvdec.GetWidth(),
nvdec.GetHeight());
else
P016ToColorPlanar<RGBA32>(reinterpret_cast<uint8_t *>(pp_frame[i]),
2 * nvdec.GetWidth(),
reinterpret_cast<uint8_t *>(p_tmp_image),
nvdec.GetWidth(),
nvdec.GetWidth(),
nvdec.GetHeight());
}
jpeg_encode(reinterpret_cast<uint8_t *>(p_tmp_image),
nvdec.GetWidth(),
nvdec.GetHeight(),
fm_tmp);
result_list.push_back(fm_tmp);
}
} while (n_video_bytes);
cuMemFree(p_tmp_image);
return result_list;
}
int baidu::xvision::ExtractFrameJpeg::jpeg_encode(uint8_t *p_image,
int width,
int height,
FrameResult &result) {
nvjpegImage_t nv_image;
nv_image.channel[0] = p_image;
nv_image.channel[1] = p_image + width * height;
nv_image.channel[2] = p_image + width * height * 2;
nv_image.pitch[0] = width;
nv_image.pitch[1] = width;
nv_image.pitch[2] = width;
auto stat = nvjpegEncodeImage(_nv_jpeg_handler,
_nv_enc_state,
_nv_enc_params,
&nv_image,
NVJPEG_INPUT_RGB,
width,
height,
_cuda_stream);
if (stat != nvjpegStatus_t::NVJPEG_STATUS_SUCCESS) {
return -1;
}
size_t len(0);
stat = nvjpegEncodeRetrieveBitstream(
_nv_jpeg_handler, _nv_enc_state, nullptr, &len, _cuda_stream);
auto cuda_stat = cudaStreamSynchronize(_cuda_stream);
if (cuda_stat != ::cudaSuccess) {
return -1;
}
result.set_frame_buffer(new uint8_t[len]);
result.set_width(width);
result.set_height(height);
result.set_rows(len);
result.set_cols(1);
result.set_thick(1);
// jpeg, rows: len, cols:1, thick:height
stat = nvjpegEncodeRetrieveBitstream(
_nv_jpeg_handler, _nv_enc_state, result.get_frame(), &len, _cuda_stream);
if (stat != nvjpegStatus_t::NVJPEG_STATUS_SUCCESS) {
return -1;
}
cuda_stat = cudaStreamSynchronize(_cuda_stream);
if (cuda_stat != ::cudaSuccess) {
return -1;
}
return 0;
}
......@@ -11,6 +11,7 @@
# 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.
# pylint: disable=doc-string-missing
from .chinese_bert_reader import ChineseBertReader
from .image_reader import ImageReader, File2Image, URL2Image, Sequential, Normalize, Base64ToImage
from .image_reader import CenterCrop, Resize, Transpose, Div, RGB2BGR, BGR2RGB, ResizeByFactor
......@@ -22,4 +23,3 @@ from .imdb_reader import IMDBDataset
from .ocr_reader import OCRReader
from libgpupreprocess import Image2Gpubuffer, Gpubuffer2Image, RGB2BGR, BGR2RGB
from libgpupreprocess import Div, Sub, Normalize, CenterCrop, Resize, ResizeByFactor
from libhwextract import HwExtractFrameJpeg, HwExtractFrameBGRARaw, HwFrameResult
......@@ -149,30 +149,6 @@ class TestOperators(unittest.TestCase):
img_resize_diff = img_vis - img
self.assertEqual(np.all(img_resize_diff == 0), True)
def test_extract_frame(self):
handler = libhwextract.HwExtractFrameJpeg(0)
# 0, gpu card index
# if you want BGRA Raw Data, plz use HwExtractBGRARaw
handler.init_handler()
# init once can decode many videos
video_file_name = sys.argv[1]
# for now just support h264 codec
frame_list = []
try:
frame_list = handler.extract_frame(video_file_name, 1)
# specifiy file name and fps you want to extract, 0 for all frame
except Exception as e_frame:
print("Failed to cutframe, exception[%s]" % (e_frame))
sys.exit(1)
for item in frame_list:
print "i am a item in frame_list"
# do something, for instance
jpeg_array = np.array(item, copy=False)
img = cv2.imdecode(jpeg_array, cv2.IMREAD_COLOR)
cv2.imwrite('1.jpg', img)
item.free_memory()
# have to release memor
if __name__ == '__main__':
unittest.main()
......@@ -44,10 +44,7 @@ if os.path.exists('../core/preprocess/hwvideoframe/libgpupreprocess.so'):
print("新建目录")
os.system('mkdir -p ./paddle_serving_app/reader/lib')
os.system('cp ../core/preprocess/hwvideoframe/libgpupreprocess.so ./paddle_serving_app/reader')
os.system('cp ../core/preprocess/nvdec-extractframe/libhwextract.so ./paddle_serving_app/reader')
os.system('cp ../core/preprocess/hwvideoframe/cuda/libgpu.so ./paddle_serving_app/reader/lib')
os.system('cp ../core/preprocess/nvdec-extractframe/cuda/libhwgpu.so ./paddle_serving_app/reader/lib')
os.system('cp -a -i ../../core/preprocess/nvdec-extractframe/lib/* ./paddle_serving_app/reader/lib')
os.system('export LD_LIBRARY_PATH="./paddle_serving_app/reader/lib"')
REQUIRED_PACKAGES = [
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册