hedgewars/avwrapper.c
changeset 9224 bce8cf41d666
parent 9223 71fc5893071c
parent 8869 11438c0bd46b
child 9225 d8d929f92633
equal deleted inserted replaced
9223:71fc5893071c 9224:bce8cf41d666
     1 /*
       
     2  * Hedgewars, a free turn based strategy game
       
     3  * Copyright (c) 2004-2013 Andrey Korotaev <unC0Rr@gmail.com>
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License as published by
       
     7  * the Free Software Foundation; version 2 of the License
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
       
    17  */
       
    18 
       
    19 #include <stdlib.h>
       
    20 #include <stdio.h>
       
    21 #include <stdint.h>
       
    22 #include <string.h>
       
    23 #include <stdarg.h>
       
    24 #include "libavformat/avformat.h"
       
    25 #include "libavutil/mathematics.h"
       
    26 
       
    27 #ifndef AVIO_FLAG_WRITE
       
    28 #define AVIO_FLAG_WRITE AVIO_WRONLY
       
    29 #endif
       
    30 
       
    31 #if (defined _MSC_VER)
       
    32 #define AVWRAP_DECL __declspec(dllexport)
       
    33 #elif ((__GNUC__ >= 3) && (!__EMX__) && (!sun))
       
    34 #define AVWRAP_DECL __attribute__((visibility("default")))
       
    35 #else
       
    36 #define AVWRAP_DECL
       
    37 #endif
       
    38 
       
    39 static AVFormatContext* g_pContainer;
       
    40 static AVOutputFormat* g_pFormat;
       
    41 static AVStream* g_pAStream;
       
    42 static AVStream* g_pVStream;
       
    43 static AVFrame* g_pAFrame;
       
    44 static AVFrame* g_pVFrame;
       
    45 static AVCodec* g_pACodec;
       
    46 static AVCodec* g_pVCodec;
       
    47 static AVCodecContext* g_pAudio;
       
    48 static AVCodecContext* g_pVideo;
       
    49 
       
    50 static int g_Width, g_Height;
       
    51 static uint32_t g_Frequency, g_Channels;
       
    52 static int g_VQuality;
       
    53 static AVRational g_Framerate;
       
    54 
       
    55 static FILE* g_pSoundFile;
       
    56 static int16_t* g_pSamples;
       
    57 static int g_NumSamples;
       
    58 
       
    59 
       
    60 #if LIBAVCODEC_VERSION_MAJOR < 54
       
    61 #define OUTBUFFER_SIZE 200000
       
    62 static uint8_t g_OutBuffer[OUTBUFFER_SIZE];
       
    63 #endif
       
    64 
       
    65 // pointer to function from hwengine (uUtils.pas)
       
    66 static void (*AddFileLogRaw)(const char* pString);
       
    67 
       
    68 static void FatalError(const char* pFmt, ...)
       
    69 {
       
    70     char Buffer[1024];
       
    71     va_list VaArgs;
       
    72 
       
    73     va_start(VaArgs, pFmt);
       
    74     vsnprintf(Buffer, 1024, pFmt, VaArgs);
       
    75     va_end(VaArgs);
       
    76 
       
    77     AddFileLogRaw("Error in av-wrapper: ");
       
    78     AddFileLogRaw(Buffer);
       
    79     AddFileLogRaw("\n");
       
    80     exit(1);
       
    81 }
       
    82 
       
    83 // Function to be called from libav for logging.
       
    84 // Note: libav can call LogCallback from different threads
       
    85 // (there is mutex in AddFileLogRaw).
       
    86 static void LogCallback(void* p, int Level, const char* pFmt, va_list VaArgs)
       
    87 {
       
    88     char Buffer[1024];
       
    89 
       
    90     vsnprintf(Buffer, 1024, pFmt, VaArgs);
       
    91     AddFileLogRaw(Buffer);
       
    92 }
       
    93 
       
    94 static void Log(const char* pFmt, ...)
       
    95 {
       
    96     char Buffer[1024];
       
    97     va_list VaArgs;
       
    98 
       
    99     va_start(VaArgs, pFmt);
       
   100     vsnprintf(Buffer, 1024, pFmt, VaArgs);
       
   101     va_end(VaArgs);
       
   102 
       
   103     AddFileLogRaw(Buffer);
       
   104 }
       
   105 
       
   106 static void AddAudioStream()
       
   107 {
       
   108 #if LIBAVFORMAT_VERSION_MAJOR >= 53
       
   109     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)
       
   114     {
       
   115         Log("Could not allocate audio stream\n");
       
   116         return;
       
   117     }
       
   118     g_pAStream->id = 1;
       
   119 
       
   120     g_pAudio = g_pAStream->codec;
       
   121 
       
   122     avcodec_get_context_defaults3(g_pAudio, g_pACodec);
       
   123     g_pAudio->codec_id = g_pACodec->id;
       
   124 
       
   125     // put parameters
       
   126     g_pAudio->sample_fmt = AV_SAMPLE_FMT_S16;
       
   127     g_pAudio->sample_rate = g_Frequency;
       
   128     g_pAudio->channels = g_Channels;
       
   129 
       
   130     // set quality
       
   131     g_pAudio->bit_rate = 160000;
       
   132 
       
   133     // for codecs that support variable bitrate use it, it should be better
       
   134     g_pAudio->flags |= CODEC_FLAG_QSCALE;
       
   135     g_pAudio->global_quality = 1*FF_QP2LAMBDA;
       
   136 
       
   137     // some formats want stream headers to be separate
       
   138     if (g_pFormat->flags & AVFMT_GLOBALHEADER)
       
   139         g_pAudio->flags |= CODEC_FLAG_GLOBAL_HEADER;
       
   140 
       
   141     // open it
       
   142 #if LIBAVCODEC_VERSION_MAJOR >= 53
       
   143     if (avcodec_open2(g_pAudio, g_pACodec, NULL) < 0)
       
   144 #else
       
   145     if (avcodec_open(g_pAudio, g_pACodec) < 0)
       
   146 #endif
       
   147     {
       
   148         Log("Could not open audio codec %s\n", g_pACodec->long_name);
       
   149         return;
       
   150     }
       
   151 
       
   152 #if LIBAVCODEC_VERSION_MAJOR >= 54
       
   153     if (g_pACodec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)
       
   154 #else
       
   155     if (g_pAudio->frame_size == 0)
       
   156 #endif
       
   157         g_NumSamples = 4096;
       
   158     else
       
   159         g_NumSamples = g_pAudio->frame_size;
       
   160     g_pSamples = (int16_t*)av_malloc(g_NumSamples*g_Channels*sizeof(int16_t));
       
   161     g_pAFrame = avcodec_alloc_frame();
       
   162     if (!g_pAFrame)
       
   163     {
       
   164         Log("Could not allocate frame\n");
       
   165         return;
       
   166     }
       
   167 }
       
   168 
       
   169 // returns non-zero if there is more sound
       
   170 static int WriteAudioFrame()
       
   171 {
       
   172     if (!g_pAStream)
       
   173         return 0;
       
   174 
       
   175     AVPacket Packet = { 0 };
       
   176     av_init_packet(&Packet);
       
   177 
       
   178     int NumSamples = fread(g_pSamples, 2*g_Channels, g_NumSamples, g_pSoundFile);
       
   179 
       
   180 #if LIBAVCODEC_VERSION_MAJOR >= 53
       
   181     AVFrame* pFrame = NULL;
       
   182     if (NumSamples > 0)
       
   183     {
       
   184         g_pAFrame->nb_samples = NumSamples;
       
   185         avcodec_fill_audio_frame(g_pAFrame, g_Channels, AV_SAMPLE_FMT_S16,
       
   186                                  (uint8_t*)g_pSamples, NumSamples*2*g_Channels, 1);
       
   187         pFrame = g_pAFrame;
       
   188     }
       
   189     // when NumSamples == 0 we still need to call encode_audio2 to flush
       
   190     int got_packet;
       
   191     if (avcodec_encode_audio2(g_pAudio, &Packet, pFrame, &got_packet) != 0)
       
   192         FatalError("avcodec_encode_audio2 failed");
       
   193     if (!got_packet)
       
   194         return 0;
       
   195 #else
       
   196     if (NumSamples == 0)
       
   197         return 0;
       
   198     int BufferSize = OUTBUFFER_SIZE;
       
   199     if (g_pAudio->frame_size == 0)
       
   200         BufferSize = NumSamples*g_Channels*2;
       
   201     Packet.size = avcodec_encode_audio(g_pAudio, g_OutBuffer, BufferSize, g_pSamples);
       
   202     if (Packet.size == 0)
       
   203         return 1;
       
   204     if (g_pAudio->coded_frame && g_pAudio->coded_frame->pts != AV_NOPTS_VALUE)
       
   205         Packet.pts = av_rescale_q(g_pAudio->coded_frame->pts, g_pAudio->time_base, g_pAStream->time_base);
       
   206     Packet.flags |= AV_PKT_FLAG_KEY;
       
   207     Packet.data = g_OutBuffer;
       
   208 #endif
       
   209 
       
   210     // Write the compressed frame to the media file.
       
   211     Packet.stream_index = g_pAStream->index;
       
   212     if (av_interleaved_write_frame(g_pContainer, &Packet) != 0) 
       
   213         FatalError("Error while writing audio frame");
       
   214     return 1;
       
   215 }
       
   216 
       
   217 // add a video output stream
       
   218 static void AddVideoStream()
       
   219 {
       
   220 #if LIBAVFORMAT_VERSION_MAJOR >= 53
       
   221     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)
       
   226         FatalError("Could not allocate video stream");
       
   227 
       
   228     g_pVideo = g_pVStream->codec;
       
   229 
       
   230     avcodec_get_context_defaults3(g_pVideo, g_pVCodec);
       
   231     g_pVideo->codec_id = g_pVCodec->id;
       
   232 
       
   233     // put parameters
       
   234     // resolution must be a multiple of two
       
   235     g_pVideo->width  = g_Width  & ~1; // make even (dimensions should be even)
       
   236     g_pVideo->height = g_Height & ~1; // make even
       
   237     /* time base: this is the fundamental unit of time (in seconds) in terms
       
   238        of which frame timestamps are represented. for fixed-fps content,
       
   239        timebase should be 1/framerate and timestamp increments should be
       
   240        identically 1. */
       
   241     g_pVideo->time_base.den = g_Framerate.num;
       
   242     g_pVideo->time_base.num = g_Framerate.den;
       
   243     //g_pVideo->gop_size = 12; /* emit one intra frame every twelve frames at most */
       
   244     g_pVideo->pix_fmt = PIX_FMT_YUV420P;
       
   245 
       
   246     // set quality
       
   247     if (g_VQuality > 100)
       
   248         g_pVideo->bit_rate = g_VQuality;
       
   249     else
       
   250     {
       
   251         g_pVideo->flags |= CODEC_FLAG_QSCALE;
       
   252         g_pVideo->global_quality = g_VQuality*FF_QP2LAMBDA;
       
   253     }
       
   254 
       
   255     // some formats want stream headers to be separate
       
   256     if (g_pFormat->flags & AVFMT_GLOBALHEADER)
       
   257         g_pVideo->flags |= CODEC_FLAG_GLOBAL_HEADER;
       
   258 
       
   259 #if LIBAVCODEC_VERSION_MAJOR < 53
       
   260     // for some versions of ffmpeg x264 options must be set explicitly
       
   261     if (strcmp(g_pVCodec->name, "libx264") == 0)
       
   262     {
       
   263         g_pVideo->coder_type = FF_CODER_TYPE_AC;
       
   264         g_pVideo->flags |= CODEC_FLAG_LOOP_FILTER;
       
   265         g_pVideo->crf = 23;
       
   266         g_pVideo->thread_count = 3;
       
   267         g_pVideo->me_cmp = FF_CMP_CHROMA;
       
   268         g_pVideo->partitions = X264_PART_I8X8 | X264_PART_I4X4 | X264_PART_P8X8 | X264_PART_B8X8;
       
   269         g_pVideo->me_method = ME_HEX;
       
   270         g_pVideo->me_subpel_quality = 7;
       
   271         g_pVideo->me_range = 16;
       
   272         g_pVideo->gop_size = 250;
       
   273         g_pVideo->keyint_min = 25;
       
   274         g_pVideo->scenechange_threshold = 40;
       
   275         g_pVideo->i_quant_factor = 0.71;
       
   276         g_pVideo->b_frame_strategy = 1;
       
   277         g_pVideo->qcompress = 0.6;
       
   278         g_pVideo->qmin = 10;
       
   279         g_pVideo->qmax = 51;
       
   280         g_pVideo->max_qdiff = 4;
       
   281         g_pVideo->max_b_frames = 3;
       
   282         g_pVideo->refs = 3;
       
   283         g_pVideo->directpred = 1;
       
   284         g_pVideo->trellis = 1;
       
   285         g_pVideo->flags2 = CODEC_FLAG2_BPYRAMID | CODEC_FLAG2_MIXED_REFS | CODEC_FLAG2_WPRED | CODEC_FLAG2_8X8DCT | CODEC_FLAG2_FASTPSKIP;
       
   286         g_pVideo->weighted_p_pred = 2;
       
   287     }
       
   288 #endif
       
   289 
       
   290     // open the codec
       
   291 #if LIBAVCODEC_VERSION_MAJOR >= 53
       
   292     AVDictionary* pDict = NULL;
       
   293     if (strcmp(g_pVCodec->name, "libx264") == 0)
       
   294         av_dict_set(&pDict, "preset", "medium", 0);
       
   295 
       
   296     if (avcodec_open2(g_pVideo, g_pVCodec, &pDict) < 0)
       
   297 #else
       
   298     if (avcodec_open(g_pVideo, g_pVCodec) < 0)
       
   299 #endif
       
   300         FatalError("Could not open video codec %s", g_pVCodec->long_name);
       
   301 
       
   302     g_pVFrame = avcodec_alloc_frame();
       
   303     if (!g_pVFrame)
       
   304         FatalError("Could not allocate frame");
       
   305 
       
   306     g_pVFrame->linesize[0] = g_Width;
       
   307     g_pVFrame->linesize[1] = g_Width/2;
       
   308     g_pVFrame->linesize[2] = g_Width/2;
       
   309     g_pVFrame->linesize[3] = 0;
       
   310 }
       
   311 
       
   312 static int WriteFrame(AVFrame* pFrame)
       
   313 {
       
   314     double AudioTime, VideoTime;
       
   315 
       
   316     // write interleaved audio frame
       
   317     if (g_pAStream)
       
   318     {
       
   319         VideoTime = (double)g_pVStream->pts.val*g_pVStream->time_base.num/g_pVStream->time_base.den;
       
   320         do
       
   321             AudioTime = (double)g_pAStream->pts.val*g_pAStream->time_base.num/g_pAStream->time_base.den;
       
   322         while (AudioTime < VideoTime && WriteAudioFrame());
       
   323     }
       
   324     
       
   325     if (!g_pVStream)
       
   326         return 0;
       
   327 
       
   328     AVPacket Packet;
       
   329     av_init_packet(&Packet);
       
   330     Packet.data = NULL;
       
   331     Packet.size = 0;
       
   332 
       
   333     g_pVFrame->pts++;
       
   334     if (g_pFormat->flags & AVFMT_RAWPICTURE)
       
   335     {
       
   336         /* raw video case. The API will change slightly in the near
       
   337            future for that. */
       
   338         Packet.flags |= AV_PKT_FLAG_KEY;
       
   339         Packet.stream_index = g_pVStream->index;
       
   340         Packet.data = (uint8_t*)pFrame;
       
   341         Packet.size = sizeof(AVPicture);
       
   342 
       
   343         if (av_interleaved_write_frame(g_pContainer, &Packet) != 0)
       
   344             FatalError("Error while writing video frame");
       
   345         return 0;
       
   346     }
       
   347     else
       
   348     {
       
   349 #if LIBAVCODEC_VERSION_MAJOR >= 54
       
   350         int got_packet;
       
   351         if (avcodec_encode_video2(g_pVideo, &Packet, pFrame, &got_packet) < 0)
       
   352             FatalError("avcodec_encode_video2 failed");
       
   353         if (!got_packet)
       
   354             return 0;
       
   355 
       
   356         if (Packet.pts != AV_NOPTS_VALUE)
       
   357             Packet.pts = av_rescale_q(Packet.pts, g_pVideo->time_base, g_pVStream->time_base);
       
   358         if (Packet.dts != AV_NOPTS_VALUE)
       
   359             Packet.dts = av_rescale_q(Packet.dts, g_pVideo->time_base, g_pVStream->time_base);
       
   360 #else 
       
   361         Packet.size = avcodec_encode_video(g_pVideo, g_OutBuffer, OUTBUFFER_SIZE, pFrame);
       
   362         if (Packet.size < 0)
       
   363             FatalError("avcodec_encode_video failed");
       
   364         if (Packet.size == 0)
       
   365             return 0;
       
   366 
       
   367         if( g_pVideo->coded_frame->pts != AV_NOPTS_VALUE)
       
   368             Packet.pts = av_rescale_q(g_pVideo->coded_frame->pts, g_pVideo->time_base, g_pVStream->time_base);
       
   369         if( g_pVideo->coded_frame->key_frame )
       
   370             Packet.flags |= AV_PKT_FLAG_KEY;
       
   371         Packet.data = g_OutBuffer;
       
   372 #endif
       
   373         // write the compressed frame in the media file
       
   374         Packet.stream_index = g_pVStream->index;
       
   375         if (av_interleaved_write_frame(g_pContainer, &Packet) != 0)
       
   376             FatalError("Error while writing video frame");
       
   377             
       
   378         return 1;
       
   379     }
       
   380 }
       
   381 
       
   382 AVWRAP_DECL void AVWrapper_WriteFrame(uint8_t* pY, uint8_t* pCb, uint8_t* pCr)
       
   383 {
       
   384     g_pVFrame->data[0] = pY;
       
   385     g_pVFrame->data[1] = pCb;
       
   386     g_pVFrame->data[2] = pCr;
       
   387     WriteFrame(g_pVFrame);
       
   388 }
       
   389 
       
   390 AVWRAP_DECL void AVWrapper_Init(
       
   391          void (*pAddFileLogRaw)(const char*),
       
   392          const char* pFilename,
       
   393          const char* pDesc,
       
   394          const char* pSoundFile,
       
   395          const char* pFormatName,
       
   396          const char* pVCodecName,
       
   397          const char* pACodecName,
       
   398          int Width, int Height,
       
   399          int FramerateNum, int FramerateDen,
       
   400          int VQuality)
       
   401 {    
       
   402     AddFileLogRaw = pAddFileLogRaw;
       
   403     av_log_set_callback( &LogCallback );
       
   404 
       
   405     g_Width  = Width;
       
   406     g_Height = Height;
       
   407     g_Framerate.num = FramerateNum;
       
   408     g_Framerate.den = FramerateDen;
       
   409     g_VQuality = VQuality;
       
   410 
       
   411     // initialize libav and register all codecs and formats
       
   412     av_register_all();
       
   413 
       
   414     // find format
       
   415     g_pFormat = av_guess_format(pFormatName, NULL, NULL);
       
   416     if (!g_pFormat)
       
   417         FatalError("Format \"%s\" was not found", pFormatName);
       
   418 
       
   419     // allocate the output media context
       
   420     g_pContainer = avformat_alloc_context();
       
   421     if (!g_pContainer)
       
   422         FatalError("Could not allocate output context");
       
   423 
       
   424     g_pContainer->oformat = g_pFormat;
       
   425 
       
   426     // store description of file
       
   427     av_dict_set(&g_pContainer->metadata, "comment", pDesc, 0);
       
   428 
       
   429     // append extesnion to filename
       
   430     char ext[16];
       
   431     strncpy(ext, g_pFormat->extensions, 16);
       
   432     ext[15] = 0;
       
   433     ext[strcspn(ext,",")] = 0;
       
   434     snprintf(g_pContainer->filename, sizeof(g_pContainer->filename), "%s.%s", pFilename, ext);
       
   435 
       
   436     // find codecs
       
   437     g_pVCodec = avcodec_find_encoder_by_name(pVCodecName);
       
   438     g_pACodec = avcodec_find_encoder_by_name(pACodecName);
       
   439 
       
   440     // add audio and video stream to container
       
   441     g_pVStream = NULL;
       
   442     g_pAStream = NULL;
       
   443 
       
   444     if (g_pVCodec)
       
   445         AddVideoStream();
       
   446     else
       
   447         Log("Video codec \"%s\" was not found; video will be ignored.\n", pVCodecName);
       
   448 
       
   449     if (g_pACodec)
       
   450     {
       
   451         g_pSoundFile = fopen(pSoundFile, "rb");
       
   452         if (g_pSoundFile)
       
   453         {
       
   454             fread(&g_Frequency, 4, 1, g_pSoundFile);
       
   455             fread(&g_Channels, 4, 1, g_pSoundFile);
       
   456             AddAudioStream();
       
   457         }
       
   458         else
       
   459             Log("Could not open %s\n", pSoundFile);
       
   460     }
       
   461     else
       
   462         Log("Audio codec \"%s\" was not found; audio will be ignored.\n", pACodecName);
       
   463 
       
   464     if (!g_pAStream && !g_pVStream)
       
   465         FatalError("No video, no audio, aborting...");
       
   466 
       
   467     // write format info to log
       
   468     av_dump_format(g_pContainer, 0, g_pContainer->filename, 1);
       
   469 
       
   470     // open the output file, if needed
       
   471     if (!(g_pFormat->flags & AVFMT_NOFILE))
       
   472     {
       
   473         if (avio_open(&g_pContainer->pb, g_pContainer->filename, AVIO_FLAG_WRITE) < 0)
       
   474             FatalError("Could not open output file (%s)", g_pContainer->filename);
       
   475     }
       
   476 
       
   477     // write the stream header, if any
       
   478     avformat_write_header(g_pContainer, NULL);
       
   479 
       
   480     g_pVFrame->pts = -1;
       
   481 }
       
   482 
       
   483 AVWRAP_DECL void AVWrapper_Close()
       
   484 {
       
   485     // output buffered frames
       
   486     if (g_pVCodec->capabilities & CODEC_CAP_DELAY)
       
   487         while( WriteFrame(NULL) );
       
   488     // output any remaining audio
       
   489     while( WriteAudioFrame() );
       
   490 
       
   491     // write the trailer, if any.
       
   492     av_write_trailer(g_pContainer);
       
   493 
       
   494     // close the output file
       
   495     if (!(g_pFormat->flags & AVFMT_NOFILE))
       
   496         avio_close(g_pContainer->pb);
       
   497 
       
   498     // free everything
       
   499     if (g_pVStream)
       
   500     {
       
   501         avcodec_close(g_pVideo);
       
   502         av_free(g_pVideo);
       
   503         av_free(g_pVStream);
       
   504         av_free(g_pVFrame);
       
   505     }
       
   506     if (g_pAStream)
       
   507     {
       
   508         avcodec_close(g_pAudio);
       
   509         av_free(g_pAudio);
       
   510         av_free(g_pAStream);
       
   511         av_free(g_pAFrame);
       
   512         av_free(g_pSamples);
       
   513         fclose(g_pSoundFile);
       
   514     }
       
   515 
       
   516     av_free(g_pContainer);
       
   517 }