提交 d792d942 编写于 作者: B BohaoWu

Reduce PR.

上级 d27a0f3b
...@@ -9,5 +9,4 @@ if (${CUDA_VERSION} LESS 10.0) ...@@ -9,5 +9,4 @@ if (${CUDA_VERSION} LESS 10.0)
return() return()
elseif (${CUDA_VERSION} LESS 10.1) # CUDA 10.0 elseif (${CUDA_VERSION} LESS 10.1) # CUDA 10.0
add_subdirectory(hwvideoframe) add_subdirectory(hwvideoframe)
add_subdirectory(nvdec-extractframe)
endif() 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 @@ ...@@ -11,6 +11,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# pylint: disable=doc-string-missing
from .chinese_bert_reader import ChineseBertReader from .chinese_bert_reader import ChineseBertReader
from .image_reader import ImageReader, File2Image, URL2Image, Sequential, Normalize, Base64ToImage from .image_reader import ImageReader, File2Image, URL2Image, Sequential, Normalize, Base64ToImage
from .image_reader import CenterCrop, Resize, Transpose, Div, RGB2BGR, BGR2RGB, ResizeByFactor from .image_reader import CenterCrop, Resize, Transpose, Div, RGB2BGR, BGR2RGB, ResizeByFactor
...@@ -22,4 +23,3 @@ from .imdb_reader import IMDBDataset ...@@ -22,4 +23,3 @@ from .imdb_reader import IMDBDataset
from .ocr_reader import OCRReader from .ocr_reader import OCRReader
from libgpupreprocess import Image2Gpubuffer, Gpubuffer2Image, RGB2BGR, BGR2RGB from libgpupreprocess import Image2Gpubuffer, Gpubuffer2Image, RGB2BGR, BGR2RGB
from libgpupreprocess import Div, Sub, Normalize, CenterCrop, Resize, ResizeByFactor from libgpupreprocess import Div, Sub, Normalize, CenterCrop, Resize, ResizeByFactor
from libhwextract import HwExtractFrameJpeg, HwExtractFrameBGRARaw, HwFrameResult
...@@ -149,30 +149,6 @@ class TestOperators(unittest.TestCase): ...@@ -149,30 +149,6 @@ class TestOperators(unittest.TestCase):
img_resize_diff = img_vis - img img_resize_diff = img_vis - img
self.assertEqual(np.all(img_resize_diff == 0), True) 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__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -44,10 +44,7 @@ if os.path.exists('../core/preprocess/hwvideoframe/libgpupreprocess.so'): ...@@ -44,10 +44,7 @@ if os.path.exists('../core/preprocess/hwvideoframe/libgpupreprocess.so'):
print("新建目录") print("新建目录")
os.system('mkdir -p ./paddle_serving_app/reader/lib') 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/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/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"') os.system('export LD_LIBRARY_PATH="./paddle_serving_app/reader/lib"')
REQUIRED_PACKAGES = [ REQUIRED_PACKAGES = [
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册