hedgewars/avwrapper/avwrapper.c
changeset 11298 9fcdf0969d53
parent 11046 47a8c19ecb60
child 11297 bf5cfd830f7d
equal deleted inserted replaced
11286:9bd2acb1b577 11298:9fcdf0969d53
    19 #include <stdlib.h>
    19 #include <stdlib.h>
    20 #include <stdio.h>
    20 #include <stdio.h>
    21 #include <stdint.h>
    21 #include <stdint.h>
    22 #include <string.h>
    22 #include <string.h>
    23 #include <stdarg.h>
    23 #include <stdarg.h>
       
    24 
       
    25 #include "libavcodec/avcodec.h"
    24 #include "libavformat/avformat.h"
    26 #include "libavformat/avformat.h"
       
    27 #include "libavutil/avutil.h"
    25 #include "libavutil/mathematics.h"
    28 #include "libavutil/mathematics.h"
    26 
       
    27 #ifndef AVIO_FLAG_WRITE
       
    28 #define AVIO_FLAG_WRITE AVIO_WRONLY
       
    29 #endif
       
    30 
    29 
    31 #if (defined _MSC_VER)
    30 #if (defined _MSC_VER)
    32 #define AVWRAP_DECL __declspec(dllexport)
    31 #define AVWRAP_DECL __declspec(dllexport)
    33 #elif ((__GNUC__ >= 3) && (!__EMX__) && (!sun))
    32 #elif ((__GNUC__ >= 3) && (!__EMX__) && (!sun))
    34 #define AVWRAP_DECL __attribute__((visibility("default")))
    33 #define AVWRAP_DECL __attribute__((visibility("default")))
    55 static FILE* g_pSoundFile;
    54 static FILE* g_pSoundFile;
    56 static int16_t* g_pSamples;
    55 static int16_t* g_pSamples;
    57 static int g_NumSamples;
    56 static int g_NumSamples;
    58 
    57 
    59 
    58 
       
    59 // compatibility section
    60 #if LIBAVCODEC_VERSION_MAJOR < 54
    60 #if LIBAVCODEC_VERSION_MAJOR < 54
    61 #define OUTBUFFER_SIZE 200000
    61 #define OUTBUFFER_SIZE 200000
    62 static uint8_t g_OutBuffer[OUTBUFFER_SIZE];
    62 static uint8_t g_OutBuffer[OUTBUFFER_SIZE];
    63 #endif
    63 #define avcodec_open2(x, y, z)              avcodec_open(x, y)
       
    64 #endif
       
    65 
       
    66 #if LIBAVCODEC_VERSION_MAJOR < 56
       
    67 #define av_frame_alloc                      avcodec_alloc_frame
       
    68 #define av_frame_free                       av_freep
       
    69 #endif
       
    70 
       
    71 #if LIBAVCODEC_VERSION_MAJOR < 57
       
    72 #define AV_CODEC_CAP_DELAY                  CODEC_CAP_DELAY
       
    73 #define AV_CODEC_CAP_VARIABLE_FRAME_SIZE    CODEC_CAP_VARIABLE_FRAME_SIZE
       
    74 #define AV_CODEC_FLAG_GLOBAL_HEADER         CODEC_FLAG_GLOBAL_HEADER
       
    75 #define AV_CODEC_FLAG_QSCALE                CODEC_FLAG_QSCALE
       
    76 #endif
       
    77 
       
    78 #if LIBAVFORMAT_VERSION_MAJOR < 53
       
    79 #define AVIO_FLAG_WRITE                     AVIO_WRONLY
       
    80 #endif
       
    81 
       
    82 #if LIBAVFORMAT_VERSION_MAJOR < 54
       
    83 #define avformat_new_stream(x, y)           av_new_stream(x, y->type == AVMEDIA_TYPE_AUDIO)
       
    84 #endif
       
    85 
       
    86 #if LIBAVUTIL_VERSION_MAJOR < 54
       
    87 #define AV_PIX_FMT_YUV420P                  PIX_FMT_YUV420P
       
    88 #endif
       
    89 
    64 
    90 
    65 // pointer to function from hwengine (uUtils.pas)
    91 // pointer to function from hwengine (uUtils.pas)
    66 static void (*AddFileLogRaw)(const char* pString);
    92 static void (*AddFileLogRaw)(const char* pString);
    67 
    93 
    68 static int FatalError(const char* pFmt, ...)
    94 static int FatalError(const char* pFmt, ...)
   103     AddFileLogRaw(Buffer);
   129     AddFileLogRaw(Buffer);
   104 }
   130 }
   105 
   131 
   106 static void AddAudioStream()
   132 static void AddAudioStream()
   107 {
   133 {
   108 #if LIBAVFORMAT_VERSION_MAJOR >= 53
       
   109     g_pAStream = avformat_new_stream(g_pContainer, g_pACodec);
   134     g_pAStream = avformat_new_stream(g_pContainer, g_pACodec);
   110 #else
       
   111     g_pAStream = av_new_stream(g_pContainer, 1);
       
   112 #endif
       
   113     if(!g_pAStream)
   135     if(!g_pAStream)
   114     {
   136     {
   115         Log("Could not allocate audio stream\n");
   137         Log("Could not allocate audio stream\n");
   116         return;
   138         return;
   117     }
   139     }
   129 
   151 
   130     // set quality
   152     // set quality
   131     g_pAudio->bit_rate = 160000;
   153     g_pAudio->bit_rate = 160000;
   132 
   154 
   133     // for codecs that support variable bitrate use it, it should be better
   155     // for codecs that support variable bitrate use it, it should be better
   134     g_pAudio->flags |= CODEC_FLAG_QSCALE;
   156     g_pAudio->flags |= AV_CODEC_FLAG_QSCALE;
   135     g_pAudio->global_quality = 1*FF_QP2LAMBDA;
   157     g_pAudio->global_quality = 1*FF_QP2LAMBDA;
   136 
   158 
   137     // some formats want stream headers to be separate
   159     // some formats want stream headers to be separate
   138     if (g_pFormat->flags & AVFMT_GLOBALHEADER)
   160     if (g_pFormat->flags & AVFMT_GLOBALHEADER)
   139         g_pAudio->flags |= CODEC_FLAG_GLOBAL_HEADER;
   161         g_pAudio->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
   140 
   162 
   141     // open it
   163     // open it
   142 #if LIBAVCODEC_VERSION_MAJOR >= 53
       
   143     if (avcodec_open2(g_pAudio, g_pACodec, NULL) < 0)
   164     if (avcodec_open2(g_pAudio, g_pACodec, NULL) < 0)
   144 #else
       
   145     if (avcodec_open(g_pAudio, g_pACodec) < 0)
       
   146 #endif
       
   147     {
   165     {
   148         Log("Could not open audio codec %s\n", g_pACodec->long_name);
   166         Log("Could not open audio codec %s\n", g_pACodec->long_name);
   149         return;
   167         return;
   150     }
   168     }
   151 
   169 
   152 #if LIBAVCODEC_VERSION_MAJOR >= 54
   170 #if LIBAVCODEC_VERSION_MAJOR >= 54
   153     if (g_pACodec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)
   171     if (g_pACodec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)
   154 #else
   172 #else
   155     if (g_pAudio->frame_size == 0)
   173     if (g_pAudio->frame_size == 0)
   156 #endif
   174 #endif
   157         g_NumSamples = 4096;
   175         g_NumSamples = 4096;
   158     else
   176     else
   159         g_NumSamples = g_pAudio->frame_size;
   177         g_NumSamples = g_pAudio->frame_size;
   160     g_pSamples = (int16_t*)av_malloc(g_NumSamples*g_Channels*sizeof(int16_t));
   178     g_pSamples = (int16_t*)av_malloc(g_NumSamples*g_Channels*sizeof(int16_t));
   161     g_pAFrame = avcodec_alloc_frame();
   179     g_pAFrame = av_frame_alloc();
   162     if (!g_pAFrame)
   180     if (!g_pAFrame)
   163     {
   181     {
   164         Log("Could not allocate frame\n");
   182         Log("Could not allocate frame\n");
   165         return;
   183         return;
   166     }
   184     }
   215 }
   233 }
   216 
   234 
   217 // add a video output stream
   235 // add a video output stream
   218 static int AddVideoStream()
   236 static int AddVideoStream()
   219 {
   237 {
   220 #if LIBAVFORMAT_VERSION_MAJOR >= 53
       
   221     g_pVStream = avformat_new_stream(g_pContainer, g_pVCodec);
   238     g_pVStream = avformat_new_stream(g_pContainer, g_pVCodec);
   222 #else
       
   223     g_pVStream = av_new_stream(g_pContainer, 0);
       
   224 #endif
       
   225     if (!g_pVStream)
   239     if (!g_pVStream)
   226         return FatalError("Could not allocate video stream");
   240         return FatalError("Could not allocate video stream");
   227 
   241 
   228     g_pVideo = g_pVStream->codec;
   242     g_pVideo = g_pVStream->codec;
   229 
   243 
   239        timebase should be 1/framerate and timestamp increments should be
   253        timebase should be 1/framerate and timestamp increments should be
   240        identically 1. */
   254        identically 1. */
   241     g_pVideo->time_base.den = g_Framerate.num;
   255     g_pVideo->time_base.den = g_Framerate.num;
   242     g_pVideo->time_base.num = g_Framerate.den;
   256     g_pVideo->time_base.num = g_Framerate.den;
   243     //g_pVideo->gop_size = 12; /* emit one intra frame every twelve frames at most */
   257     //g_pVideo->gop_size = 12; /* emit one intra frame every twelve frames at most */
   244     g_pVideo->pix_fmt = PIX_FMT_YUV420P;
   258     g_pVideo->pix_fmt = AV_PIX_FMT_YUV420P;
   245 
   259 
   246     // set quality
   260     // set quality
   247     if (g_VQuality > 100)
   261     if (g_VQuality > 100)
   248         g_pVideo->bit_rate = g_VQuality;
   262         g_pVideo->bit_rate = g_VQuality;
   249     else
   263     else
   250     {
   264     {
   251         g_pVideo->flags |= CODEC_FLAG_QSCALE;
   265         g_pVideo->flags |= AV_CODEC_FLAG_QSCALE;
   252         g_pVideo->global_quality = g_VQuality*FF_QP2LAMBDA;
   266         g_pVideo->global_quality = g_VQuality*FF_QP2LAMBDA;
   253     }
   267     }
   254 
   268 
   255     // some formats want stream headers to be separate
   269     // some formats want stream headers to be separate
   256     if (g_pFormat->flags & AVFMT_GLOBALHEADER)
   270     if (g_pFormat->flags & AVFMT_GLOBALHEADER)
   257         g_pVideo->flags |= CODEC_FLAG_GLOBAL_HEADER;
   271         g_pVideo->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
   258 
   272 
   259 #if LIBAVCODEC_VERSION_MAJOR < 53
   273 #if LIBAVCODEC_VERSION_MAJOR < 53
   260     // for some versions of ffmpeg x264 options must be set explicitly
   274     // for some versions of ffmpeg x264 options must be set explicitly
   261     if (strcmp(g_pVCodec->name, "libx264") == 0)
   275     if (strcmp(g_pVCodec->name, "libx264") == 0)
   262     {
   276     {
   290     // open the codec
   304     // open the codec
   291 #if LIBAVCODEC_VERSION_MAJOR >= 53
   305 #if LIBAVCODEC_VERSION_MAJOR >= 53
   292     AVDictionary* pDict = NULL;
   306     AVDictionary* pDict = NULL;
   293     if (strcmp(g_pVCodec->name, "libx264") == 0)
   307     if (strcmp(g_pVCodec->name, "libx264") == 0)
   294         av_dict_set(&pDict, "preset", "medium", 0);
   308         av_dict_set(&pDict, "preset", "medium", 0);
       
   309 #endif
   295 
   310 
   296     if (avcodec_open2(g_pVideo, g_pVCodec, &pDict) < 0)
   311     if (avcodec_open2(g_pVideo, g_pVCodec, &pDict) < 0)
   297 #else
       
   298     if (avcodec_open(g_pVideo, g_pVCodec) < 0)
       
   299 #endif
       
   300         return FatalError("Could not open video codec %s", g_pVCodec->long_name);
   312         return FatalError("Could not open video codec %s", g_pVCodec->long_name);
   301 
   313 
   302     g_pVFrame = avcodec_alloc_frame();
   314     g_pVFrame = av_frame_alloc();
   303     if (!g_pVFrame)
   315     if (!g_pVFrame)
   304         return FatalError("Could not allocate frame");
   316         return FatalError("Could not allocate frame");
   305 
   317 
   306     g_pVFrame->linesize[0] = g_Width;
   318     g_pVFrame->linesize[0] = g_Width;
   307     g_pVFrame->linesize[1] = g_Width/2;
   319     g_pVFrame->linesize[1] = g_Width/2;
   315     double AudioTime, VideoTime;
   327     double AudioTime, VideoTime;
   316     int ret;
   328     int ret;
   317     // write interleaved audio frame
   329     // write interleaved audio frame
   318     if (g_pAStream)
   330     if (g_pAStream)
   319     {
   331     {
   320         VideoTime = (double)g_pVStream->pts.val*g_pVStream->time_base.num/g_pVStream->time_base.den;
   332         VideoTime = (double)g_pVFrame->pts * g_pVStream->time_base.num/g_pVStream->time_base.den;
   321         do
   333         do
   322         {
   334         {
   323             AudioTime = (double)g_pAStream->pts.val*g_pAStream->time_base.num/g_pAStream->time_base.den;
   335             AudioTime = (double)g_pAFrame->pts * g_pAStream->time_base.num/g_pAStream->time_base.den;
   324             ret = WriteAudioFrame();
   336             ret = WriteAudioFrame();
   325         }
   337         }
   326         while (AudioTime < VideoTime && ret);
   338         while (AudioTime < VideoTime && ret);
   327         if (ret < 0)
   339         if (ret < 0)
   328             return ret;
   340             return ret;
   494 
   506 
   495 AVWRAP_DECL int AVWrapper_Close()
   507 AVWRAP_DECL int AVWrapper_Close()
   496 {
   508 {
   497     int ret;
   509     int ret;
   498     // output buffered frames
   510     // output buffered frames
   499     if (g_pVCodec->capabilities & CODEC_CAP_DELAY)
   511     if (g_pVCodec->capabilities & AV_CODEC_CAP_DELAY)
   500     {
   512     {
   501         do
   513         do
   502             ret = WriteFrame(NULL);
   514             ret = WriteFrame(NULL);
   503         while (ret >= 0);
   515         while (ret >= 0);
   504         if (ret < 0)
   516         if (ret < 0)
   524     if (g_pVStream)
   536     if (g_pVStream)
   525     {
   537     {
   526         avcodec_close(g_pVideo);
   538         avcodec_close(g_pVideo);
   527         av_free(g_pVideo);
   539         av_free(g_pVideo);
   528         av_free(g_pVStream);
   540         av_free(g_pVStream);
   529         av_free(g_pVFrame);
   541         av_frame_free(&g_pVFrame);
   530     }
   542     }
   531     if (g_pAStream)
   543     if (g_pAStream)
   532     {
   544     {
   533         avcodec_close(g_pAudio);
   545         avcodec_close(g_pAudio);
   534         av_free(g_pAudio);
   546         av_free(g_pAudio);
   535         av_free(g_pAStream);
   547         av_free(g_pAStream);
   536         av_free(g_pAFrame);
   548         av_frame_free(&g_pAFrame);
   537         av_free(g_pSamples);
   549         av_free(g_pSamples);
   538         fclose(g_pSoundFile);
   550         fclose(g_pSoundFile);
   539     }
   551     }
   540 
   552 
   541     av_free(g_pContainer);
   553     av_free(g_pContainer);