Fixed avwrapper exit calls, fixing issue 752
authorGianfranco Costamagna <costamagnagianfranco@yahoo.it>
Fri, 03 Jan 2014 14:21:39 +0100
changeset 9925 113e61a8cadc
parent 9923 5071f5682733
child 9927 22bb4dfbfea8
Fixed avwrapper exit calls, fixing issue #752
hedgewars/avwrapper/avwrapper.c
hedgewars/uVideoRec.pas
--- a/hedgewars/avwrapper/avwrapper.c	Fri Jan 03 07:09:28 2014 -0800
+++ b/hedgewars/avwrapper/avwrapper.c	Fri Jan 03 14:21:39 2014 +0100
@@ -65,7 +65,7 @@
 // pointer to function from hwengine (uUtils.pas)
 static void (*AddFileLogRaw)(const char* pString);
 
-static void FatalError(const char* pFmt, ...)
+static int FatalError(const char* pFmt, ...)
 {
     char Buffer[1024];
     va_list VaArgs;
@@ -77,7 +77,7 @@
     AddFileLogRaw("Error in av-wrapper: ");
     AddFileLogRaw(Buffer);
     AddFileLogRaw("\n");
-    exit(1);
+    return(-1);
 }
 
 // Function to be called from libav for logging.
@@ -166,7 +166,7 @@
     }
 }
 
-// returns non-zero if there is more sound
+// returns non-zero if there is more sound, -1 in case of error
 static int WriteAudioFrame()
 {
     if (!g_pAStream)
@@ -189,7 +189,7 @@
     // when NumSamples == 0 we still need to call encode_audio2 to flush
     int got_packet;
     if (avcodec_encode_audio2(g_pAudio, &Packet, pFrame, &got_packet) != 0)
-        FatalError("avcodec_encode_audio2 failed");
+        return FatalError("avcodec_encode_audio2 failed");
     if (!got_packet)
         return 0;
 #else
@@ -210,12 +210,12 @@
     // Write the compressed frame to the media file.
     Packet.stream_index = g_pAStream->index;
     if (av_interleaved_write_frame(g_pContainer, &Packet) != 0)
-        FatalError("Error while writing audio frame");
+        return FatalError("Error while writing audio frame");
     return 1;
 }
 
 // add a video output stream
-static void AddVideoStream()
+static int AddVideoStream()
 {
 #if LIBAVFORMAT_VERSION_MAJOR >= 53
     g_pVStream = avformat_new_stream(g_pContainer, g_pVCodec);
@@ -223,7 +223,7 @@
     g_pVStream = av_new_stream(g_pContainer, 0);
 #endif
     if (!g_pVStream)
-        FatalError("Could not allocate video stream");
+        return FatalError("Could not allocate video stream");
 
     g_pVideo = g_pVStream->codec;
 
@@ -297,29 +297,35 @@
 #else
     if (avcodec_open(g_pVideo, g_pVCodec) < 0)
 #endif
-        FatalError("Could not open video codec %s", g_pVCodec->long_name);
+        return FatalError("Could not open video codec %s", g_pVCodec->long_name);
 
     g_pVFrame = avcodec_alloc_frame();
     if (!g_pVFrame)
-        FatalError("Could not allocate frame");
+        return FatalError("Could not allocate frame");
 
     g_pVFrame->linesize[0] = g_Width;
     g_pVFrame->linesize[1] = g_Width/2;
     g_pVFrame->linesize[2] = g_Width/2;
     g_pVFrame->linesize[3] = 0;
+    return 0;
 }
 
 static int WriteFrame(AVFrame* pFrame)
 {
     double AudioTime, VideoTime;
-
+    int ret;
     // write interleaved audio frame
     if (g_pAStream)
     {
         VideoTime = (double)g_pVStream->pts.val*g_pVStream->time_base.num/g_pVStream->time_base.den;
         do
+        {
             AudioTime = (double)g_pAStream->pts.val*g_pAStream->time_base.num/g_pAStream->time_base.den;
-        while (AudioTime < VideoTime && WriteAudioFrame());
+            ret = WriteAudioFrame();
+        }
+        while (AudioTime < VideoTime && ret);
+        if (ret < 0)
+            return ret;
     }
 
     if (!g_pVStream)
@@ -341,7 +347,7 @@
         Packet.size = sizeof(AVPicture);
 
         if (av_interleaved_write_frame(g_pContainer, &Packet) != 0)
-            FatalError("Error while writing video frame");
+            return FatalError("Error while writing video frame");
         return 0;
     }
     else
@@ -349,7 +355,7 @@
 #if LIBAVCODEC_VERSION_MAJOR >= 54
         int got_packet;
         if (avcodec_encode_video2(g_pVideo, &Packet, pFrame, &got_packet) < 0)
-            FatalError("avcodec_encode_video2 failed");
+            return FatalError("avcodec_encode_video2 failed");
         if (!got_packet)
             return 0;
 
@@ -360,7 +366,7 @@
 #else
         Packet.size = avcodec_encode_video(g_pVideo, g_OutBuffer, OUTBUFFER_SIZE, pFrame);
         if (Packet.size < 0)
-            FatalError("avcodec_encode_video failed");
+            return FatalError("avcodec_encode_video failed");
         if (Packet.size == 0)
             return 0;
 
@@ -373,21 +379,21 @@
         // write the compressed frame in the media file
         Packet.stream_index = g_pVStream->index;
         if (av_interleaved_write_frame(g_pContainer, &Packet) != 0)
-            FatalError("Error while writing video frame");
+            return FatalError("Error while writing video frame");
 
         return 1;
     }
 }
 
-AVWRAP_DECL void AVWrapper_WriteFrame(uint8_t* pY, uint8_t* pCb, uint8_t* pCr)
+AVWRAP_DECL int AVWrapper_WriteFrame(uint8_t* pY, uint8_t* pCb, uint8_t* pCr)
 {
     g_pVFrame->data[0] = pY;
     g_pVFrame->data[1] = pCb;
     g_pVFrame->data[2] = pCr;
-    WriteFrame(g_pVFrame);
+    return WriteFrame(g_pVFrame);
 }
 
-AVWRAP_DECL void AVWrapper_Init(
+AVWRAP_DECL int AVWrapper_Init(
          void (*pAddFileLogRaw)(const char*),
          const char* pFilename,
          const char* pDesc,
@@ -399,6 +405,7 @@
          int FramerateNum, int FramerateDen,
          int VQuality)
 {
+    int ret;
     AddFileLogRaw = pAddFileLogRaw;
     av_log_set_callback( &LogCallback );
 
@@ -414,12 +421,12 @@
     // find format
     g_pFormat = av_guess_format(pFormatName, NULL, NULL);
     if (!g_pFormat)
-        FatalError("Format \"%s\" was not found", pFormatName);
+        return FatalError("Format \"%s\" was not found", pFormatName);
 
     // allocate the output media context
     g_pContainer = avformat_alloc_context();
     if (!g_pContainer)
-        FatalError("Could not allocate output context");
+        return FatalError("Could not allocate output context");
 
     g_pContainer->oformat = g_pFormat;
 
@@ -442,7 +449,11 @@
     g_pAStream = NULL;
 
     if (g_pVCodec)
-        AddVideoStream();
+    {
+        ret = AddVideoStream();
+        if (ret < 0)
+            return ret;
+    }
     else
         Log("Video codec \"%s\" was not found; video will be ignored.\n", pVCodecName);
 
@@ -462,7 +473,7 @@
         Log("Audio codec \"%s\" was not found; audio will be ignored.\n", pACodecName);
 
     if (!g_pAStream && !g_pVStream)
-        FatalError("No video, no audio, aborting...");
+        return FatalError("No video, no audio, aborting...");
 
     // write format info to log
     av_dump_format(g_pContainer, 0, g_pContainer->filename, 1);
@@ -471,22 +482,36 @@
     if (!(g_pFormat->flags & AVFMT_NOFILE))
     {
         if (avio_open(&g_pContainer->pb, g_pContainer->filename, AVIO_FLAG_WRITE) < 0)
-            FatalError("Could not open output file (%s)", g_pContainer->filename);
+            return FatalError("Could not open output file (%s)", g_pContainer->filename);
     }
 
     // write the stream header, if any
     avformat_write_header(g_pContainer, NULL);
 
     g_pVFrame->pts = -1;
+    return 0;
 }
 
-AVWRAP_DECL void AVWrapper_Close()
+AVWRAP_DECL int AVWrapper_Close()
 {
+    int ret;
     // output buffered frames
     if (g_pVCodec->capabilities & CODEC_CAP_DELAY)
-        while( WriteFrame(NULL) );
+    {
+        do
+            ret = WriteFrame(NULL);
+        while (ret);
+        if (ret < 0)
+            return ret;
+    }
     // output any remaining audio
-    while( WriteAudioFrame() );
+    do
+    {
+        ret = WriteAudioFrame();
+    }
+    while(ret);
+    if (ret < 0)
+        return ret;
 
     // write the trailer, if any.
     av_write_trailer(g_pContainer);
@@ -514,4 +539,5 @@
     }
 
     av_free(g_pContainer);
+    return 0;
 }
