Added a log file to detail avi recording issues. Memory allocation cleanup fixes for libav.
This commit is contained in:
parent
74e3b81536
commit
591b21f4af
|
@ -23,6 +23,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -66,6 +67,8 @@ extern "C"
|
||||||
#include "Qt/ConsoleUtilities.h"
|
#include "Qt/ConsoleUtilities.h"
|
||||||
#include "Qt/fceuWrapper.h"
|
#include "Qt/fceuWrapper.h"
|
||||||
|
|
||||||
|
#define AV_LOG_FILE_NAME "fceuxAV.log"
|
||||||
|
|
||||||
static gwavi_t *gwavi = NULL;
|
static gwavi_t *gwavi = NULL;
|
||||||
static bool recordEnable = false;
|
static bool recordEnable = false;
|
||||||
static bool recordAudio = true;
|
static bool recordAudio = true;
|
||||||
|
@ -79,6 +82,7 @@ static uint32_t *rawVideoBuf = NULL;
|
||||||
static int16_t *rawAudioBuf = NULL;
|
static int16_t *rawAudioBuf = NULL;
|
||||||
static int videoFormat = AVI_RGB24;
|
static int videoFormat = AVI_RGB24;
|
||||||
static int audioSampleRate = 48000;
|
static int audioSampleRate = 48000;
|
||||||
|
static FILE *avLogFp = NULL;
|
||||||
//**************************************************************************************
|
//**************************************************************************************
|
||||||
|
|
||||||
static void convertRgb_32_to_24( const unsigned char *src, unsigned char *dest, int w, int h, int nPix, bool verticalFlip )
|
static void convertRgb_32_to_24( const unsigned char *src, unsigned char *dest, int w, int h, int nPix, bool verticalFlip )
|
||||||
|
@ -749,6 +753,8 @@ struct OutputStream
|
||||||
int64_t next_pts;
|
int64_t next_pts;
|
||||||
int bytesPerSample;
|
int bytesPerSample;
|
||||||
int frameSize;
|
int frameSize;
|
||||||
|
bool isAudio;
|
||||||
|
bool writeError;
|
||||||
std::string selEnc;
|
std::string selEnc;
|
||||||
|
|
||||||
OutputStream(void)
|
OutputStream(void)
|
||||||
|
@ -761,10 +767,19 @@ struct OutputStream
|
||||||
bytesPerSample = 0;
|
bytesPerSample = 0;
|
||||||
frameSize = 0;
|
frameSize = 0;
|
||||||
next_pts = 0;
|
next_pts = 0;
|
||||||
|
writeError = false;
|
||||||
|
isAudio = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void close(void)
|
void close(void)
|
||||||
{
|
{
|
||||||
|
if ( writeError )
|
||||||
|
{
|
||||||
|
char msg[512];
|
||||||
|
sprintf( msg, "%s Stream Write Errors Detected.\nOutput may be incomplete or corrupt.\nSee log file '%s' for details\n",
|
||||||
|
isAudio ? "Audio" : "Video", AV_LOG_FILE_NAME);
|
||||||
|
FCEUD_PrintError(msg);
|
||||||
|
}
|
||||||
if ( enc != NULL )
|
if ( enc != NULL )
|
||||||
{
|
{
|
||||||
avcodec_free_context(&enc); enc = NULL;
|
avcodec_free_context(&enc); enc = NULL;
|
||||||
|
@ -777,10 +792,15 @@ struct OutputStream
|
||||||
{
|
{
|
||||||
av_frame_free(&tmp_frame); tmp_frame = NULL;
|
av_frame_free(&tmp_frame); tmp_frame = NULL;
|
||||||
}
|
}
|
||||||
|
if ( sws_ctx != NULL )
|
||||||
|
{
|
||||||
|
sws_freeContext(sws_ctx); sws_ctx = NULL;
|
||||||
|
}
|
||||||
if ( swr_ctx != NULL )
|
if ( swr_ctx != NULL )
|
||||||
{
|
{
|
||||||
swr_free(&swr_ctx); swr_ctx = NULL;
|
swr_free(&swr_ctx); swr_ctx = NULL;
|
||||||
}
|
}
|
||||||
|
writeError = false;
|
||||||
bytesPerSample = 0;
|
bytesPerSample = 0;
|
||||||
next_pts = 0;
|
next_pts = 0;
|
||||||
}
|
}
|
||||||
|
@ -788,6 +808,22 @@ struct OutputStream
|
||||||
static OutputStream video_st;
|
static OutputStream video_st;
|
||||||
static OutputStream audio_st;
|
static OutputStream audio_st;
|
||||||
|
|
||||||
|
static void log_callback( void *avcl, int level, const char *fmt, va_list vl)
|
||||||
|
{
|
||||||
|
if ( avLogFp != NULL )
|
||||||
|
{
|
||||||
|
va_list vl2;
|
||||||
|
|
||||||
|
va_copy( vl2, vl );
|
||||||
|
|
||||||
|
vfprintf( avLogFp, fmt, vl2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
av_log_default_callback( avcl, level, fmt, vl );
|
||||||
|
|
||||||
|
//FCEUD_Message( stmp );
|
||||||
|
}
|
||||||
|
|
||||||
static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, int width, int height)
|
static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, int width, int height)
|
||||||
{
|
{
|
||||||
AVFrame *picture;
|
AVFrame *picture;
|
||||||
|
@ -834,16 +870,16 @@ static int initVideoStream( const char *codec_name, OutputStream *ost )
|
||||||
|
|
||||||
if (codec == NULL)
|
if (codec == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "codec not found\n");
|
fprintf( avLogFp, "Video codec not found: %s\n", codec_name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
printf("CODEC: %s\n", codec->name );
|
//printf("CODEC: %s\n", codec->name );
|
||||||
|
|
||||||
ost->st = avformat_new_stream(oc, NULL);
|
ost->st = avformat_new_stream(oc, NULL);
|
||||||
|
|
||||||
if (ost->st == NULL)
|
if (ost->st == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Could not alloc stream\n");
|
fprintf( avLogFp, "Error: Could not alloc video stream\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -851,12 +887,12 @@ static int initVideoStream( const char *codec_name, OutputStream *ost )
|
||||||
|
|
||||||
if (c == NULL)
|
if (c == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Could not alloc an encoding context\n");
|
fprintf( avLogFp, "Error: Could not alloc an video encoding context\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ost->enc = c;
|
ost->enc = c;
|
||||||
|
|
||||||
av_opt_show2( (void*)c, NULL, AV_OPT_FLAG_VIDEO_PARAM, 0 );
|
//av_opt_show2( (void*)c, NULL, AV_OPT_FLAG_VIDEO_PARAM, 0 );
|
||||||
|
|
||||||
/* Put sample parameters. */
|
/* Put sample parameters. */
|
||||||
c->bit_rate = 400000;
|
c->bit_rate = 400000;
|
||||||
|
@ -895,7 +931,7 @@ static int initVideoStream( const char *codec_name, OutputStream *ost )
|
||||||
int i=0, formatOk=0;
|
int i=0, formatOk=0;
|
||||||
while (codec->pix_fmts[i] != -1)
|
while (codec->pix_fmts[i] != -1)
|
||||||
{
|
{
|
||||||
printf("Codec PIX_FMT: %i\n", codec->pix_fmts[i]);
|
//printf("Codec PIX_FMT: %i\n", codec->pix_fmts[i]);
|
||||||
if ( codec->pix_fmts[i] == c->pix_fmt )
|
if ( codec->pix_fmts[i] == c->pix_fmt )
|
||||||
{
|
{
|
||||||
printf("CODEC Supports PIX_FMT:%i\n", c->pix_fmt );
|
printf("CODEC Supports PIX_FMT:%i\n", c->pix_fmt );
|
||||||
|
@ -933,7 +969,7 @@ static int initVideoStream( const char *codec_name, OutputStream *ost )
|
||||||
/* open the codec */
|
/* open the codec */
|
||||||
if (avcodec_open2(c, NULL, NULL) < 0)
|
if (avcodec_open2(c, NULL, NULL) < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "could not open codec\n");
|
fprintf( avLogFp, "Error: Could not open codec: %s\n", codec_name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -942,7 +978,7 @@ static int initVideoStream( const char *codec_name, OutputStream *ost )
|
||||||
|
|
||||||
if (!ost->frame)
|
if (!ost->frame)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Could not allocate picture\n");
|
fprintf( avLogFp, "Error: Could not allocate picture\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -953,7 +989,7 @@ static int initVideoStream( const char *codec_name, OutputStream *ost )
|
||||||
|
|
||||||
if (ost->tmp_frame == NULL)
|
if (ost->tmp_frame == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Could not allocate temporary picture\n");
|
fprintf( avLogFp, "Error: Could not allocate temporary picture\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -963,14 +999,22 @@ static int initVideoStream( const char *codec_name, OutputStream *ost )
|
||||||
c->pix_fmt,
|
c->pix_fmt,
|
||||||
SWS_BICUBIC, NULL, NULL, NULL);
|
SWS_BICUBIC, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
if ( ost->sws_ctx == NULL )
|
||||||
|
{
|
||||||
|
fprintf( avLogFp, "Error: Video sws_getContext Failed. Video conversion not possible\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* copy the stream parameters to the muxer */
|
/* copy the stream parameters to the muxer */
|
||||||
ret = avcodec_parameters_from_context(ost->st->codecpar, c);
|
ret = avcodec_parameters_from_context(ost->st->codecpar, c);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Could not copy the stream parameters\n");
|
fprintf( avLogFp, "Error: Video avcodec_parameters_from_context Failed. Could not copy the stream parameters\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
ost->writeError = false;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1008,12 +1052,14 @@ static int initAudioStream( const char *codec_name, OutputStream *ost )
|
||||||
const AVCodec *codec;
|
const AVCodec *codec;
|
||||||
AVCodecContext *c;
|
AVCodecContext *c;
|
||||||
|
|
||||||
|
ost->isAudio = true;
|
||||||
|
|
||||||
/* find the audio encoder */
|
/* find the audio encoder */
|
||||||
codec = avcodec_find_encoder_by_name(codec_name);
|
codec = avcodec_find_encoder_by_name(codec_name);
|
||||||
|
|
||||||
if (codec == NULL)
|
if (codec == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "codec not found: '%s'\n", codec_name);
|
fprintf( avLogFp, "Audio codec not found: '%s'\n", codec_name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1021,7 +1067,7 @@ static int initAudioStream( const char *codec_name, OutputStream *ost )
|
||||||
|
|
||||||
if (ost->st == NULL)
|
if (ost->st == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Could not alloc stream\n");
|
fprintf( avLogFp, "Could not alloc audio stream\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1029,7 +1075,7 @@ static int initAudioStream( const char *codec_name, OutputStream *ost )
|
||||||
|
|
||||||
if (c == NULL)
|
if (c == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Could not alloc an encoding context\n");
|
fprintf( avLogFp, "Could not alloc an audio encoding context\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ost->enc = c;
|
ost->enc = c;
|
||||||
|
@ -1056,7 +1102,7 @@ static int initAudioStream( const char *codec_name, OutputStream *ost )
|
||||||
ost->swr_ctx = swr_alloc();
|
ost->swr_ctx = swr_alloc();
|
||||||
if (!ost->swr_ctx)
|
if (!ost->swr_ctx)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error allocating the resampling context\n");
|
fprintf( avLogFp, "Error allocating the audio resampling context\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
av_opt_set_sample_fmt(ost->swr_ctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
|
av_opt_set_sample_fmt(ost->swr_ctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
|
||||||
|
@ -1069,14 +1115,14 @@ static int initAudioStream( const char *codec_name, OutputStream *ost )
|
||||||
ret = swr_init(ost->swr_ctx);
|
ret = swr_init(ost->swr_ctx);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error opening the resampling context\n");
|
fprintf( avLogFp, "Error: Could not init the audio resampling context\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* open it */
|
/* open it */
|
||||||
if (avcodec_open2(c, NULL, NULL) < 0)
|
if (avcodec_open2(c, NULL, NULL) < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "could not open codec\n");
|
fprintf( avLogFp, "Error: Could not open codec: %s\n", codec_name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1096,17 +1142,18 @@ static int initAudioStream( const char *codec_name, OutputStream *ost )
|
||||||
ost->tmp_frame = alloc_audio_frame(c->sample_fmt, c->channel_layout, c->sample_rate, nb_samples);
|
ost->tmp_frame = alloc_audio_frame(c->sample_fmt, c->channel_layout, c->sample_rate, nb_samples);
|
||||||
//ost->tmp_frame = alloc_audio_frame(AV_SAMPLE_FMT_S16, AV_CH_LAYOUT_MONO, audioSampleRate, nb_samples);
|
//ost->tmp_frame = alloc_audio_frame(AV_SAMPLE_FMT_S16, AV_CH_LAYOUT_MONO, audioSampleRate, nb_samples);
|
||||||
|
|
||||||
printf("Audio: FMT:%i ChanLayout:%li Rate:%i FrameSize:%i bytesPerSample:%i \n",
|
//printf("Audio: FMT:%i ChanLayout:%li Rate:%i FrameSize:%i bytesPerSample:%i \n",
|
||||||
c->sample_fmt, c->channel_layout, c->sample_rate, nb_samples, ost->bytesPerSample );
|
// c->sample_fmt, c->channel_layout, c->sample_rate, nb_samples, ost->bytesPerSample );
|
||||||
|
|
||||||
/* copy the stream parameters to the muxer */
|
/* copy the stream parameters to the muxer */
|
||||||
ret = avcodec_parameters_from_context(ost->st->codecpar, c);
|
ret = avcodec_parameters_from_context(ost->st->codecpar, c);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Could not copy the stream parameters\n");
|
fprintf( avLogFp, "Error: Audio avcodec_parameters_from_context Failed. Could not copy the stream parameters\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ost->frame->nb_samples = 0;
|
ost->frame->nb_samples = 0;
|
||||||
|
ost->writeError = false;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1207,6 +1254,8 @@ static int initMedia( const char *filename )
|
||||||
/* Initialize libavcodec, and register all codecs and formats. */
|
/* Initialize libavcodec, and register all codecs and formats. */
|
||||||
//av_register_all();
|
//av_register_all();
|
||||||
|
|
||||||
|
av_log_set_callback( log_callback );
|
||||||
|
|
||||||
print_Codecs();
|
print_Codecs();
|
||||||
|
|
||||||
/* Autodetect the output format from the name. default is MPEG. */
|
/* Autodetect the output format from the name. default is MPEG. */
|
||||||
|
@ -1214,21 +1263,21 @@ static int initMedia( const char *filename )
|
||||||
|
|
||||||
if (fmt == NULL)
|
if (fmt == NULL)
|
||||||
{
|
{
|
||||||
printf("Could not deduce output format from file extension: using AVI.\n");
|
fprintf( avLogFp, "Could not deduce output format from file extension: using AVI.\n");
|
||||||
fmt = av_guess_format("avi", NULL, NULL);
|
fmt = av_guess_format("avi", NULL, NULL);
|
||||||
}
|
}
|
||||||
if (fmt == NULL)
|
if (fmt == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Could not find suitable output format\n");
|
fprintf( avLogFp, "Error: Could not find suitable output format\n");
|
||||||
return -1;
|
goto LIBAV_INIT_MEDIA_ERROR_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate the output media context. */
|
/* Allocate the output media context. */
|
||||||
oc = avformat_alloc_context();
|
oc = avformat_alloc_context();
|
||||||
if (oc == NULL)
|
if (oc == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Memory error\n");
|
fprintf( avLogFp, "Memory error: avformat_alloc_context failed\n");
|
||||||
return -1;
|
goto LIBAV_INIT_MEDIA_ERROR_EXIT;
|
||||||
}
|
}
|
||||||
oc->oformat = fmt;
|
oc->oformat = fmt;
|
||||||
|
|
||||||
|
@ -1236,13 +1285,13 @@ static int initMedia( const char *filename )
|
||||||
|
|
||||||
if ( initVideoStream( video_st.selEnc.c_str(), &video_st ) )
|
if ( initVideoStream( video_st.selEnc.c_str(), &video_st ) )
|
||||||
{
|
{
|
||||||
printf("Video Stream Init Failed\n");
|
fprintf( avLogFp, "Video Stream Init Failed\n");
|
||||||
return -1;
|
goto LIBAV_INIT_MEDIA_ERROR_EXIT;
|
||||||
}
|
}
|
||||||
if ( initAudioStream( audio_st.selEnc.c_str(), &audio_st ) )
|
if ( initAudioStream( audio_st.selEnc.c_str(), &audio_st ) )
|
||||||
{
|
{
|
||||||
printf("Audio Stream Init Failed\n");
|
fprintf( avLogFp, "Audio Stream Init Failed\n");
|
||||||
return -1;
|
goto LIBAV_INIT_MEDIA_ERROR_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
av_dump_format(oc, 0, filename, 1);
|
av_dump_format(oc, 0, filename, 1);
|
||||||
|
@ -1252,23 +1301,39 @@ static int initMedia( const char *filename )
|
||||||
{
|
{
|
||||||
if (avio_open( &oc->pb, filename, AVIO_FLAG_WRITE) < 0)
|
if (avio_open( &oc->pb, filename, AVIO_FLAG_WRITE) < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Could not open '%s'\n", filename);
|
fprintf( avLogFp, "Error: Could not open file: '%s'\n", filename);
|
||||||
return -1;
|
goto LIBAV_INIT_MEDIA_ERROR_EXIT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("Opened: %s\n", filename);
|
fprintf( avLogFp, "Opened file for writing: %s\n", filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the stream header, if any. */
|
/* Write the stream header, if any. */
|
||||||
if ( avformat_write_header(oc, NULL) )
|
if ( avformat_write_header(oc, NULL) )
|
||||||
{
|
{
|
||||||
printf("Error: Failed to write avformat header\n");
|
fprintf( avLogFp, "Error: avformat_write_header Failed: Could not write avformat header\n");
|
||||||
return -1;
|
goto LIBAV_INIT_MEDIA_ERROR_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
LIBAV_INIT_MEDIA_ERROR_EXIT:
|
||||||
|
|
||||||
|
video_st.close();
|
||||||
|
audio_st.close();
|
||||||
|
|
||||||
|
/* Close the output file. */
|
||||||
|
|
||||||
|
/* free the stream */
|
||||||
|
if ( oc )
|
||||||
|
{
|
||||||
|
avio_close(oc->pb);
|
||||||
|
|
||||||
|
avformat_free_context(oc); oc = NULL;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int init( int width, int height )
|
static int init( int width, int height )
|
||||||
|
@ -1281,6 +1346,10 @@ static int write_audio_frame( AVFrame *frame )
|
||||||
int ret;
|
int ret;
|
||||||
OutputStream *ost = &audio_st;
|
OutputStream *ost = &audio_st;
|
||||||
|
|
||||||
|
if ( ost->writeError )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if ( frame )
|
if ( frame )
|
||||||
{
|
{
|
||||||
frame->pts = ost->next_pts;
|
frame->pts = ost->next_pts;
|
||||||
|
@ -1292,7 +1361,8 @@ static int write_audio_frame( AVFrame *frame )
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error submitting a frame for encoding\n");
|
fprintf( avLogFp, "Error submitting audio frame for encoding\n");
|
||||||
|
ost->writeError = true;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
while (ret >= 0)
|
while (ret >= 0)
|
||||||
|
@ -1302,7 +1372,8 @@ static int write_audio_frame( AVFrame *frame )
|
||||||
ret = avcodec_receive_packet(ost->enc, &pkt);
|
ret = avcodec_receive_packet(ost->enc, &pkt);
|
||||||
if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
|
if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error encoding a video frame\n");
|
fprintf( avLogFp, "Error encoding audio frame\n");
|
||||||
|
ost->writeError = true;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else if (ret >= 0)
|
else if (ret >= 0)
|
||||||
|
@ -1313,7 +1384,8 @@ static int write_audio_frame( AVFrame *frame )
|
||||||
ret = av_interleaved_write_frame(oc, &pkt);
|
ret = av_interleaved_write_frame(oc, &pkt);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error while writing video frame\n");
|
fprintf( avLogFp, "Error while writing audio frame\n");
|
||||||
|
ost->writeError = true;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1326,6 +1398,11 @@ static int encode_audio_frame( int16_t *audioOut, int numSamples)
|
||||||
int i,ret;
|
int i,ret;
|
||||||
OutputStream *ost = &audio_st;
|
OutputStream *ost = &audio_st;
|
||||||
const uint8_t *inData[AV_NUM_DATA_POINTERS];
|
const uint8_t *inData[AV_NUM_DATA_POINTERS];
|
||||||
|
|
||||||
|
if ( ost->writeError )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
for (i=0; i<AV_NUM_DATA_POINTERS; i++)
|
for (i=0; i<AV_NUM_DATA_POINTERS; i++)
|
||||||
{
|
{
|
||||||
|
@ -1439,6 +1516,10 @@ static int encode_video_frame( unsigned char *inBuf )
|
||||||
AVCodecContext *c = video_st.enc;
|
AVCodecContext *c = video_st.enc;
|
||||||
unsigned char *outBuf;
|
unsigned char *outBuf;
|
||||||
|
|
||||||
|
if ( ost->writeError )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
ret = av_frame_make_writable( video_st.frame );
|
ret = av_frame_make_writable( video_st.frame );
|
||||||
|
|
||||||
if ( ret < 0 )
|
if ( ret < 0 )
|
||||||
|
@ -1469,7 +1550,8 @@ static int encode_video_frame( unsigned char *inBuf )
|
||||||
ret = avcodec_send_frame(c, video_st.frame);
|
ret = avcodec_send_frame(c, video_st.frame);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error submitting a frame for encoding\n");
|
fprintf( avLogFp, "Error submitting a video frame for encoding\n");
|
||||||
|
ost->writeError = true;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1483,7 +1565,8 @@ static int encode_video_frame( unsigned char *inBuf )
|
||||||
|
|
||||||
if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
|
if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error encoding a video frame\n");
|
fprintf( avLogFp, "Error encoding a video frame\n");
|
||||||
|
ost->writeError = true;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else if (ret >= 0)
|
else if (ret >= 0)
|
||||||
|
@ -1494,7 +1577,8 @@ static int encode_video_frame( unsigned char *inBuf )
|
||||||
ret = av_interleaved_write_frame(oc, &pkt);
|
ret = av_interleaved_write_frame(oc, &pkt);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error while writing video frame\n");
|
fprintf( avLogFp, "Error while writing video frame\n");
|
||||||
|
ost->writeError = true;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1530,6 +1614,40 @@ static int close(void)
|
||||||
} // End namespace LIBAV
|
} // End namespace LIBAV
|
||||||
#endif
|
#endif
|
||||||
//**************************************************************************************
|
//**************************************************************************************
|
||||||
|
int aviRecordLogClose(void)
|
||||||
|
{
|
||||||
|
if ( avLogFp != NULL )
|
||||||
|
{
|
||||||
|
if ( avLogFp != stdout )
|
||||||
|
{
|
||||||
|
fclose(avLogFp);
|
||||||
|
}
|
||||||
|
avLogFp = NULL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//**************************************************************************************
|
||||||
|
int aviRecordLogOpen(void)
|
||||||
|
{
|
||||||
|
if ( avLogFp != NULL )
|
||||||
|
{
|
||||||
|
aviRecordLogClose();
|
||||||
|
}
|
||||||
|
if ( avLogFp == NULL )
|
||||||
|
{
|
||||||
|
avLogFp = fopen( AV_LOG_FILE_NAME, "w");
|
||||||
|
|
||||||
|
if ( avLogFp == NULL )
|
||||||
|
{
|
||||||
|
char msg[512];
|
||||||
|
sprintf( msg, "Error: Failed to open AV Recording log file for writing: %s\n", AV_LOG_FILE_NAME);
|
||||||
|
FCEUD_PrintError(msg);
|
||||||
|
avLogFp = stdout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return avLogFp == NULL;
|
||||||
|
}
|
||||||
|
//**************************************************************************************
|
||||||
int aviRecordOpenFile( const char *filepath )
|
int aviRecordOpenFile( const char *filepath )
|
||||||
{
|
{
|
||||||
char fourcc[8];
|
char fourcc[8];
|
||||||
|
@ -1537,6 +1655,12 @@ int aviRecordOpenFile( const char *filepath )
|
||||||
double fps;
|
double fps;
|
||||||
char fileName[1024];
|
char fileName[1024];
|
||||||
|
|
||||||
|
if ( aviRecordLogOpen() )
|
||||||
|
{
|
||||||
|
// Log Error
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if ( filepath != NULL )
|
if ( filepath != NULL )
|
||||||
{
|
{
|
||||||
strcpy( fileName, filepath );
|
strcpy( fileName, filepath );
|
||||||
|
@ -1643,7 +1767,7 @@ int aviRecordOpenFile( const char *filepath )
|
||||||
{
|
{
|
||||||
fourcc[i] = toupper(fourcc[i]);
|
fourcc[i] = toupper(fourcc[i]);
|
||||||
}
|
}
|
||||||
printf("Set VFW FourCC: %s\n", fourcc);
|
//printf("Set VFW FourCC: %s\n", fourcc);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1652,8 +1776,11 @@ int aviRecordOpenFile( const char *filepath )
|
||||||
{
|
{
|
||||||
if ( LIBAV::initMedia( fileName ) )
|
if ( LIBAV::initMedia( fileName ) )
|
||||||
{
|
{
|
||||||
printf("Error: Failed to open AVI file.\n");
|
char msg[512];
|
||||||
|
fprintf( avLogFp, "Error: Failed to open AVI file.\n");
|
||||||
recordEnable = false;
|
recordEnable = false;
|
||||||
|
sprintf( msg, "Error: AV Recording Initialization Failed.\nSee %s for details...\n", AV_LOG_FILE_NAME);
|
||||||
|
FCEUD_PrintError(msg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1664,8 +1791,11 @@ int aviRecordOpenFile( const char *filepath )
|
||||||
|
|
||||||
if ( gwavi->open( fileName, nes_shm->video.ncol, nes_shm->video.nrow, fourcc, fps, &audioConfig ) )
|
if ( gwavi->open( fileName, nes_shm->video.ncol, nes_shm->video.nrow, fourcc, fps, &audioConfig ) )
|
||||||
{
|
{
|
||||||
printf("Error: Failed to open AVI file.\n");
|
char msg[512];
|
||||||
|
fprintf( avLogFp, "Error: Failed to open AVI file.\n");
|
||||||
recordEnable = false;
|
recordEnable = false;
|
||||||
|
sprintf( msg, "Error: AV Recording Initialization Failed.\nSee %s for details...\n", AV_LOG_FILE_NAME);
|
||||||
|
FCEUD_PrintError(msg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1917,7 +2047,7 @@ void AviRecordDiskThread_t::run(void)
|
||||||
char writeAudio = 1;
|
char writeAudio = 1;
|
||||||
int avgAudioPerFrame, localVideoFormat;
|
int avgAudioPerFrame, localVideoFormat;
|
||||||
|
|
||||||
printf("AVI Record Disk Start\n");
|
fprintf( avLogFp, "AVI Record Disk Thread Start\n");
|
||||||
|
|
||||||
setPriority( QThread::HighestPriority );
|
setPriority( QThread::HighestPriority );
|
||||||
|
|
||||||
|
@ -1925,7 +2055,7 @@ void AviRecordDiskThread_t::run(void)
|
||||||
|
|
||||||
avgAudioPerFrame = ( audioSampleRate / fps) + 1;
|
avgAudioPerFrame = ( audioSampleRate / fps) + 1;
|
||||||
|
|
||||||
printf("Avg Audio Rate per Frame: %i \n", avgAudioPerFrame );
|
fprintf( avLogFp, "Avg Audio Sample Rate per Frame: %i \n", avgAudioPerFrame );
|
||||||
|
|
||||||
width = nes_shm->video.ncol;
|
width = nes_shm->video.ncol;
|
||||||
height = nes_shm->video.nrow;
|
height = nes_shm->video.nrow;
|
||||||
|
@ -2105,8 +2235,17 @@ void AviRecordDiskThread_t::run(void)
|
||||||
free(audioOut);
|
free(audioOut);
|
||||||
free(videoOut);
|
free(videoOut);
|
||||||
|
|
||||||
printf("AVI Record Disk Exit\n");
|
fprintf( avLogFp, "AVI Record Disk Thread Exit\n");
|
||||||
emit finished();
|
emit finished();
|
||||||
|
|
||||||
|
if ( avLogFp != NULL )
|
||||||
|
{
|
||||||
|
if ( avLogFp != stdout )
|
||||||
|
{
|
||||||
|
fclose(avLogFp);
|
||||||
|
}
|
||||||
|
avLogFp = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
//**************************************************************************************
|
//**************************************************************************************
|
||||||
|
|
|
@ -3641,8 +3641,10 @@ void consoleWin_t::aviRecordStart(void)
|
||||||
if ( !aviRecordRunning() )
|
if ( !aviRecordRunning() )
|
||||||
{
|
{
|
||||||
fceuWrapperLock();
|
fceuWrapperLock();
|
||||||
aviRecordOpenFile(NULL);
|
if ( aviRecordOpenFile(NULL) == 0 )
|
||||||
aviDiskThread->start();
|
{
|
||||||
|
aviDiskThread->start();
|
||||||
|
}
|
||||||
fceuWrapperUnLock();
|
fceuWrapperUnLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3719,8 +3721,10 @@ void consoleWin_t::aviRecordAsStart(void)
|
||||||
FCEUI_printf ("AVI Recording movie to %s\n", filename.toStdString().c_str() );
|
FCEUI_printf ("AVI Recording movie to %s\n", filename.toStdString().c_str() );
|
||||||
|
|
||||||
fceuWrapperLock();
|
fceuWrapperLock();
|
||||||
aviRecordOpenFile( filename.toStdString().c_str() );
|
if ( aviRecordOpenFile( filename.toStdString().c_str() ) == 0 )
|
||||||
aviDiskThread->start();
|
{
|
||||||
|
aviDiskThread->start();
|
||||||
|
}
|
||||||
fceuWrapperUnLock();
|
fceuWrapperUnLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue