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:

  1. 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?
  2. Ist av_free den richtigen Weg, um frei SwsContext?
  3. Der frame-Schleife wird beendet, wenn av_read_frame zurück < 0. In diesem Fall muss ich immer noch av_free_packet wenn es fertig ist?
  4. Muss ich anrufen av_free_packet jedes mal durch die Schleife, oder wird av_read_frame frei/Wiederverwendung der alten AVPacket automatisch?
  5. Ich kann nur av_free die AVFrames 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.
  6. Muss ich av_free(codec) die AVCodec oder irgendetwas anderes tun, die nach avcodec_close auf die AVCodecContext?
  7. Muss ich av_free(format) die AVFormatContext oder irgendetwas anderes tun, die nach av_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.

InformationsquelleAutor Jason C | 2013-08-02
Schreibe einen Kommentar