jodan feng
jodan feng

Reputation: 1

When decoding a video using ffmpeg and playing it with qt, the image is not refreshed

This is the code in the main thread.

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    Ffplay f;
    QObject::connect(&f,&Ffplay::send,&w,&MainWindow::paint);
    w.show();
    f.start();
    return a.exec();
}

MainWindow is the form that displays images.Ffplay is a thread used for decoding.Ffplay::send() is a function that sends the decoded image to the main thread,MainWindow::paint() is a function that puts the decoded image on qlabel.

The complete code of Ffplay thread:

class Ffplay : public QThread
{
   Q_OBJECT
public:
    Ffplay();
    signals:
      void send(QImage* image);
    protected:
      void run() override;
public:
    AVFormatContext* format;
    AVCodecContext* codec;
    const AVCodec* c;
    AVPacket* packet;
    AVFrame* frame;
    SwsContext* s;
};
Ffplay::Ffplay() {}

void Ffplay::run(){
    format=avformat_alloc_context();
    avformat_open_input(&format,"c:/Qt/project/player/movie.mp4",NULL,NULL);
    avformat_find_stream_info(format,NULL);
    int index=-1;
    for(unsigned int i=0;i<format->nb_streams;i++){
        if(format->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_VIDEO){
            index=i;
            break;
        }
    }
    c=avcodec_find_decoder(format->streams[index]->codecpar->codec_id);
    codec=avcodec_alloc_context3(c);
    avcodec_parameters_to_context(codec,format->streams[index]->codecpar);
    avcodec_open2(codec,c,NULL);
    packet=av_packet_alloc();
    frame=av_frame_alloc();
    s=sws_getContext(codec->width,codec->height,codec->pix_fmt,655,378,AV_PIX_FMT_RGB32,SWS_FAST_BILINEAR,NULL,NULL,NULL);
    QImage* image=new QImage(655,378,QImage::Format_RGB32);
    uint8_t* dst[]={image->bits()};
    int dstStride[4];
    av_image_fill_linesizes(dstStride,AV_PIX_FMT_RGB32,655);
    while(av_read_frame(format,packet)==0){
        if(packet->stream_index==0){
            avcodec_send_packet(codec,packet);
            while(avcodec_receive_frame(codec,frame)>=0){
                sws_scale(s,frame->data,frame->linesize,0,frame->height,dst,dstStride);
                emit send(image);
            }
        }
    }
}

The complete code of MainWindow class:

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private:
    Ui::MainWindow *ui;
public slots:
    void paint(QImage* image);

};
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

}

void MainWindow::paint(QImage* image){
    QPixmap m=QPixmap::fromImage(*image);
    ui->label->setPixmap(m);
    ui->label->setScaledContents(true);
}

MainWindow::~MainWindow()
{
    delete ui;
}

Theoretically, this shouldn't happen, how can I fix this?

Upvotes: 0

Views: 36

Answers (0)

Related Questions