Ubuntu FFmpeg Mjpeg to H264

读取摄像头的图像,转为原始二进制码流vector,加上序列帧的下标ID,利用FFmpeg库中的AV_CODEC_ID_H264编码器进行压缩,转为h264视频流。

以下为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();

 

你可能感兴趣的:(C++)