Wo finde ich moderne Tutorials für libav, ffmpeg usw.? [closed]

Lesezeit: 5 Minuten

Benutzer-Avatar
Martin

Ich möchte ein schnelles Programm in C erstellen, das ein Video öffnet, jedes Bild als ppm speichert und Bewegungsvektoren ausgibt. Alle Tutorials, die ich finden kann, stammen von vor fast zehn Jahren und rufen veraltete oder nicht vorhandene Funktionen auf.

Gibt es gute Online-Ressourcen, Websites, Videos oder Lehrbücher, die einen modernen Ansatz für diese Art von Dingen behandeln?

Benutzer-Avatar
Randall Koch

Ich arbeite seit mehreren Jahren mit ffmpeg und libav und habe auch keine anständigen aktuellen Tutorials auf API-Ebene gefunden. Manchmal muss ich einfach in die Quelle eintauchen, um herauszufinden, was los ist und wie man sie benutzt. Auch das Lesen des Quellcodes für die CLI-Programme (die die zugrunde liegenden Bibliotheken verwenden) kann aufschlussreich sein.

In der Tat, ffmpeg empfiehlt, dass Sie nur den Quellcode lesen, entweder für echte OSS-Projekte oder deren Beispiele. Libav bietet Doxygen-Dokumentation, aber keine Schritt-für-Schritt-Tutorials. Meiner Meinung nach ist dies typisch für Open-Source-Projekte: Die Quelle mag gut sein, aber die Dokumentation fehlt oft.

