ffmpeg/libavcodec memory management
Es-die libavcodec-Dokumentation ist nicht sehr spezifisch über, wenn zu kostenlos zugeteilten Daten und wie Sie zu befreien. Nach dem Lesen durch die Dokumentation und die Beispiele, die ich zusammengestellt habe das Beispielprogramm unten. Es gibt einige spezifische Fragen, die inline in der Quelle, aber meine Allgemeine Frage ist, bin ich befreit alle Speicher richtig im code unten? Ich weiß, das Programm unter nicht-Bereinigung nach der Fehler-der Fokus liegt auf der definitiven Bereinigung.
Dem testfile () - Funktion ist, die man in Frage stellen.
extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
}
#include <cstdio>
using namespace std;
void AVFAIL (int code, const char *what) {
char msg[500];
av_strerror(code, msg, sizeof(msg));
fprintf(stderr, "failed: %s\nerror: %s\n", what, msg);
exit(2);
}
#define AVCHECK(f) do { int e = (f); if (e < 0) AVFAIL(e, #f); } while (0)
#define AVCHECKPTR(p,f) do { p = (f); if (!p) AVFAIL(AVERROR_UNKNOWN, #f); } while (0)
void testfile (const char *filename) {
AVFormatContext *format;
unsigned streamIndex;
AVStream *stream = NULL;
AVCodec *codec;
SwsContext *sws;
AVPacket packet;
AVFrame *rawframe;
AVFrame *rgbframe;
unsigned char *rgbdata;
av_register_all();
//load file header
AVCHECK(av_open_input_file(&format, filename, NULL, 0, NULL));
AVCHECK(av_find_stream_info(format));
//find video stream
for (streamIndex = 0; streamIndex < format->nb_streams && !stream; ++ streamIndex)
if (format->streams[streamIndex]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
stream = format->streams[streamIndex];
if (!stream) {
fprintf(stderr, "no video stream\n");
exit(2);
}
//initialize codec
AVCHECKPTR(codec, avcodec_find_decoder(stream->codec->codec_id));
AVCHECK(avcodec_open(stream->codec, codec));
int width = stream->codec->width;
int height = stream->codec->height;
//initialize frame buffers
int rgbbytes = avpicture_get_size(PIX_FMT_RGB24, width, height);
AVCHECKPTR(rawframe, avcodec_alloc_frame());
AVCHECKPTR(rgbframe, avcodec_alloc_frame());
AVCHECKPTR(rgbdata, (unsigned char *)av_mallocz(rgbbytes));
AVCHECK(avpicture_fill((AVPicture *)rgbframe, rgbdata, PIX_FMT_RGB24, width, height));
//initialize sws (for conversion to rgb24)
AVCHECKPTR(sws, sws_getContext(width, height, stream->codec->pix_fmt, width, height, PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL));
//read all frames fromfile
while (av_read_frame(format, &packet) >= 0) {
int frameok = 0;
if (packet.stream_index == (int)streamIndex)
AVCHECK(avcodec_decode_video2(stream->codec, rawframe, &frameok, &packet));
av_free_packet(&packet); //Q: is this necessary or will next av_read_frame take care of it?
if (frameok) {
sws_scale(sws, rawframe->data, rawframe->linesize, 0, height, rgbframe->data, rgbframe->linesize);
//would process rgbframe here
}
//Q: is there anything i need to free here?
}
//CLEANUP: Q: am i missing anything /doing anything unnecessary?
av_free(sws); //Q: is av_free all i need here?
av_free_packet(&packet); //Q: is this necessary (av_read_frame has returned < 0)?
av_free(rgbframe);
av_free(rgbdata);
av_free(rawframe); //Q: i can just do this once at end, instead of in loop above, right?
avcodec_close(stream->codec); //Q: do i need av_free(codec)?
av_close_input_file(format); //Q: do i need av_free(format)?
}
int main (int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "usage: %s filename\n", argv[0]);
return 1;
}
testfile(argv[1]);
}
Spezifische Fragen:
- Gibt es alles, was ich brauche, um frei in die frame-Verarbeitung-Schleife, oder wird libav kümmern memory management gibt es für mich?
- Ist
av_free
den richtigen Weg, um freiSwsContext
? - Der frame-Schleife wird beendet, wenn
av_read_frame
zurück < 0. In diesem Fall muss ich immer nochav_free_packet
wenn es fertig ist? - Muss ich anrufen
av_free_packet
jedes mal durch die Schleife, oder wirdav_read_frame
frei/Wiederverwendung der altenAVPacket
automatisch? - Ich kann nur
av_free
dieAVFrame
s am Ende der Schleife statt der Umverteilung Sie jedes mal durch, richtig? Es scheint zu funktionieren gut, aber ich möchte, um zu bestätigen, dass es funktioniert, weil es eigentlich eher als Glück. - Muss ich
av_free(codec)
dieAVCodec
oder irgendetwas anderes tun, die nachavcodec_close
auf dieAVCodecContext
? - Muss ich
av_free(format)
dieAVFormatContext
oder irgendetwas anderes tun, die nachav_close_input_file
?
Ich auch erkennen, dass einige dieser Funktionen sind deprecated in aktuellen Versionen von libav. Aus Gründen, die hier nicht relevant, ich habe Sie zu benutzen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Diese Funktionen sind nicht nur veraltet, Sie wurden entfernt, vor einiger Zeit. So sollten Sie wirklich erwägen.
Sowieso, als für Ihre Fragen:
1) Nein, nichts mehr frei
2) Nein, Verwendung
sws_freeContext()
3) Nein, wenn
av_read_frame()
gibt einen Fehler zurück, dann wird das Paket enthält keine gültigen Daten4) ja, Sie haben, um das gratis-Paket, nachdem Sie fertig sind mit es und vor nächsten
av_read_frame()
nennen5) ja, es ist vollkommen gültig
6) Nein, der codec Kontext selbst zugewiesen ist, durch libavformat so
av_close_input_file()
istverantwortlich für die Freigabe. Also nichts mehr für Sie zu tun.
7) Nein,
av_close_input_file()
befreit die format-Kontext, so sollte es nichts mehr für Sie zu tun.