Anzeige:
Ergebnis 1 bis 4 von 4

Thema: Videowiedergabe unter Qt4

  1. #1
    Registrierter Benutzer
    Registriert seit
    22.03.2005
    Beiträge
    16

    Videowiedergabe unter Qt4

    Hallo,

    ich dekodiere ein Video unter Windows mittels ffmpeg und versuche die einzelnen Frames mittels QPainter auszugeben, jedoch zeigt er mir immer nur den letzten Frame des Videos an. Wo liegt hier mein Fehler

    Code:
    #ifndef WINDOW_H_
    #define WINDOW_H_
    
    #include "avformat.h"
    #include <QWidget>
    #include <QPainter>
    
    class Window : public QWidget
    {
        Q_OBJECT
    
        public:
            Window();
            
        protected:
        	virtual void paintEvent(QPaintEvent*);
        	virtual void keyPressEvent(QKeyEvent*);
    
        private slots:
        	void play();
            
    	private:    	
        	void decode(char*);
        	QPixmap *fPixmap;
        	QPixmap *constructPixmap(AVFrame*, int, int);
    };
    
    #endif /*WINDOW_H_*/
    Code:
    #include "window.h"
    #include <QBuffer>
    #include <iostream>
    
    using namespace std;
    
    Window::Window()
    {	
    	// Register all available codecs
    	av_register_all();
    	
    	fPixmap = NULL;
    }
    
    void Window::play()
    {
    	char *avfile = "test.mpg";
    	decode(avfile);
    }
    
    void Window::keyPressEvent(QKeyEvent*)
    {
    	play();
    }
    
    void Window::paintEvent(QPaintEvent*)
    {
    	QPainter p(this);
    	if(fPixmap != NULL)
    		p.drawPixmap(10, 10, *fPixmap);
    }
    
    
    void Window::decode(char *input_filename)
    {
    	int err = 0, i = 0, len1 = 0, got_picture, video_index = -1;
    
        AVFormatContext *fcx = NULL;
        AVCodecContext  *ccx = NULL;
        AVCodec *codec = NULL;
    
        AVFormatParameters params;
        AVPacket pkt;
        AVFrame *frame = avcodec_alloc_frame();
        AVFrame *frameRGB = avcodec_alloc_frame();
        
        int             numBytes;
        uint8_t         *buffer;  
        
        // Open the input file.
        err = av_open_input_file(&fcx, input_filename, NULL, 0, &params);
        if(err < 0)
    		cout << "Can't open file: " << input_filename << endl;
    	else
    	{
    		// Find the stream info.
    	    err = av_find_stream_info(fcx);
    	    
    	    // Find the first video stream.
    	    for(i = 0; i <fcx->nb_streams; i++)
    	    {
    			ccx = fcx->streams[i]->codec;
    			if(ccx->codec_type == CODEC_TYPE_VIDEO) 
    				break;
    	    }
    	    
    	    video_index = i;
    	    
    	    // Open stream.
    	    if(video_index >= 0)
    	    {
    			codec = avcodec_find_decoder(ccx->codec_id);
    			if(codec)
    			    err = avcodec_open(ccx, codec);
    			if(err < 0)
    			    cout << "Can't open codec." << endl;
    	    }
    	    else
    			cout << "Video stream not found." << endl;
    	    
    	    // Determine required buffer size and allocate buffer
    	    numBytes=avpicture_get_size(PIX_FMT_RGB24, ccx->width, ccx->height);
    	    buffer=new uint8_t[numBytes];
    	
    	    // Assign appropriate parts of buffer to image planes in pFrameRGB
    	    avpicture_fill((AVPicture *)frameRGB, buffer, PIX_FMT_RGB24,
    	        ccx->width, ccx->height);
    	    
    	    // Decode
    	    while(true)
    	    {
    			// Read a frame/packet.
    			if(av_read_frame(fcx, &pkt) < 0 ) 
    				break;
    	
    			// If it's a video packet from our video stream... 
    			if(pkt.stream_index == video_index)
    			{
    		    	// Decode the packet
    		    	len1 = avcodec_decode_video(ccx, frame, &got_picture, 
    						pkt.data, pkt.size);
    	
    			    if(got_picture) 
    			    {
    					
    					// Convert image to RGB
    					img_convert((AVPicture*)frameRGB, PIX_FMT_RGB24, (AVPicture*)frame, 
    						ccx->pix_fmt, ccx->width, ccx->height);
    					
    					// Display frames
    					fPixmap = constructPixmap(frameRGB, ccx->width, ccx->height);
    					this->update();	
    			    }
    	
    		    	av_free_packet(&pkt);
    			}
    	    }
    	    
    	    // Clean up
    	    av_free(frameRGB);
    	    av_free(frame);
        	av_close_input_file(fcx);
    	}
    }
    
    QPixmap* Window::constructPixmap(AVFrame *pFrame, int width, int height)
    {
    	char buffer[128];
    	
    	QBuffer *pImageBuffer = new QBuffer();
    	pImageBuffer->open(QIODevice::WriteOnly);
    	QDataStream *pDataStream = new QDataStream(pImageBuffer);
    	
    	// Header for ppm
    	sprintf(buffer,"P6 %d %d 255\n", width, height);
    	pDataStream->writeRawData(buffer, strlen(buffer));
    	
    	// Writing the ppm data
    	for(int y = 0;  y < height; y++)
            pDataStream->writeRawData((char*)pFrame->data[0] + y * pFrame->linesize[0], width * 3);
    	
    	pImageBuffer->close();
    	pImageBuffer->open(QIODevice::ReadOnly);
    	
    	QPixmap *pixmap = new QPixmap();
    	
    	// Convert buffer to pixmap
    	if(pixmap->loadFromData(pImageBuffer->buffer()))
    	{
    		pImageBuffer->close();
    		delete pImageBuffer;
    		delete pDataStream;
    		
    		return pixmap;
    	}
    	
    	cout << "Failed to construct pixmap" << endl;
    	
    	// Free buffer
    	pImageBuffer->close();
    	delete pImageBuffer;
    	delete pDataStream;
    		
    	return NULL;
    }

  2. #2
    Registrierter Benutzer
    Registriert seit
    22.03.2005
    Beiträge
    16
    Problem hat sich erledigt

  3. #3
    Registrierter Benutzer Avatar von panzi
    Registriert seit
    04.05.2001
    Ort
    Kottingbrunn
    Beiträge
    609
    Und wie schnell läuft das mit QPainter als Videoausgabedevice?
    Intel Core 2 Duo CPU 2.66GHz; Nvidia GeForce 8 8800 GTS; 4GB RAM; Fedora 12; KDE-testing

  4. #4
    Registrierter Benutzer
    Registriert seit
    22.03.2005
    Beiträge
    16
    Also es läuft auf jeden Fall flüssig, wenn ich das Bild per timer alle 15 ms aktualisiere. Werds in kürze auch noch mit opengl testen.

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •