hedgewars/avwrapper.c
changeset 7280 fd707afbc3a2
parent 7235 baa69bd025d9
child 7282 c65992e2d794
equal deleted inserted replaced
7278:000e4543f204 7280:fd707afbc3a2
     1 
     1 
     2 #include <stdlib.h>
     2 #include <stdlib.h>
     3 #include <stdio.h>
     3 #include <stdio.h>
       
     4 #include <stdint.h>
     4 #include <string.h>
     5 #include <string.h>
     5 #include <stdarg.h>
     6 #include <stdarg.h>
     6 #include "libavformat/avformat.h"
     7 #include "libavformat/avformat.h"
     7 
     8 
     8 static AVFormatContext* g_pContainer;
     9 static AVFormatContext* g_pContainer;
    15 static AVCodec* g_pVCodec;
    16 static AVCodec* g_pVCodec;
    16 static AVCodecContext* g_pAudio;
    17 static AVCodecContext* g_pAudio;
    17 static AVCodecContext* g_pVideo;
    18 static AVCodecContext* g_pVideo;
    18 
    19 
    19 static int g_Width, g_Height;
    20 static int g_Width, g_Height;
    20 static int g_Frequency, g_Channels;
    21 static uint32_t g_Frequency, g_Channels;
    21 static int g_VQuality, g_AQuality;
    22 static int g_VQuality, g_AQuality;
    22 static AVRational g_Framerate;
    23 static AVRational g_Framerate;
    23 static const char* g_pPreset;
    24 static const char* g_pPreset;
    24 
    25 
    25 static FILE* g_pSoundFile;
    26 static FILE* g_pSoundFile;
    26 static int16_t* g_pSamples;
    27 static int16_t* g_pSamples;
    27 static int g_NumSamples;
    28 static int g_NumSamples;
    28 
       
    29 static char g_Filename[1024];
       
    30 
    29 
    31 /*
    30 /*
    32 Initially I wrote code for latest ffmpeg, but on Linux (Ubuntu)
    31 Initially I wrote code for latest ffmpeg, but on Linux (Ubuntu)
    33 only older version is available from repository. That's why you see here
    32 only older version is available from repository. That's why you see here
    34 all of this #if LIBAVCODEC_VERSION_MAJOR < 54.
    33 all of this #if LIBAVCODEC_VERSION_MAJOR < 54.
    88     g_pAStream = avformat_new_stream(g_pContainer, g_pACodec);
    87     g_pAStream = avformat_new_stream(g_pContainer, g_pACodec);
    89 #else
    88 #else
    90     g_pAStream = av_new_stream(g_pContainer, 1);
    89     g_pAStream = av_new_stream(g_pContainer, 1);
    91 #endif
    90 #endif
    92     if(!g_pAStream)
    91     if(!g_pAStream)
    93         FatalError("Could not allocate audio stream");
    92     {
       
    93         Log("Could not allocate audio stream");
       
    94         return;
       
    95     }
    94     g_pAStream->id = 1;
    96     g_pAStream->id = 1;
    95 
    97 
    96     g_pAudio = g_pAStream->codec;
    98     g_pAudio = g_pAStream->codec;
    97 
    99 
    98     avcodec_get_context_defaults3(g_pAudio, g_pACodec);
   100     avcodec_get_context_defaults3(g_pAudio, g_pACodec);
   116     if (g_pFormat->flags & AVFMT_GLOBALHEADER)
   118     if (g_pFormat->flags & AVFMT_GLOBALHEADER)
   117         g_pAudio->flags |= CODEC_FLAG_GLOBAL_HEADER;
   119         g_pAudio->flags |= CODEC_FLAG_GLOBAL_HEADER;
   118 
   120 
   119     // open it
   121     // open it
   120     if (avcodec_open2(g_pAudio, g_pACodec, NULL) < 0)
   122     if (avcodec_open2(g_pAudio, g_pACodec, NULL) < 0)
   121         FatalError("Could not open audio codec %s", g_pACodec->long_name);
   123     {
       
   124         Log("Could not open audio codec %s", g_pACodec->long_name);
       
   125         return;
       
   126     }
   122 
   127 
   123 #if LIBAVCODEC_VERSION_MAJOR >= 54
   128 #if LIBAVCODEC_VERSION_MAJOR >= 54
   124     if (g_pACodec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)
   129     if (g_pACodec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)
   125 #else
   130 #else
   126     if (g_pAudio->frame_size == 0)
   131     if (g_pAudio->frame_size == 0)
   129     else
   134     else
   130         g_NumSamples = g_pAudio->frame_size;
   135         g_NumSamples = g_pAudio->frame_size;
   131     g_pSamples = (int16_t*)av_malloc(g_NumSamples*g_Channels*sizeof(int16_t));
   136     g_pSamples = (int16_t*)av_malloc(g_NumSamples*g_Channels*sizeof(int16_t));
   132     g_pAFrame = avcodec_alloc_frame();
   137     g_pAFrame = avcodec_alloc_frame();
   133     if (!g_pAFrame)
   138     if (!g_pAFrame)
   134         FatalError("Could not allocate frame");
   139     {
       
   140         Log("Could not allocate frame");
       
   141         return;
       
   142     }
   135 }
   143 }
   136 
   144 
   137 // returns non-zero if there is more sound
   145 // returns non-zero if there is more sound
   138 static int WriteAudioFrame()
   146 static int WriteAudioFrame()
   139 {
   147 {
   240     g_pVFrame->linesize[1] = g_Width/2;
   248     g_pVFrame->linesize[1] = g_Width/2;
   241     g_pVFrame->linesize[2] = g_Width/2;
   249     g_pVFrame->linesize[2] = g_Width/2;
   242     g_pVFrame->linesize[3] = 0;
   250     g_pVFrame->linesize[3] = 0;
   243 }
   251 }
   244 
   252 
   245 static int WriteFrame( AVFrame* pFrame )
   253 static int WriteFrame(AVFrame* pFrame)
   246 {
   254 {
   247     double AudioTime, VideoTime;
   255     double AudioTime, VideoTime;
   248 
   256 
   249     // write interleaved audio frame
   257     // write interleaved audio frame
   250     if (g_pAStream)
   258     if (g_pAStream)
   321 }
   329 }
   322 
   330 
   323 void AVWrapper_Init(
   331 void AVWrapper_Init(
   324          void (*pAddFileLogRaw)(const char*),
   332          void (*pAddFileLogRaw)(const char*),
   325          const char* pFilename,
   333          const char* pFilename,
   326          const char* pFinalFilename,
   334          const char* pDesc,
   327          const char* pSoundFile,
   335          const char* pSoundFile,
   328          const char* pFormatName,
   336          const char* pFormatName,
   329          const char* pVCodecName,
   337          const char* pVCodecName,
   330          const char* pACodecName,
   338          const char* pACodecName,
   331          const char* pVPreset,
   339          const char* pVPreset,
   332          int Width, int Height,
   340          int Width, int Height,
   333          int FramerateNum, int FramerateDen,
   341          int FramerateNum, int FramerateDen,
   334          int Frequency, int Channels,
       
   335          int VQuality, int AQuality)
   342          int VQuality, int AQuality)
   336 {    
   343 {    
   337     AddFileLogRaw = pAddFileLogRaw;
   344     AddFileLogRaw = pAddFileLogRaw;
   338     av_log_set_callback( &LogCallback );
   345     av_log_set_callback( &LogCallback );
   339 
   346 
   340     g_Width = Width;
   347     g_Width  = Width  & ~1; // make even (dimensions should be even)
   341     g_Height = Height;
   348     g_Height = Height & ~1; // make even
   342     g_Framerate.num = FramerateNum;
   349     g_Framerate.num = FramerateNum;
   343     g_Framerate.den = FramerateDen;
   350     g_Framerate.den = FramerateDen;
   344     g_Frequency = Frequency;
       
   345     g_Channels = Channels;
       
   346     g_VQuality = VQuality;
   351     g_VQuality = VQuality;
   347     g_AQuality = AQuality;
   352     g_AQuality = AQuality;
   348     g_pPreset = pVPreset;
   353     g_pPreset = pVPreset;
   349 
   354 
   350     // initialize libav and register all codecs and formats
   355     // initialize libav and register all codecs and formats
   359     g_pContainer = avformat_alloc_context();
   364     g_pContainer = avformat_alloc_context();
   360     if (!g_pContainer)
   365     if (!g_pContainer)
   361         FatalError("Could not allocate output context");
   366         FatalError("Could not allocate output context");
   362 
   367 
   363     g_pContainer->oformat = g_pFormat;
   368     g_pContainer->oformat = g_pFormat;
       
   369 
       
   370     // store description of file
       
   371     av_dict_set(&g_pContainer->metadata, "comment", pDesc, 0);
   364 
   372 
   365     // append extesnion to filename
   373     // append extesnion to filename
   366     char ext[16];
   374     char ext[16];
   367     strncpy(ext, g_pFormat->extensions, 16);
   375     strncpy(ext, g_pFormat->extensions, 16);
   368     ext[15] = 0;
   376     ext[15] = 0;
   369     ext[strcspn(ext,",")] = 0;
   377     ext[strcspn(ext,",")] = 0;
   370     snprintf(g_pContainer->filename, sizeof(g_pContainer->filename), "%s.%s", pFilename, ext);
   378     snprintf(g_pContainer->filename, sizeof(g_pContainer->filename), "%s.%s", pFilename, ext);
   371     snprintf(g_Filename, sizeof(g_Filename), "%s.%s", pFinalFilename, ext);
       
   372 
   379 
   373     // find codecs
   380     // find codecs
   374     g_pVCodec = avcodec_find_encoder_by_name(pVCodecName);
   381     g_pVCodec = avcodec_find_encoder_by_name(pVCodecName);
   375     g_pACodec = avcodec_find_encoder_by_name(pACodecName);
   382     g_pACodec = avcodec_find_encoder_by_name(pACodecName);
   376 
   383 
   382         AddVideoStream();
   389         AddVideoStream();
   383     else
   390     else
   384         Log("Video codec \"%s\" was not found; video will be ignored.\n", pVCodecName);
   391         Log("Video codec \"%s\" was not found; video will be ignored.\n", pVCodecName);
   385 
   392 
   386     if (g_pACodec)
   393     if (g_pACodec)
   387         AddAudioStream();
   394     {
       
   395         g_pSoundFile = fopen(pSoundFile, "rb");
       
   396         if (g_pSoundFile)
       
   397         {
       
   398             fread(&g_Frequency, 4, 1, g_pSoundFile);
       
   399             fread(&g_Channels, 4, 1, g_pSoundFile);
       
   400             AddAudioStream();
       
   401         }
       
   402         else
       
   403             Log("Could not open %s", pSoundFile);
       
   404     }
   388     else
   405     else
   389         Log("Audio codec \"%s\" was not found; audio will be ignored.\n", pACodecName);
   406         Log("Audio codec \"%s\" was not found; audio will be ignored.\n", pACodecName);
   390 
   407 
   391     if (!g_pAStream && !g_pVStream)
   408     if (!g_pAStream && !g_pVStream)
   392         FatalError("No video, no audio, aborting...");
   409         FatalError("No video, no audio, aborting...");
   393 
       
   394     if (g_pAStream)
       
   395     {
       
   396         g_pSoundFile = fopen(pSoundFile, "rb");
       
   397         if (!g_pSoundFile)
       
   398             FatalError("Could not open %s", pSoundFile);
       
   399     }
       
   400 
   410 
   401     // write format info to log
   411     // write format info to log
   402     av_dump_format(g_pContainer, 0, g_pContainer->filename, 1);
   412     av_dump_format(g_pContainer, 0, g_pContainer->filename, 1);
   403 
   413 
   404     // open the output file, if needed
   414     // open the output file, if needed
   426     av_write_trailer(g_pContainer);
   436     av_write_trailer(g_pContainer);
   427 
   437 
   428     // close the output file
   438     // close the output file
   429     if (!(g_pFormat->flags & AVFMT_NOFILE))
   439     if (!(g_pFormat->flags & AVFMT_NOFILE))
   430         avio_close(g_pContainer->pb);
   440         avio_close(g_pContainer->pb);
   431         
       
   432     // move file to destination
       
   433     rename(g_pContainer->filename, g_Filename);
       
   434 
   441 
   435     // free everything
   442     // free everything
   436     if (g_pVStream)
   443     if (g_pVStream)
   437     {
   444     {
   438         avcodec_close(g_pVideo);
   445         avcodec_close(g_pVideo);