zoukankan      html  css  js  c++  java
  • 编译ffmpeg(第一次),实现JPG转MP4

    ffpmeg网址:http://ffmpeg.org/

    ffmpegapi文档:http://ffmpeg.org/doxygen/trunk/index.html

    因为这是JPG转MP4,所以不涉及音频部分,可参考例子解码:http://ffmpeg.org/doxygen/trunk/decode_video_8c-example.html 编码:http://ffmpeg.org/doxygen/trunk/encode_video_8c-example.html

    一、读取到的JPG图像内容需要解码:

    1、打开一个解码器需要的内容

    AVCodec* pDecodec;
    AVCodecContext* pDecodecCtx;
    AVFrame* pDeFrame;
    AVPacket pDePacket;
    //读取jpg用的解码器mjpeg
    pDecodec = avcodec_find_decoder(AV_CODEC_ID_MJPEG);
    //获取解码器上下文
    pDecodecCtx = avcodec_alloc_context3(pDecodec);
    pDecodecCtx->width = 512;
    pDecodecCtx->height = 512;
    pDecodecCtx->pix_fmt = AV_PIX_FMT_RGB24;
    //打开解码器
    avcodec_open2(pDecodecCtx,pDecodec,NULL);
    

    2、解码操作

    //用一个avstream来接收解码的数据帧
    pDeFrame = av_frame_alloc();
    //初始化一个ffmpeg的数据包
    av_init_packet(&pDePacket);
    unsigned char *jpgdata = new unsigned char[2048*2048];
    FILE *file;
    file = fopen([需要打开的文件全路径], "rw");
    int readlen = fread(jpgdata, 1, 2048*2048, file);
    //调用解码器解码
    avcodec_decode_video2(pDecodecCtx,pDeFrame,&deCFflag,&pDePacket);
    

    二、创建打开编码器

    AVCodec* pEncodec;
    AVCodecContext* pEncodecCtx;
    AVFrame* pEnFrame;
    AVPacket pEnPacket;
    
    pEncodecCtx = pVideoStream->codec;
    pEncodecCtx->codec_id = pOutPutFormatCtx->oformat->video_codec;
    pEncodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
    pEncodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
    pEncodecCtx->width = 720;
    pEncodecCtx->height = 576;
    //pEncodecCtx->bit_rate = 400000; 码流 适用于网络传输
    pEncodecCtx->gop_size = 1;
    pEncodecCtx->time_base.num = 1;
    pEncodecCtx->time_base.den = 25;
    pEncodecCtx->qmin = 10;
    pEncodecCtx->qmax = 51;
    pEncodecCtx->max_b_frames=3;
    //质量 文件
    pEncodecCtx->bit_rate = 0;
    av_opt_set_int(pEncodecCtx->priv_data,"crf",0,0);
    //在文件头写入文件信息(默认在每个包写入文件信息,微软默认播放器可能播放不了)
    pEncodecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
    //找一个视频编码器
    pEncodec = avcodec_find_encoder(pEncodecCtx->codec_id);
    //打开编码器
    avcodec_open2(pEncodecCtx,pEncodec,NULL); int picture_size =0;
    uint8_t* picture_buf;
    //初始换编码用avframe pEnFrame
    = av_frame_alloc();
    //编码的图像大小 picture_size
    = avpicture_get_size(pEncodecCtx->pix_fmt,pEncodecCtx->width,pEncodecCtx->height);
    //编码图像buf picture_buf
    = (uint8_t *)av_malloc(picture_size);
    //关联相关属性 avpicture_fill((AVPicture
    *)pEnFrame,picture_buf, pEncodecCtx->pix_fmt,pEncodecCtx->width,pEncodecCtx->height); pEnFrame->width = pEncodecCtx->width; pEnFrame->height = pEncodecCtx->height; pEnFrame->format = pEncodecCtx->pix_fmt;
    //初始话编码的包 av_init_packet(
    &pEnPacket);

    三、输出文件的信息

    AVFormatContext* pOutPutFormatCtx;
    AVStream* pVideoStream;
    
    avformat_alloc_output_context2(&pOutPutFormatCtx, NULL, NULL, [输出的文件全路径].c_str());
    pVideoStream = avformat_new_stream(pOutPutFormatCtx, NULL);
    avio_open(&pOutPutFormatCtx->pb,[输出的文件全路径],AVIO_FLAG_READ_WRITE); 
    av_dump_format(pOutPutFormatCtx,
    0,[输出的文件全路径],1);
    //将编码器的信息与输出的信息属性关联起来
    avcodec_parameters_from_context(pVideoStream->codecpar,pEncodecCtx);
    av_codec_get_tag2(pOutPutFormatCtx->oformat->codec_tag, pEncodecCtx->codec_id, &pVideoStream->codecpar->codec_tag);
    //写输出的文件的头 avformat_write_header(pOutPutFormatCtx,NULL);

    四、转码,将用解码器打开的jpg文件转码成需要编码的Frame格式

    //FFmpeg的一个转换类
    SwsContext* pImagectx;
    
    pImagectx = sws_getContext(pDecodecCtx->width, pDecodecCtx->height, pDecodecCtx->pix_fmt,pEncodecCtx->width,pEncodecCtx->height, pEncodecCtx->pix_fmt,SWS_BICUBIC, NULL,NULL, NULL);
    
    sws_scale(pImagectx,pDeFrame->data,pDeFrame->linesize,0,pDeFrame->height,pEnFrame->data,pEnFrame->linesize);

     五、编码写文件

    注释信息为测试读取文件的逻辑
    //snprintf(imagename, 255, "%d.jpg", i);//X.jpg //string imagefilePath = dir + imagename; //printf("---"); //printf(imagefilePath.c_str()); //printf(" "); //FILE *file; //file = fopen(imagefilePath.c_str(), "rw"); //int readlen = fread(jpgdata, 1, 2048*2048, file); //printf("----read file success %d ",readlen); //fclose(file); //pDePacket.data = jpgdata; //pDePacket.size = readlen; //int decodecresult = avcodec_decode_video2(pDecodecCtx,pDeFrame,&deCFflag,&pDePacket); //printf("----decodecresult %d ",decodecresult); //sws_scale(pImagectx,pDeFrame->data,pDeFrame->linesize,0,pDeFrame->height,pEnFrame->data,pEnFrame->linesize); int gotpicture = 0; pEnFrame->pts = i;
    //编码
    avcodec_encode_video2(pEncodecCtx,
    &pEnPacket,pEnFrame,&gotpicture); //printf("----encodecresult %d ",gotpicture); pEnPacket.pts = av_rescale_q(pEnPacket.pts, rational, pVideoStream->time_base); pEnPacket.stream_index = pVideoStream->index;
    //将编码得到的包写入输出文件 av_write_frame(pOutPutFormatCtx,
    &pEnPacket);
    //写文件尾
    av_write_trailer(
    pOutPutFormatCtx);

    六、释放资源

    av_free_packet(&pDePacket);
        if(pDeFrame != NULL)
        {
            av_free(pDeFrame);
        }
        if(pDecodecCtx != NULL)
        {
             avcodec_close(pDecodecCtx);
        }
    av_free_packet(&pEnPacket);
        if(pEnFrame != NULL)
        {
            av_free(pEnFrame);
        }
        if(pEncodecCtx != NULL)
        {
             avcodec_close(pEncodecCtx);
        }
    
    if(pOutPutFormatCtx!= NULL)
        {
            avformat_free_context(pOutPutFormatCtx);
        }
        if(pVideoStream != NULL)
        {
            av_free(pVideoStream);
        }
    if(pImagectx != NULL)
        {
            sws_freeContext(pImagectx);
        }
  • 相关阅读:
    js常用代码整理
    java 序列化时排除指定属性
    FastJson bean序列化属性顺序问题
    用logger在控制台打印信息
    UNITY 内存问题资料收集
    数组指针和指针数组的区别
    inl文件介绍
    C++防止文件重复包含
    VS2017 Intelligense C++ 设置的几个重点
    GPU架构图
  • 原文地址:https://www.cnblogs.com/zebra-bin/p/12788568.html
Copyright © 2011-2022 走看看