Probleme mit ffmpeg



  • Hallo
    Ich schreibe gerade ein Programm das bei einem Video jedes Frame analysieren soll.
    Dazu benutze ich denn ffmpeg decoder um aus dem Video (mpeg) mir jedes Frame raus zu holen.
    Das klappt bis jetzt auch ganz gut.
    Anbei meine videostream Klasse.
    Problem folgt weiter unten.
    (Sorry wenn zu lang)

    #include "videostream.h"
    
    VideoStream::VideoStream(){}
    
    VideoStream::~VideoStream()
    {
        // Free the RGB image
        delete [] buffer;
        av_free(pFrameGRAY);
    
        // Free the YUV frame
        av_free(pFrame);
    
        // Close the codec
        avcodec_close(pCodecCtx);
    
        // Close the video file
        av_close_input_file(pFormatCtx);
    }
    
    int VideoStream::init(char* filename)
    {
        // Register all formats and codecs
        av_register_all();
    
        // Open video file
        if(av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL)!=0)
        {
            log->logerror("Error while opening the file %s",filename);        
            return -1;
        }
    
        // Retrieve stream information
        if(av_find_stream_info(pFormatCtx)<0)
        {
            log->logerror("Error. Can't find stream infos...");
            return -1;
        }
    
        // Find the first video stream
        videoStream=-1;
        for(i=0; i<pFormatCtx->nb_streams; i++)
            if(pFormatCtx->streams[i]->codec.codec_type==CODEC_TYPE_VIDEO)
            {
                videoStream=i;
                break;
            }
        if(videoStream==-1)
        {
            log->logerror("Error. Can't find a Video Stream");
            return -1;
        }
    
        //CurrentFrameNumber
        currentFrameNumber = 0;
        // Get a pointer to the codec context for the video stream
        pCodecCtx=&pFormatCtx->streams[videoStream]->codec;
    
        // Find the decoder for the video stream
        pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
        if(pCodec==NULL)
        {
            log->logerror("Error. Can't find the Video Codec ");
            return -1;
        }
    
        // Open codec
        if(avcodec_open(pCodecCtx, pCodec)<0)
        {
            log->logerror("Error. Can't open the Video Codec ");
            return -1;
        }
    
        // Hack to correct wrong frame rates that seem to be generated by some
        // codecs
        if(pCodecCtx->frame_rate>1000 && pCodecCtx->frame_rate_base==1)
            pCodecCtx->frame_rate_base=1000;
    
        // Allocate video frame
        pFrame=avcodec_alloc_frame();
    
        // Allocate an AVFrame structure
        pFrameGRAY=avcodec_alloc_frame();
        if(pFrameGRAY==NULL)
        {
            log->logerror("Error. Can't allocad memory ");
            return -1;        
        }
        // Determine required buffer size and allocate buffer
        numBytes=avpicture_get_size(PIX_FMT_GRAY8, pCodecCtx->width,
                                    pCodecCtx->height);
        buffer=new uint8_t[numBytes];
    
        // Assign appropriate parts of buffer to image planes in pFrameRGB
        avpicture_fill((AVPicture *)pFrameGRAY, buffer, PIX_FMT_GRAY8,
                       pCodecCtx->width, pCodecCtx->height);
    
        //save pointer to the first Frame
        //firstpFormatCtx->packet_buffer->next = NULL;//pFormatCtx->packet_buffer->next;
        //firstpFormatCtx->packet_buffer->next = firstpFormatCtx->packet_buffer;
        //test->packet_buffer = NULL;
        resetStream();
        return 0;
    }
    
    void VideoStream::resetStream()
    {
        //Set the pointer to the first Frame
        log->logdevelop("Reset the stream");
        av_seek_frame(pFormatCtx,videoStream,0,0);
    
        //CurrentFrameNumber
        currentFrameNumber = 0;
    }
    
    sFrame VideoStream::getNextFrame()
    {
        int found = 0 ;
        while(av_read_frame(pFormatCtx, &packet)>=0 && !found )
        {
            // Is this a packet from the video stream?
            if(packet.stream_index==videoStream)
            {
                // Decode video frame
                avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,
                                     packet.data, packet.size);
    
                // Did we get a video frame?
                if(frameFinished)
                {
                    currentFrameNumber++;
                    // Convert the image from its native format to Gray
                    img_convert((AVPicture *)pFrameGRAY, PIX_FMT_GRAY8 ,
                                (AVPicture*)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width,
                                pCodecCtx->height);
                    av_free_packet(&packet);
                    found = 1;
                    //break;
                }
            }
    
            // Free the packet that was allocated by av_read_frame
            av_free_packet(&packet);
        }
    
        sFrame frame;
        *frame.data = *pFrameGRAY->data;
        frame.width = pCodecCtx->width;
        frame.height = pCodecCtx->height;
        frame.number = currentFrameNumber;
    
        //DEBUG ON
        if(currentFrameNumber > 200 && currentFrameNumber < 300){
        log->logdevelop("Framenumber beim getFrame ist %d %d %d %d",frame.number,frame.data[0],frame.data[100],frame.data[200]);
    
        FILE *pFile;
        char szFilename[32];
        int  y,x;
    
        sprintf(szFilename, "%i_%i.pgm", currentFrameNumber,c);
    
        // Open file
        pFile=fopen(szFilename, "wb");
    
        // Write header720x576
        //fprintf(pFile, "P5 %d %d 255\n",  avf.width,avf.height);
        fprintf(pFile, "P5 %d %d 255 ",  frame.width, frame.height);
    
        // Write pixel data
        for(y=0; y<frame.height; y++)
            for (x=0;x<frame.width;x++)
                fwrite(frame.data[0]+y*frame.width+x, sizeof(uint8_t), 1, pFile);
    
        // Close file
        fclose(pFile);
        }
        //DEBUG OFF
    
        if (!found )
            *frame.data = NULL;
    
        return frame;
    }
    

    Die Arbeit wird dabei in mehreren Schritten gemacht.
    FirstPass, SecondPass,...
    In dem FirstPass wird einfach getFrame() solange aufgerufen bis das Video zuende ist. SecondPass macht zZ genau das selbe.
    Leider bekomme ich beim FirstPass immer falsche Daten geliefert.
    In der Methode getFrame() speichere ich die Frames zum debuggen auch als image ab.
    Ab einem bestimmten Frame werden aber immer nur die selben Frames zurückgeliefert.
    Wenn ich dann durch bin mit meiner FirstPass, dann bekomme ich beim zweiten mal richtige Images geliefert.
    Das verstehe ich nicht, weil der FirstPass und der SecondPass 100% genau das selbe machen.
    Kennt sich da jemand aus?

    Ich hätte da auch noch ein paar Fragen zum Audio Codec.
    Aber das kommt dann später.



  • Antworte ich mir mal selber.

    Also ich lese nun schon beim init das erste Frame ein und resete den Stream dann wieder. Scheint zu gehen. Warum weiß ich nicht 😞



  • Hallo,

    durch eine Google-Suche bin ich auf diesen Beitrag geladet.

    Ich versuche mich gerade in FFMpeg und FOBS ihn ein zu arbeiten. Es gibt einen schönes Demo für FOBS 'test.cpp', welches ich nicht kompelieren kann:

    lore@tauron:~/workspace/fobs** ll insgesamt 56 -rw-r--r-- 1 lore lore 444 2005-02-01 19:17 buildFobs.sh -rw-r--r-- 1 lore lore 4379 2005-02-02 05:00 ChangeLog -rw-r--r-- 1 lore lore 26442 2005-02-01 19:17 COPYING drwxr-xr-x 2 lore lore 48 2007-12-30 00:14 CVS lrwxrwxrwx 1 lore lore 10 2008-01-03 00:19 ffmpeg -> ../ffmpeg/ drwxr-xr-x 3 lore lore 138 2008-01-02 23:52 lib -rw-r--r-- 1 lore lore 1315 2005-02-01 19:17 README drwxr-xr-x 3 lore lore 51 2007-12-30 01:30 resources -rw-r--r-- 1 lore lore 79 2005-02-01 19:17 SConstruct drwxr-xr-x 4 lore lore 4096 2008-01-06 08:15 scripts -rw-r--r-- 1 lore lore 2015 2005-02-02 05:01 SInit drwxr-xr-x 5 lore lore 59 2007-12-30 00:01 src **lore@tauron:~/workspace/fobs g++ src/cppapi/test.cpp -Iffmpeg -Lffmpeg -o test
    In file included from src/cppapi/Decoder.h:27,
    from src/cppapi/test.cpp:23:
    src/cppapi/common.h:42:7: warning: no newline at end of file
    In file included from src/cppapi/PacketBuffer.h:24,
    from src/cppapi/Decoder.h:29,
    from src/cppapi/test.cpp:23:
    ffmpeg/libavformat/avformat.h:32:21: error: avcodec.h: No such file or directory
    In file included from src/cppapi/PacketBuffer.h:25,
    from src/cppapi/Decoder.h:29,
    from src/cppapi/test.cpp:23:
    ffmpeg/libavcodec/avcodec.h:30:20: error: avutil.h: No such file or directory
    In file included from src/cppapi/Decoder.h:29,
    from src/cppapi/test.cpp:23:
    src/cppapi/PacketBuffer.h:26:23: error: framehook.h: No such file or directory
    src/cppapi/PacketBuffer.h:57:3: warning: no newline at end of file
    src/cppapi/test.cpp:56:2: warning: no newline at end of file
    ffmpeg/libavformat/avformat.h:112: Fehler: expected initializer before »attribute_deprecated«
    ffmpeg/libavformat/avformat.h:132: Fehler: »AVRational« bezeichnet keinen Typ
    ffmpeg/libavformat/avformat.h:137: Fehler: Verwendung des enum »PixelFormat« ohne vorherige Deklaration
    ffmpeg/libavformat/avformat.h:148: Fehler: Verwendung des enum »CodecID« ohne vorherige Deklaration
    ffmpeg/libavformat/avformat.h:149: Fehler: Verwendung des enum »CodecID« ohne vorherige Deklaration
    ffmpeg/libavformat/avformat.h:171: Fehler: Verwendung des enum »CodecID« ohne vorherige Deklaration
    ffmpeg/libavformat/avformat.h:172: Fehler: Verwendung des enum »CodecID« ohne vorherige Deklaration
    (..)
    ffmpeg/libavcodec/avcodec.h:2963: Fehler: expected primary-expression before »const«
    ffmpeg/libavcodec/avcodec.h:2963: Fehler: initializer Ausdrucksliste als zusammengesetzten Ausdruck behandelt
    src/cppapi/Decoder.h:192: Fehler: Verwendung des enum »PixelFormat« ohne vorherige Deklaration
    lore@tauron:~/workspace/fobs$

    Was habe ich getan? Nach dem Download habe ich das FOBS-Build-Skript ausgeführt. Probleme gab es nicht. Eigentlich bringt ja FOBS seine FFMpeg-Version selbst mit, deshalb denke ich mal das es keine Probleme geben sollte.

    Ich kenne die Grundlagen der C++-Programmierung und habe Beispiele für QT-Anwendungen mit KDevelop erfolgreich durchgeführt. Mit dem ersten eigenen Projekt komme ich einfach nicht weiter.

    Ich binde die FFMpeg-Lib mit dem Include-Parameter (-I) ein. Das Link-Verzeichnis (-L) ist auch das gleiche. Was fehlt? 😕 Gibt es eine Anleitung, die man wirklich empfehlen kann?



  • Dir scheinen noch ein paar Header-Dateien zu fehlen (bzw. der Pfad ist falsch):
    - avcodec.h
    - avutil.h
    - framehook.h

    Schau mal, ob die in den Lib-Installationsverzeichnissen dabei sind...


Anmelden zum Antworten