FFMPEG按比例缩放YUV视频

218 阅读1分钟

sws_scale函数

void FFmpegPLay::playScaleInternal(float scaleW,float scaleH)
{
    if (filePath_.isEmpty())
    {
        QMessageBox::warning(nullptr,"warn","未选择文件",QMessageBox::Ok);
        return;
    }
    std::string input_file=filePath_.toStdString();

    av_register_all();
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    if (avformat_open_input(&pFormatCtx,input_file.c_str(),nullptr,nullptr) < 0)
    {
        qDebug() << "fail to find the stream\n";
        return;
    }
    if (avformat_find_stream_info(pFormatCtx,NULL) < 0)
    {
        qDebug() << "fail to find the stream info\n";
        return;
    }
   // av_dump_format(pFormatCtx,0,input_file.c_str(),0);

    int video_stream_index = -1;
    for (size_t i =0;i < pFormatCtx->nb_streams ;++i )
    {
        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            video_stream_index = i;
            break;
        }
    }
    if (video_stream_index == -1)
    {
        qDebug() << "fail to find the video stream";
        return;
    }

    AVCodecContext *pCodecCtx = pFormatCtx->streams[video_stream_index]->codec;
    AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
    if (pCodec == NULL)
    {
        qDebug() << "fail to find the decoder\n";
        return;
    }
    if (avcodec_open2(pCodecCtx,pCodec,nullptr) < 0 )
    {
        qDebug() << "fail to open the decodec\n";
        return;
    }

    AVFrame *pFrame = av_frame_alloc();
    AVFrame *pframeRGB = av_frame_alloc();

    unsigned char *out_buffer = (unsigned char*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_RGB32,pCodecCtx->width*scaleW,pCodecCtx->height*scaleH,1));
    av_image_fill_arrays(pframeRGB->data,pframeRGB->linesize,out_buffer,AV_PIX_FMT_RGB32,pCodecCtx->width*scaleW,pCodecCtx->height*scaleH,1);

    AVPacket *pkt = av_packet_alloc();
    av_init_packet(pkt);
    SwsContext *pSwsCtx = sws_alloc_context();

    emit calSize(pCodecCtx->width*scaleW,pCodecCtx->height*scaleH);

    pSwsCtx = sws_getContext(pCodecCtx->width,pCodecCtx->height,pCodecCtx->pix_fmt,
                             pCodecCtx->width*scaleW,pCodecCtx->height*scaleH,AV_PIX_FMT_RGB32,
                             SWS_BICUBIC,nullptr,nullptr,nullptr);

    int got_frame = 0;
    while(av_read_frame(pFormatCtx,pkt) >= 0)
    {
        if (pkt->stream_index == video_stream_index){
            int ret = avcodec_decode_video2(pCodecCtx,pFrame,&got_frame,pkt);
            if (ret < 0)
            {
                qDebug() << "fail to decode video\n";
                return;
            }
           if (got_frame > 0)
            {
                sws_scale(pSwsCtx,(const unsigned char* const*)pFrame->data,pFrame->linesize,0,pCodecCtx->height,pframeRGB->data,pframeRGB->linesize);
                QImage image = QImage((unsigned char*)pframeRGB->data[0],pCodecCtx->width*scaleW,pCodecCtx->height*scaleH,QImage::Format_RGB32,nullptr,nullptr);
                emit genImage(image);
                usleep(30000);
            }
        }
        av_packet_unref(pkt);
    }

    sws_freeContext(pSwsCtx);
    av_packet_free(&pkt);
    avformat_close_input(&pFormatCtx);
    avformat_free_context(pFormatCtx);

    emit palyFinished();
}

测试结果

2倍大小 Screenshot from 2022-12-01 15-26-19.png 0.5倍大小

Screenshot from 2022-12-01 15-27-04.png

1倍大小

Screenshot from 2022-12-01 15-27-54.png