读取摄像头的图像,转为原始二进制码流vector
以下为C++代码中的转换函数,需要在ubuntu中预装FFmpeg库才可以使用。
#include "MjpegtoH264.h"
FILE* outPath;
AVCodec* dec;
AVCodecContext* dec_ctx;
AVCodec* enc;
AVCodecContext* enc_ctx;
SwsContext* sws_cxt;
AVFrame* src_frame;
AVPacket src_packet;
AVFrame* dst_frame;
int dst_size;
AVPacket dst_packet;
bool InitMjpegToH264(const std::string file_name) {
outPath = fopen(file_name.c_str(), "wb");
av_register_all();
dec = avcodec_find_decoder(AV_CODEC_ID_MJPEG);
dec_ctx = avcodec_alloc_context3(dec);
dec_ctx->width = WIDTH;
dec_ctx->height = HEIGHT;
dec_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
if (dec->capabilities & CODEC_CAP_TRUNCATED) dec_ctx->flags|= CODEC_FLAG_TRUNCATED;
if (avcodec_open2(dec_ctx, dec,NULL) < 0) {
std::cout<< "avcodec_open2 Error" <width = WIDTH;
enc_ctx->height = HEIGHT;
enc_ctx->bit_rate = 1024;
enc_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
enc_ctx->time_base.den = FRAME;
enc_ctx->time_base.num = 1;
enc_ctx->gop_size = 12;
enc_ctx->max_b_frames = 0;
av_opt_set(enc_ctx->priv_data, "preset", "slow", 0);
//av_opt_set(enc_ctx->priv_data, "tune", "zerolatency", 0);
if (avcodec_open2(enc_ctx,enc,NULL)<0)
{
std::cout << "avcodec_open2 Error" << std::endl;
return false;
}
sws_cxt = sws_getContext(dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt, enc_ctx->width,
enc_ctx->height, enc_ctx->pix_fmt, SWS_BILINEAR, NULL, NULL, NULL);
src_frame = av_frame_alloc();
av_init_packet(&src_packet);
src_packet.data = NULL;
src_packet.size = 0;
dst_frame = av_frame_alloc();
dst_size = av_image_alloc(dst_frame->data, dst_frame->linesize, enc_ctx->width, enc_ctx->height, enc_ctx->pix_fmt, 32);
dst_frame->width = enc_ctx->width;
dst_frame->height = enc_ctx->height;
dst_frame->format = (int)enc_ctx->pix_fmt;
dst_frame->pts = 0;
av_init_packet(&dst_packet);
dst_packet.data = NULL;
dst_packet.size = 0;
return true;
}
bool MjpegToH264(std::vector& buff, int frame_id) {
src_packet.data = (uint8_t *)buff.data();
src_packet.size = buff.size();
int got_frame = 0;
if(avcodec_decode_video2(dec_ctx, src_frame, &got_frame, &src_packet ) < 0)
{
std::cout << "avcodec_decode_video2 error" <data, src_frame->linesize, 0, src_frame->height, dst_frame->data, dst_frame->linesize);
int got_packet = 0;
dst_packet.pts = dst_packet.dts = dst_frame->pts;
if (avcodec_encode_video2(enc_ctx, &dst_packet, dst_frame, &got_packet) < 0) {
std::cout<< "avcodec_encode_video2 error" <pts = frame_id * 1000;
}
}
return true;
}
bool CloseH264File() {
// delete(dec);
// dec = nullptr;
// delete(dec_ctx);
// dec_ctx = nullptr;
// delete(enc);
// enc = nullptr;
// delete(enc_ctx);
// enc_ctx = nullptr;
// delete(sws_cxt);
// sws_cxt = nullptr;
// delete(src_frame);
// src_frame = nullptr;
// delete(dst_frame);
// dst_frame = nullptr;
fclose(outPath);
}
以下是头文件:
#include
#include
#include
#include
#include
#include
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/avutil.h"
#include "libavutil/opt.h"
#include "libavutil/imgutils.h"
};
#define WIDTH 1280
#define HEIGHT 720
#define FRAME 30
bool InitMjpegToH264(const std::string file_name);
bool MjpegToH264(std::vector& buff, int frame_id);
bool CloseH264File();