--- a/hedgewars/uVideoRec.pas	Fri Jan 03 07:09:28 2014 -0800
+++ b/hedgewars/uVideoRec.pas	Fri Jan 03 14:21:39 2014 +0100
@@ -53,12 +53,12 @@
 type TAddFileLogRaw = procedure (s: pchar); cdecl;
 const AvwrapperLibName = 'libavwrapper';
 
-procedure AVWrapper_Init(
+function AVWrapper_Init(
               AddLog: TAddFileLogRaw;
               filename, desc, soundFile, format, vcodec, acodec: PChar;
-              width, height, framerateNum, framerateDen, vquality: LongInt); cdecl; external AvwrapperLibName;
-procedure AVWrapper_Close; cdecl; external AvwrapperLibName;
-procedure AVWrapper_WriteFrame( pY, pCb, pCr: PByte ); cdecl; external AvwrapperLibName;
+              width, height, framerateNum, framerateDen, vquality: LongInt): LongInt; cdecl; external AvwrapperLibName;
+function AVWrapper_Close: LongInt; cdecl; external AvwrapperLibName;
+function AVWrapper_WriteFrame( pY, pCb, pCr: PByte ): LongInt; cdecl; external AvwrapperLibName;
 
 type TFrame = record
                   realTicks: LongWord;
@@ -109,14 +109,15 @@
     filename:= UserPathPrefix + '/VideoTemp/' + RecPrefix;
     soundFilePath:= UserPathPrefix + '/VideoTemp/' + RecPrefix + '.sw';
 
-    AVWrapper_Init(@AddFileLogRaw
+    if AVWrapper_Init(@AddFileLogRaw
         , PChar(ansistring(filename))
         , PChar(ansistring(desc))
         , PChar(ansistring(soundFilePath))
         , PChar(ansistring(cAVFormat))
         , PChar(ansistring(cVideoCodec))
         , PChar(ansistring(cAudioCodec))
-        , cScreenWidth, cScreenHeight, cVideoFramerateNum, cVideoFramerateDen, cVideoQuality);
+        , cScreenWidth, cScreenHeight, cVideoFramerateNum, cVideoFramerateDen, cVideoQuality) < 0 then
+        halt(-1);
 
     numPixels:= cScreenWidth*cScreenHeight;
     YCbCr_Planes[0]:= GetMem(numPixels);
@@ -150,7 +151,8 @@
     FreeMem(YCbCr_Planes[2], numPixels div 4);
     FreeMem(RGB_Buffer, 4*numPixels);
     Close(cameraFile);
-    AVWrapper_Close();
+    if AVWrapper_Close() < 0 then
+        halt(-1);
     Erase(cameraFile);
     DeleteFile(soundFilePath);
     SendIPC(_S'v'); // inform frontend that we finished
@@ -185,7 +187,8 @@
             YCbCr_Planes[2][y*(cScreenWidth div 2) + x]:= Byte(128 + (( 7196*r - 6026*g - 1170*b) shr 16));
         end;
 
-    AVWrapper_WriteFrame(YCbCr_Planes[0], YCbCr_Planes[1], YCbCr_Planes[2]);
+    if AVWrapper_WriteFrame(YCbCr_Planes[0], YCbCr_Planes[1], YCbCr_Planes[2]) < 0 then
+        halt(-1);
 
     // inform frontend that we have encoded new frame
     s[0]:= #3;