FFmpeg API 사용 ~ 빌드 환경 구축

소개



FFmpeg를 사용하여 멀티미디어 프로그래밍을 수행하는 방법을 설명합니다.
OS는 Windows를 사용합니다.

FFmpeg란?



from Wikipedia

FFmpeg is a free software project that produces libraries and programs for handling multimedia data.

from Official site

A complete, cross-platform solution to record, convert and stream audio and video.

상기로부터 특징은 이하인 것을 알 수 있습니다.

  • multimedia를 다룬다. audio/video record, convert, streaming
  • free software
  • cross-platform

  • FFmpeg는 다음 라이브러리를 포함합니다.

    libavcodec(decode/encode)
    libavformat(demux/mux)
    libswresample(audio format change)

    동작 소프트 버전


  • FFmpeg
  • Zeranoe's FFmpeg Builds Home Page: <http://ffmpeg.zeranoe.com/builds/>
    FFmpeg version: 20160812-e8b355a base on FFmpeg3.0.1
    
  • Visual Studio/Visual C++
  • Microsoft Visual Studio Community 2015
    Version 14.0.25425.01 Update 3
    Microsoft .NET Framework
    Version 4.6.01038
    
    Visual C++ 2015   00322-20000-00000-AA216
    Microsoft Visual C++ 2015
    

    설정



    Visual Studio


  • Microsoft Visual Studio Community 2015를 설치합니다.
  • Visual C++를 설치합니다.
  • Visual Studio 2015 では、既定で Visual C++ がインストールされません。 インストール時に、
    [カスタム] インストールを選択してから、必要な C++ コンポーネントを選択します。 または、
    Visual Studio が既にインストールされている状態で、[ファイル |新規作成 |プロジェクト 
    |C++] を選択すると、必要なコンポーネントをインストールするように求められます。
    

    Windows 용 FFmpeg



    htp : / / fm㎺g. 제발. 코 m/부이 lds/ 로 이동합니다.
    dev/share를 모두 다운로드합니다.
  • Visual C++ Win32 콘솔 응용 프로그램을 만듭니다.

  • ffmpeg_sample이라는 솔루션을 만듭니다.
    프로젝트 폴더 내에 ffmpeg 폴더를 만듭니다. 다음과 같은 폴더 구성이 됩니다.



    작성한 ffmpeg 이하에 ffmpeg/include, ffmpeg/lib의 2 폴더를 작성합니다.
    각 폴더에 다음과 같이 다운로드한 FFmpeg의 내용을 복사합니다.

    ffmpeg/include <- copy <- FFmpeg/win64-dev/include
    ffmpeg/lib <- copy <- FFmpeg/win64-dev/lib and FFmpeg/win64-shared/bin

    다음과 같은 폴더 구성이 됩니다.

  • include/lib 경로 설정

  • 솔루션 탐색기에서 ffmpeg 프로젝트를 선택하고 마우스 오른쪽 버튼을 클릭합니다.
    속성을 선택합니다.


    플랫폼을 "모든 플랫폼"으로 만듭니다.
    구성 속성 > C/C++ > 일반을 선택합니다.


    추가 포함 디렉토리에 다음을 입력합니다.
    $(SolutionDir)\ffmpeg\include;%(AdditionalIncludeDirectories)
    

    추가 #using 디렉토리에 다음을 입력합니다.
    $(SolutionDir)\ffmpeg\lib
    

    구성 속성 > 링커 > 일반을 선택합니다.
    추가 라이브러리 디렉토리에 다음을 입력합니다.
    $(SolutionDir)\ffmpeg\lib;%(AdditionalLibraryDirectories)
    

    구성 속성 > 디버깅을 선택합니다.
    명령에 다음을 입력합니다.
    $(TargetPath)
    

    구성 속성 > 링커 > 입력을 선택합니다.
    추가 종속 파일에 다음을 입력합니다.
    avcodec.lib
    avdevice.lib
    avfilter.lib
    avformat.lib
    avutil.lib
    postproc.lib
    swresample.lib
    swscale.lib
    

    구성 속성 > 빌드 이벤트 > 이전 링크 이벤트를 선택합니다.
    명령줄에 다음을 입력합니다.
    copy "$(SolutionDir)ffmpeg\lib\avcodec-57.dll" "$(TargetDir)"
    copy "$(SolutionDir)ffmpeg\lib\avdevice-57.dll" "$(TargetDir)"
    copy "$(SolutionDir)ffmpeg\lib\avfilter-6.dll" "$(TargetDir)"
    copy "$(SolutionDir)ffmpeg\lib\avformat-57.dll" "$(TargetDir)"
    copy "$(SolutionDir)ffmpeg\lib\avutil-55.dll" "$(TargetDir)"
    copy "$(SolutionDir)ffmpeg\lib\postproc-54.dll" "$(TargetDir)"
    copy "$(SolutionDir)ffmpeg\lib\swresample-2.dll" "$(TargetDir)"
    copy "$(SolutionDir)ffmpeg\lib\swscale-4.dll" "$(TargetDir)"
    

    컨테이너에서 Video ES를 제거하고 디코딩합니다.



    환경 설정이 성공했는지 확인합니다.
  • test.mpg라는 파일 이름을 가진 TS 파일을 ffmpeg_sample/ffmpeg_sample 이하에 작성하십시오.


  • 다음을 ffmpeg_sample.cpp에 입력합니다.
  • 플랫폼을 x64로 설정합니다.


  • 컴파일하고 실행할 수 있으면 빌드 환경 구축에 성공하고 있습니다.
  • #include "stdafx.h"
    extern "C" {
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    }
    
    int main()
    {
        av_register_all();
    
        const char *filename = "test.mpg";
        AVFormatContext *format_context = NULL;
        int ret = -1;
        ret = avformat_open_input(&format_context, filename, NULL, NULL);
        if (ret < 0) {
            printf("cannot open file. filename=%s, ret=%08x\n", filename, AVERROR(ret));
            return -1;
        }
    
        ret = avformat_find_stream_info(format_context, NULL);
        if (ret < 0) {
            printf("avformat_find_stream_info error. ret=%08x\n", AVERROR(ret));
            return -1;
        }
    
        AVStream *video_stream = NULL;
        for (unsigned int i = 0; i < format_context->nb_streams; i++) {
            if (format_context->streams[i]->codecpar->codec_type == AVMediaType::AVMEDIA_TYPE_VIDEO) {
                // found Video stream
                video_stream = format_context->streams[i];
                break;
            }
        }
        if (video_stream == NULL) {
            printf("video_stream not found\n");
            return -1;
        }
    
        AVCodec *video_codec = avcodec_find_decoder(video_stream->codecpar->codec_id);
        if (video_codec == NULL) {
            printf("avcodec_find_decoder codec not found. codec_id=%d\n", video_stream->codecpar->codec_id);
            return -1;
        }
    
        AVCodecContext *video_codec_context = avcodec_alloc_context3(video_codec);
        if (video_codec_context == NULL) {
            printf("avcodec_alloc_context3 error.\n");
            return -1;
        }
    
        ret = avcodec_open2(video_codec_context, video_codec, NULL);
        if (ret < 0) {
            printf("avcodec_open2 error. ret=%08x\n", AVERROR(ret));
            return -1;
        }
    
        AVFrame *frame = av_frame_alloc();
        AVPacket packet;
        int frame_number = 0;
        while (1) {
            // read ES
            if ((ret = av_read_frame(format_context, &packet)) < 0) {
                printf("av_read_frame eof or error. ret=%08x\n", AVERROR(ret));
                break; // eof or error
            }
            if (packet.stream_index == video_stream->index) {
                // decode Video ES
                if ((ret = avcodec_send_packet(video_codec_context, &packet)) < 0) {
                    printf("avcodec_send_packet error. ret=%08x\n", AVERROR(ret));
                }
                if ((ret = avcodec_receive_frame(video_codec_context, frame)) < 0) {
                    if (ret != AVERROR(EAGAIN)) {
                        printf("avcodec_receive_frame error. ret=%08x\n", AVERROR(ret));
                        break;
                    }
                }
                else {
                    printf("decode finished. frame_number=%d\n", ++frame_number);
                }
            }
            else {
                // does not Video ES.
            }
            av_packet_unref(&packet);
        }
    
        getchar(); // wait user input
    
        return 0;
    }
    

    좋은 웹페이지 즐겨찾기