pybind 编码264
#include
#include
#include
using namespace std;
#include
#include
#include
#ifdef __cplusplus
extern "C"
{
#endif
#include
#include
#include
#include
#include
#include
#include
#ifdef __cplusplus
};
#endif
namespace py = pybind11;
int add(int i, int j)
{
return i + j+2000;
}
// display console
void OpenConsole()
{
// create a console
AllocConsole();
// FreeConsole();
}
void GetImage(py::array_t input1)
{
py::buffer_info buf1 = input1.request();
OpenConsole();
printf("dim len:%d ", buf1.ndim);
for (int cnt = 0; cnt < buf1.ndim; cnt++)
{
printf("dim size %d : %d ", cnt, buf1.shape[cnt]);
}
unsigned char *ptr1 = (unsigned char *)buf1.ptr;
printf("image data: %d %d %d %d %d %d\n", ptr1[0], ptr1[1], ptr1[2], ptr1[3], ptr1[4], ptr1[5]);
}
#include
int gettimeofday(struct timeval *tp, void *tzp)
{
time_t clock;
struct tm tm;
SYSTEMTIME wtm;
GetLocalTime(&wtm);
tm.tm_year = wtm.wYear - 1900;
tm.tm_mon = wtm.wMonth - 1;
tm.tm_mday = wtm.wDay;
tm.tm_hour = wtm.wHour;
tm.tm_min = wtm.wMinute;
tm.tm_sec = wtm.wSecond;
tm.tm_isdst = -1;
clock = mktime(&tm);
tp->tv_sec = clock;
tp->tv_usec = wtm.wMilliseconds * 1000;
return (0);
}
/*
This device demo will connect to url as a channel, the chnum is the channel of this device,
this device will connect chnum times to the url.
*/
class Rtmp_tool {
public:
int nWidth = 0;
int nHeight = 0;
int pts_value = 0;
AVCodecContext *c;
AVFrame *m_pRGBFrame = new AVFrame[1]; //RGB帧数据
AVFrame *m_pYUVFrame; //YUV帧数据
uint8_t * yuv_buff;//
SwsContext * scxt;
FILE *f = NULL;
AVFormatContext *ofmt_ctx = NULL;
};
void* pre_save(char* filepath, int width, int height, int frame_rate) {
//void* pre_save(std::string & filepath, int width, int height, int frame_rate) {
av_log_set_level(AV_LOG_ERROR);
Rtmp_tool *rtmp_tool;
rtmp_tool = new Rtmp_tool();
int nLen;
int fileI;
rtmp_tool->nWidth = width;
rtmp_tool->nHeight = height;
AVCodecContext *c = NULL;
AVCodecContext *in_c = NULL;
AVCodec *pCodecH264; //编码器
pCodecH264 = avcodec_find_encoder(AV_CODEC_ID_H264);//查找h264编码器
c = avcodec_alloc_context3(pCodecH264);
if (!c)
{
printf("Could not allocate video codec context\n");
exit(1);
}
//av_opt_set(c->priv_data, "preset", "slow", 0);
av_opt_set(c->priv_data, "preset", "superfast", 0);
av_opt_set(c->priv_data, "tune", "zerolatency", 0);
c->bit_rate = 1024 * 1024;// put sample parameters
c->width = width;
c->height = height;
c->time_base.den = frame_rate;//视频每秒帧数
c->time_base.num = 1;
c->framerate.den = 1;//视频帧速
c->framerate.num = frame_rate;
c->gop_size = 20; // emit one intra frame every ten frames
c->max_b_frames = 0;
c->thread_count = 1;
c->pix_fmt = AV_PIX_FMT_YUV420P;//PIX_FMT_RGB24;
//打开编码器
if (avcodec_open2(c, pCodecH264, NULL)<0)
printf("不能打开编码库");
int size = c->width * c->height;
rtmp_tool->yuv_buff = (uint8_t *)malloc((size * 3) / 2); // size for YUV 420
rtmp_tool->f = fopen(filepath, "wb");
//rtmp_tool->f = fopen(filepath.data(), "wb");
if (!rtmp_tool->f)
{
printf("could not open %s\n", filepath);
exit(1);
}
printf("context3 w h %d %d\n", c->width, c->height);
AVFrame *frame = av_frame_alloc();
if (!frame) {
fprintf(stderr, "Could not allocate video frame\n");
exit(1);
}
frame->format = c->pix_fmt;
frame->width = c->width;
frame->height = c->height;
int ret = av_frame_get_buffer(frame, 32);
if (ret < 0)
{
printf("Could not allocate the video frame data\n");
exit(1);
}
//初始化格式转换器SwsContext
rtmp_tool->scxt = sws_getContext(c->width, c->height, AV_PIX_FMT_BGR24, c->width, c->height, AV_PIX_FMT_YUV420P, SWS_POINT, NULL, NULL, NULL);
rtmp_tool->m_pYUVFrame = frame;
rtmp_tool->c = c;
return rtmp_tool;
}
int save_frame(py::array_t input1, int len, void* vp){//, void* service) {
Rtmp_tool *rtmp_tool = (Rtmp_tool *)vp;
//DemoDevice *pDev = (DemoDevice *)service;
av_log_set_level(AV_LOG_WARNING);
py::buffer_info buf1 = input1.request();
/*for (int i = 0; i < len; i++) {
plus1[i] = (uint8_t)plus1[i];
}*/
unsigned char *ptr1 = (unsigned char *)buf1.ptr;
AVCodecContext *c = rtmp_tool->c;// (AVCodecContext*)vp;
AVPacket *avpkt;
AVFrame *m_pRGBFrame = rtmp_tool->m_pRGBFrame;
AVFrame *m_pYUVFrame = rtmp_tool->m_pYUVFrame;
av_image_fill_arrays(m_pRGBFrame->data, m_pRGBFrame->linesize, (uint8_t*)ptr1, AV_PIX_FMT_RGB24, rtmp_tool->nWidth, rtmp_tool->nHeight, 1);
m_pRGBFrame->width = rtmp_tool->nWidth;
m_pRGBFrame->height = rtmp_tool->nHeight;
av_image_fill_arrays(m_pYUVFrame->data, m_pYUVFrame->linesize, (uint8_t*)rtmp_tool->yuv_buff, AV_PIX_FMT_YUV420P, c->width, c->height, 1);
int ret = av_frame_make_writable(m_pYUVFrame);//检测帧对象是否可读
if (ret < 0) {
printf("av_frame_make_writable %d\n", ret);
exit(1);
}
sws_scale(rtmp_tool->scxt, (uint8_t * const *)m_pRGBFrame->data, m_pRGBFrame->linesize, 0, c->height, m_pYUVFrame->data, m_pYUVFrame->linesize);
//m_pYUVFrame->pts++;
//将RGB转化为YUV
//sws_scale(rtmp_tool->scxt, m_pRGBFrame->data, m_pRGBFrame->linesize, 0, c->height, m_pYUVFrame->data, m_pYUVFrame->linesize);
int got_packet_ptr = 0;
avpkt = av_packet_alloc();
int send_ret = avcodec_send_frame(c, m_pYUVFrame);
m_pYUVFrame->pts++;
//printf("avcodec_send_frame %d\n", send_ret);
if (ret < 0)
{
printf("Error sending a frame for encoding\n");
exit(1);
}
while (ret >= 0)
{
ret = avcodec_receive_packet(c, avpkt);
if (ret != 0) {
if (ret == -11 || ret == AVERROR(EAGAIN)) {//-11
//printf("avcodec_receive_packet AVERROR(EAGAIN)\n");
}
else if (ret == AVERROR(EINVAL)) {//-22
printf("avcodec_receive_packet AVERROR(EINVAL)\n");
}
else {
printf("avcodec_receive_packet error %d\n", ret);
}
return ret;
}
//printf("Write packet %3(size=%5d)\n", avpkt->pts, avpkt->size);
fwrite(avpkt->data, 1, avpkt->size, rtmp_tool->f);
av_packet_unref(avpkt);
}
return 0;
}
PYBIND11_MODULE(example, m)
{
// optional module docstring
m.doc() = "pybind11 example plugin";
// expose add function, and add keyword arguments and default arguments
m.def("add", &add, "A function which adds two numbers", py::arg("i") = 1, py::arg("j") = 2);
// exporting variables
m.attr("the_answer") = 42;
py::object world = py::cast("World");
m.attr("what") = world;
m.def("GetImage", &GetImage, "Get NumPy arrays");
m.def("pre_save", &pre_save, "pre_save");
m.def("save_frame", &save_frame, "pre_save");
}