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.hSchau mal, ob die in den Lib-Installationsverzeichnissen dabei sind...