H.264 in Visual C++ 2008 Programmieren



  • hi,

    wie der Titel schon sagt suche ich geeignete Bibliotheken für c++ mit denen ich den H.264 Codec verwenden kann. Ich möchte ein Programm schreiben mit dem ich eine Videodatei(bzw. Videostream) in h.264 kodieren kann. Ich such KEINE komplexen Projekte, sondern nur etwas, dass ich in c++ mit h.264 kodieren/dekodieren kann.
    Hab schon überall gesucht aber nichts passendes gefunden.

    Ich habe mich auch schon mit OpenCV beschäfftigt; gibts da irgendwelche Implementierungen?

    Alternativ würde auch C# in Frage kommen.

    Kennt ihr da geeignete Bibliotheken, die dokumentiert sind?

    Gruß Profcoder



  • Ich kann da nur die libavcodec empfehlen. :3 Die Dokumentation ist zwar nicht optimal, aber es gibt Beispielcode. ^^



  • hi,

    danke für die antwort. FFmpeg habe ich mir schon angeschaut. Das scheint nicht schlecht zu sein. Leider nicht sonderlich gut dokumentiert und die deutschen Tutorials sind auch schon veraltet...

    Jetzt hab mal ein paar Beispielcodes ausprobiert. Und ich bekomm sie nicht zum laufen. Das fängt schon bei den Header Dateien an (Inttypes.h findet er z.B. nicht). VisualC++ 2008 unterstützt den C99 Standard nicht (der auch nicht sehr beliebt ist, aber warum wird der in FFmpeg verwendet?)

    Ich bekomm kein einziges Programm kompiliert. Muss ich mich mit Unix Versionen von C++ befassen oder gibts da auch eine Version die für das "normale" Windows C++ geeignet ist?

    Edit:

    Die X264 library scheint auch geeignet zu sein, da fehlen aber zu dem C99Standard auch noch die Posix Dateien. Ich werd warscheinlich nicht drumrumkommen mich näher mit Linux/Unix und deren Shells zu beschäfftigen, bzw. mit mingw und co. -.-

    Habt ihr Ideen wie ichs unter Windows zum laufen bekomm?



  • Du hast deine Frage schon selbst beantwortet. ;3 Nimm einen vernünftigen Compiler, wie den MinGW. ^^ Da brauchst du dich auch nicht mit Linux/Unix beschäftigen. :3



  • Ich hab die CodeBlocksversion installiert, die bereits mingw enthält.
    Als Compiler nehm ich den GNU GCC Compiler wie es in vielen Tutorials beschrieben ist
    Dann hab ich ein Beispielprojekt von ffmpeg erstellt, jetzt erkennt er eine UINT64_C Variable nicht die er aber eig wegen C99 Unterstützung erkennen müsste.

    Zudem fehlt bei vielen FFMPEG Versionen die avconfig.h, die habe ich aber ersetzt und den fehlende code eingefügt. Das Problem hab ich gelöst.

    Ich verwende die Version 0.6 von FFMPEG.

    Ich hab dieses Beispielprojekt von deiner Seite genommen, eine Consoleanwendung erstellt und den code hier als Main.cpp verwendet:

    // avcodec_sample.0.5.0.c
    
    // A small sample program that shows how to use libavformat and libavcodec to
    // read video from a file.
    //
    // This version is for the 0.4.9+ release of ffmpeg. This release adds the
    // av_read_frame() API call, which simplifies the reading of video frames
    // considerably.
    //
    // Use
    //
    // gcc -o avcodec_sample.0.5.0 avcodec_sample.0.5.0.c -lavformat -lavcodec -lavutil -lswscale -lz -lbz2
    //
    // to build (assuming libavformat, libavcodec, libavutil, and swscale are correctly installed on
    // your system).
    //
    // Run using
    //
    // avcodec_sample.0.5.0 myvideofile.mpg
    //
    // to write the first five frames from "myvideofile.mpg" to disk in PPM
    // format.
    
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libswscale/swscale.h>
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    
    static void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame);
    
    int main (int argc, const char * argv[])
    {
        AVFormatContext *pFormatCtx;
        int             i, videoStream;
        AVCodecContext  *pCodecCtx;
        AVCodec         *pCodec;
        AVFrame         *pFrame;
        AVFrame         *pFrameRGB;
        AVPacket        packet;
        int             frameFinished;
        int             numBytes;
        uint8_t         *buffer;
    
        // Register all formats and codecs
        av_register_all();
    
        // Open video file
        if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)
            return -1; // Couldn't open file
    
        // Retrieve stream information
        if(av_find_stream_info(pFormatCtx)<0)
            return -1; // Couldn't find stream information
    
        // Dump information about file onto standard error
        dump_format(pFormatCtx, 0, argv[1], false);
    
        // 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)
            return -1; // Didn't find a video stream
    
        // 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)
            return -1; // Codec not found
    
        // Open codec
        if(avcodec_open(pCodecCtx, pCodec)<0)
            return -1; // Could not open codec
    
        // Hack to correct wrong frame rates that seem to be generated by some codecs
        if(pCodecCtx->time_base.num>1000 && pCodecCtx->time_base.den==1)
    		pCodecCtx->time_base.den=1000;
    
        // Allocate video frame
        pFrame=avcodec_alloc_frame();
    
        // Allocate an AVFrame structure
        pFrameRGB=avcodec_alloc_frame();
        if(pFrameRGB==NULL)
            return -1;
    
        // Determine required buffer size and allocate buffer
        numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,
            pCodecCtx->height);
    
        buffer=malloc(numBytes);
    
        // Assign appropriate parts of buffer to image planes in pFrameRGB
        avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
            pCodecCtx->width, pCodecCtx->height);
    
        // Read frames and save first five frames to disk
        i=0;
        while(av_read_frame(pFormatCtx, &packet)>=0)
        {
            // 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)
                {
    				static struct SwsContext *img_convert_ctx;
    
    #if 0
    				// Older removed code
                    // Convert the image from its native format to RGB swscale
                    img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24,
                        (AVPicture*)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width,
                        pCodecCtx->height);
    
    				// function template, for reference
    				int sws_scale(struct SwsContext *context, uint8_t* src[], int srcStride[], int srcSliceY,
    							  int srcSliceH, uint8_t* dst[], int dstStride[]);
    #endif
    				// Convert the image into YUV format that SDL uses
    				if(img_convert_ctx == NULL) {
    					int w = pCodecCtx->width;
    					int h = pCodecCtx->height;
    
    					img_convert_ctx = sws_getContext(w, h,
    									pCodecCtx->pix_fmt,
    									w, h, PIX_FMT_RGB24, SWS_BICUBIC,
    									NULL, NULL, NULL);
    					if(img_convert_ctx == NULL) {
    						fprintf(stderr, "Cannot initialize the conversion context!\n");
    						exit(1);
    					}
    				}
    				int ret = sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0,
    						  pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
    #if 0 // this use to be true, as of 1/2009, but apparently it is no longer true in 3/2009
    				if(ret) {
    					fprintf(stderr, "SWS_Scale failed [%d]!\n", ret);
    					exit(-1);
    				}
    #endif
                    // Save the frame to disk
                    if(i++<=5)
                        SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);
                }
            }
    
            // Free the packet that was allocated by av_read_frame
            av_free_packet(&packet);
        }
    
        // Free the RGB image
        free(buffer);
        av_free(pFrameRGB);
    
        // Free the YUV frame
        av_free(pFrame);
    
        // Close the codec
        avcodec_close(pCodecCtx);
    
        // Close the video file
        av_close_input_file(pFormatCtx);
    
        return 0;
    }
    
    static void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame)
    {
        FILE *pFile;
        char szFilename[32];
        int  y;
    
        // Open file
        sprintf(szFilename, "frame%d.ppm", iFrame);
        pFile=fopen(szFilename, "wb");
        if(pFile==NULL)
            return;
    
        // Write header
        fprintf(pFile, "P6\n%d %d\n255\n", width, height);
    
        // Write pixel data
        for(y=0; y<height; y++)
            fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);
    
        // Close file
        fclose(pFile);
    }
    

    Hier noch der ein codeteil in der common.h und die Fehlermeldungen die ich dazu bekomme:

    static inline av_const int32_t av_clipl_int32(int64_t a)
    {
        if ((a+0x80000000u) & ~UINT64_C(0xFFFFFFFF)) return (a>>63) ^ 0x7FFFFFFF;
        else                                         return a;
    }
    

    D:\dsch\ffmpeg-0.6\libavutil\common.h|154|error: 'UINT64_C' was not declared in this scope|

    UINT64_C sollte er aber eig erkennen, gehört soweit ich weiß zum c99 standard!

    Ich hab schon die Headerdateien durchsucht. UINT64_C ist dort angegeben. Ich hab echt keinen Plan mehr was ich machen soll! Das ist nur noch rumgemache -.-

    Wie hast du FFMPEG zum laufen gebracht? Hast du zufälligerweise einen eigenen Beispielcode dazu? Wäre echt cool.

    Edit: Die Fehlermeldung hab ich behoben indem ich das UINT64_C einfach gelöscht hab.

    static inline av_const int32_t av_clipl_int32(int64_t a)
    {
        if ((a+0x80000000u) & (0xFFFFFFFF)) return (a>>63) ^ 0x7FFFFFFF;
        else                                         return a;
    }
    

    Aber ob das ned irgendwann mal ein Problem gibt. Das Programm läuft trotzdem nicht, weil es jetzt die FFMPEG Funktionen nicht findet.

    Die Header konnte ich einbinden. Aber jetzt findet er die Funktionen nicht.
    Dafür bräuchte ich .DLL und .lib Dateien. Die es leider nicht gibt.
    Wie kann/muss ich die erstellen. Wie geht das unter Mingw?



  • kann man schliessen. habs problem gelöst.

    danke für die zahlreichen antworten...


Anmelden zum Antworten