Einen Schritt zurückzutreten, könntest du in Betracht ziehen OpenCV, das gut dokumentiert ist (Bücher existieren!) und eine einfachere API hat. Schließlich ist ppm ein so einfaches Format, dass Sie wahrscheinlich eine 50-Zeilen-Funktion schreiben könnten, um die Pixel selbst zu speichern, und ich habe ein Bewegungsextraktionsprogramm gefunden hier.

        #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <fstream>
    #include <math.h>

    #define __STDC_CONSTANT_MACROS
    //FFMPEG LIBRARIES
    extern "C"
    {
    #include "libavcodec/avcodec.h"
    #include "libswscale/swscale.h"
    #include "libavutil/opt.h"
    #include "libavutil/common.h"
    #include "libavutil/channel_layout.h"
    #include "libavutil/imgutils.h"
    #include "libavutil/mathematics.h"
    #include "libavutil/samplefmt.h"
    #include "libavutil/time.h"
    #include "libavformat/avformat.h"
    #include "libavformat/avio.h"
    #include "libavfilter/avfilter.h"
    #include "libavdevice/avdevice.h"
    #include "libavfilter/avfiltergraph.h"
    #include "libavfilter/buffersink.h"
    }

    using namespace std;

    void SaveMyFrame(AVFrame *sAVFrame , int swidth, int sheight, int iFrame)
    {
    FILE *pfile;
    char szFilename[32];
    int y;

    sprintf(szFilename , "frame%d.ppm" , iFrame);
    pfile = fopen(szFilename , "wb");
    if(pfile == NULL)
    {
      cout<<"\n\ncould'nt open file";
      return;
    }

    fprintf(pfile , "P6\n%d %d\n255\n" , swidth , sheight );

    for( y=0; y<sheight; y++)
    {
      fwrite(sAVFrame->data[0]+y*sAVFrame->linesize[0] , 1 , swidth*3 , pfile );
    }

    fclose(pfile);
    }

    int CaptureScene(int VideoStreamIndx ,
                       AVFormatContext *bAVFormatContext ,
                       AVCodecContext *bAVCodecContext,
                       AVCodec *bAVCodec )
    {
      AVPacket bAVPacket;
      AVFrame *bAVFrame = NULL;
      bAVFrame = av_frame_alloc();
      AVFrame *bAVFrameRGB = NULL;
      bAVFrameRGB = av_frame_alloc();

    if(bAVFrame == NULL)
    {
      cout<<"\n\nframe alloc failed";
    }

    if(bAVFrameRGB == NULL)
    {
      cout<<"\n\nframe alloc RGB failed";
    }

      int numBytes;
      uint8_t *buffer = NULL;

    numBytes =  av_image_get_buffer_size(AV_PIX_FMT_RGB24 , bAVCodecContext->width,bAVCodecContext->height, 32);  // avpicture_get_size  deprecated

    buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));

    avpicture_fill((AVPicture *)bAVFrameRGB , buffer , AV_PIX_FMT_RGB24 , bAVCodecContext->width , bAVCodecContext->height);

    int framefinish;
    struct SwsContext *sws_ctx = NULL;
    sws_ctx = sws_getContext( bAVCodecContext->width,
                              bAVCodecContext->height,
                              bAVCodecContext->pix_fmt,
                              bAVCodecContext->width,
                              bAVCodecContext->height,
                              AV_PIX_FMT_RGB24,
                              SWS_BILINEAR,
                              NULL,NULL,NULL);
    int i =0;

    while(av_read_frame(bAVFormatContext,&bAVPacket) >=0)
    {
          if(bAVPacket.stream_index == VideoStreamIndx)
      {
          avcodec_decode_video2(bAVCodecContext , bAVFrame , &framefinish , &bAVPacket);
          if(framefinish)
        {
          // convert image from native format to RGB
          sws_scale(sws_ctx , (uint8_t const* const *)bAVFrame->data ,
          bAVFrame->linesize , 0, bAVCodecContext->height,
          bAVFrameRGB->data , bAVFrameRGB->linesize);
          // save frame to disk
          if(++i <= 100)SaveMyFrame(bAVFrameRGB , bAVCodecContext->width , bAVCodecContext->height , i );

        }

      }

    }

    av_free(bAVFrame);
    av_free(bAVFrameRGB);
    }

    int main()
    {

      avdevice_register_all();
      avcodec_register_all();
      av_register_all();

      char *dev_name = "/dev/video0";

     int VideoStreamIndx = -1;
     AVCodecContext *pAVCodecContext = NULL;
     AVCodec *pAVCodec = NULL;
     AVInputFormat *inputFormat =av_find_input_format("v4l2");
     AVDictionary *options = NULL;
     av_dict_set(&options, "framerate", "20", 0);

     AVFormatContext *pAVFormatContext = NULL;

     if(avformat_open_input(&pAVFormatContext, dev_name, inputFormat, NULL) != 0)
     {
       cout<<"\nError : could'nt open video source\n\n";
       return -1;
     }

     if( avformat_find_stream_info( pAVFormatContext , NULL) < 0)
     {
     cout<<"Error : streams not found";
      return -1;
     }

      av_dump_format(pAVFormatContext , 0 , "/dev/video1" , 0 );

     for(int i=0; i<pAVFormatContext->nb_streams ;i++ )
     {
      if( pAVFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO ) // if video stream found then get the index.
      {
        VideoStreamIndx = i;
        break;
      }
     }

    if((VideoStreamIndx) == -1)
    {
      cout<<"Error : video streams not found";
      return -1;
    }

    pAVCodecContext = pAVFormatContext->streams[VideoStreamIndx]->codec;

    pAVCodec = avcodec_find_decoder( pAVCodecContext->codec_id );

    if(pAVCodec == NULL)
    {
     fprintf(stderr,"Unsupported codec !");
     return -1;
    }

    int value = avcodec_open2(pAVCodecContext , pAVCodec , NULL);
    if( value < 0)
    {
      cout<<"Error : Could not open codec";
      return -1;
    }

    int Vwidth , Vheight , videoFPS , videoBaseTime , duration_2 ;
    int sframe , length , Fheight;

    /*
    To fetch/display some media information programatically
    */

    //int64_t duration_1 = pAVFormatContext->duration;
    videoFPS = av_q2d(pAVFormatContext->streams[VideoStreamIndx]->r_frame_rate);
    videoBaseTime = av_q2d(pAVFormatContext->streams[VideoStreamIndx]->time_base);
    Vwidth = pAVFormatContext->streams[VideoStreamIndx]->codec->width;
    Vheight = pAVFormatContext->streams[VideoStreamIndx]->codec->height;
    //duration_2 = (unsigned long)pAVFormatContext->streams[VideoStreamIndx]->duration*(videoFPS*videoBaseTime);

    cout<<"Video FPS :"<<videoFPS;
    cout<<"\n\n width : "<<Vwidth;
    cout<<"\n\n height : "<<Vheight;
    cout<<"\n\n time base"<<videoBaseTime;
    //cout<<"\n\nduration (1): "<<duration_1;
    //cout<<"\n\nduration (2): "<<duration_2;

    CaptureScene( VideoStreamIndx , pAVFormatContext , pAVCodecContext , pAVCodec );

    avcodec_close(pAVCodecContext);
    avformat_close_input(&pAVFormatContext);

    return 0;
    }

Dieser C++-Code hilft Ihnen, ein .ppm-Bild von einer USB (UVC)-basierten Kamera zu erhalten. es speichert im .ppm-Format. Verwenden Sie v4l2 für Linux und dshow für Windows. Anstelle des Kamera-Frame-Feeds kann auch ein Video als Eingabe bereitgestellt werden. Dieser Code wurde mit den neuesten ffmpeg-Bibliotheken erstellt.

libavutil 55.24.100 / 55.24.100

libavcodec 57.43.100 / 57.43.100

libavformat 57.37.100 / 57.37.100

libavdevice 57. 0.101 / 57. 0.101

libavfilter 6.46.100 / 6.46.100

libswscale 4.1.100 / 4.1.100

libswresample 2. 0.101 / 2. 0.101

libpostproc 54. 0.100 / 54. 0.100

1150470cookie-checkWo finde ich moderne Tutorials für libav, ffmpeg usw.? [closed]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy