From daee5b4450635b4045133b25b1b241d8b03d1e44 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 11 Aug 2017 12:03:37 -0400 Subject: [PATCH] experiment with no ffmpeg thread --- src/zm_config.cpp | 2 + src/zm_ffmpeg_camera.cpp | 53 ++++++++---- src/zm_logger.cpp | 183 +++++++++++++++++++++------------------ src/zm_monitor.cpp | 101 ++++++++++++--------- src/zm_videostore.cpp | 42 +++++---- 5 files changed, 222 insertions(+), 159 deletions(-) diff --git a/src/zm_config.cpp b/src/zm_config.cpp index 03f7b587a..945838567 100644 --- a/src/zm_config.cpp +++ b/src/zm_config.cpp @@ -288,8 +288,10 @@ Config::~Config() { if ( items ) { for ( int i = 0; i < n_items; i++ ) { delete items[i]; + items[i] = NULL; } delete[] items; + items = NULL; } } diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index 12d3f4d19..c1884a9f4 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -115,13 +115,20 @@ int FfmpegCamera::PrimeCapture() { mAudioStreamId = -1; Info( "Priming capture from %s", mPath.c_str() ); +#if THREAD if ( OpenFfmpeg() != 0 ) { ReopenFfmpeg(); } return 0; +#else + return OpenFfmpeg(); +#endif } int FfmpegCamera::PreCapture() { + // If Reopen was called, then ffmpeg is closed and we need to reopen it. + if ( ! mCanCapture ) + return OpenFfmpeg(); // Nothing to do here return( 0 ); } @@ -283,14 +290,18 @@ int FfmpegCamera::OpenFfmpeg() { } if ( ret < 0 ) { - Warning("Could not set rtsp_transport method '%s'\n", Method().c_str()); + Warning("Could not set rtsp_transport method '%s'\n", method.c_str()); } - Debug ( 1, "Calling avformat_open_input" ); + Debug ( 1, "Calling avformat_open_input for %s", mPath.c_str() ); mFormatContext = avformat_alloc_context( ); - mFormatContext->interrupt_callback.callback = FfmpegInterruptCallback; - mFormatContext->interrupt_callback.opaque = this; + //mFormatContext->interrupt_callback.callback = FfmpegInterruptCallback; + //mFormatContext->interrupt_callback.opaque = this; + // Speed up find_stream_info + //FIXME can speed up initial analysis but need sensible parameters... + //mFormatContext->probesize = 32; + //mFormatContext->max_analyze_duration = 32; if ( avformat_open_input( &mFormatContext, mPath.c_str(), NULL, &opts ) != 0 ) #endif @@ -310,10 +321,6 @@ int FfmpegCamera::OpenFfmpeg() { Info( "Stream open %s", mPath.c_str() ); - //FIXME can speed up initial analysis but need sensible parameters... - //mFormatContext->probesize = 32; - //mFormatContext->max_analyze_duration = 32; - // Locate stream info from avformat_open_input #if !LIBAVFORMAT_VERSION_CHECK(53, 6, 0, 6, 0) Debug ( 1, "Calling av_find_stream_info" ); if ( av_find_stream_info( mFormatContext ) < 0 ) @@ -484,11 +491,17 @@ int FfmpegCamera::ReopenFfmpeg() { Debug(2, "ReopenFfmpeg called."); +#if THREAD mCanCapture = false; - if (pthread_create( &mReopenThread, NULL, ReopenFfmpegThreadCallback, (void*) this) != 0){ + if ( pthread_create( &mReopenThread, NULL, ReopenFfmpegThreadCallback, (void*) this) != 0 ) { // Log a fatal error and exit the process. Fatal( "ReopenFfmpeg failed to create worker thread." ); } +#else + CloseFfmpeg(); + OpenFfmpeg(); + +#endif return 0; } @@ -499,8 +512,14 @@ int FfmpegCamera::CloseFfmpeg() { mCanCapture = false; - av_frame_free( &mFrame ); - av_frame_free( &mRawFrame ); + if ( mFrame ) { + av_frame_free( &mFrame ); + mFrame = NULL; + } + if ( mRawFrame ) { + av_frame_free( &mRawFrame ); + mRawFrame = NULL; + } #if HAVE_LIBSWSCALE if ( mConvertContext ) { @@ -511,12 +530,12 @@ int FfmpegCamera::CloseFfmpeg() { if ( mVideoCodecContext ) { avcodec_close(mVideoCodecContext); - av_free(mVideoCodecContext); + //av_free(mVideoCodecContext); mVideoCodecContext = NULL; // Freed by av_close_input_file } if ( mAudioCodecContext ) { avcodec_close(mAudioCodecContext); - av_free(mAudioCodecContext); + //av_free(mAudioCodecContext); mAudioCodecContext = NULL; // Freed by av_close_input_file } @@ -533,11 +552,12 @@ int FfmpegCamera::CloseFfmpeg() { } int FfmpegCamera::FfmpegInterruptCallback(void *ctx) { + Debug(3,"FfmpegInteruptCallback"); FfmpegCamera* camera = reinterpret_cast(ctx); if ( camera->mIsOpening ) { int now = time(NULL); if ( (now - camera->mOpenStart) > config.ffmpeg_open_timeout ) { - Error ( "Open video took more than %d seconds.", config.ffmpeg_open_timeout ); + Error( "Open video took more than %d seconds.", config.ffmpeg_open_timeout ); return 1; } } @@ -546,11 +566,12 @@ int FfmpegCamera::FfmpegInterruptCallback(void *ctx) { } void *FfmpegCamera::ReopenFfmpegThreadCallback(void *ctx){ - if (ctx == NULL) return NULL; + Debug(3,"FfmpegReopenThreadtCallback"); + if ( ctx == NULL ) return NULL; FfmpegCamera* camera = reinterpret_cast(ctx); - while (1){ + while (1) { // Close current stream. camera->CloseFfmpeg(); diff --git a/src/zm_logger.cpp b/src/zm_logger.cpp index 4a4756f4c..909aeed5e 100644 --- a/src/zm_logger.cpp +++ b/src/zm_logger.cpp @@ -112,9 +112,16 @@ Logger::Logger() : Logger::~Logger() { terminate(); + smCodes.clear(); + smSyslogPriorities.clear(); +#if 0 for ( StringMap::iterator itr = smCodes.begin(); itr != smCodes.end(); itr ++ ) { smCodes.erase( itr ); } + for ( IntMap::iterator itr = smSyslogPriorities.begin(); itr != smSyslogPriorities.end(); itr ++ ) { + smSyslogPriorities.erase(itr); + } +#endif } void Logger::initialise( const std::string &id, const Options &options ) { @@ -417,124 +424,128 @@ void Logger::closeSyslog() { } void Logger::logPrint( bool hex, const char * const filepath, const int line, const int level, const char *fstring, ... ) { - if ( level <= mEffectiveLevel ) { - char timeString[64]; - char logString[8192]; - va_list argPtr; - struct timeval timeVal; + if ( level > mEffectiveLevel ) + return; + char timeString[64]; + char logString[8192]; + va_list argPtr; + struct timeval timeVal; - char *filecopy = strdup(filepath); - const char * const file = basename(filecopy); - const char *classString = smCodes[level].c_str(); + char *filecopy = strdup(filepath); + const char * const file = basename(filecopy); + const char *classString = smCodes[level].c_str(); - if ( level < PANIC || level > DEBUG9 ) - Panic( "Invalid logger level %d", level ); + if ( level < PANIC || level > DEBUG9 ) + Panic( "Invalid logger level %d", level ); - gettimeofday( &timeVal, NULL ); + gettimeofday( &timeVal, NULL ); #if 0 - if ( logRuntime ) { - static struct timeval logStart; + if ( logRuntime ) { + static struct timeval logStart; - subtractTime( &timeVal, &logStart ); + subtractTime( &timeVal, &logStart ); - snprintf( timeString, sizeof(timeString), "%ld.%03ld", timeVal.tv_sec, timeVal.tv_usec/1000 ); - } else { + snprintf( timeString, sizeof(timeString), "%ld.%03ld", timeVal.tv_sec, timeVal.tv_usec/1000 ); + } else { #endif - char *timePtr = timeString; - timePtr += strftime( timePtr, sizeof(timeString), "%x %H:%M:%S", localtime(&timeVal.tv_sec) ); - snprintf( timePtr, sizeof(timeString)-(timePtr-timeString), ".%06ld", timeVal.tv_usec ); + char *timePtr = timeString; + timePtr += strftime( timePtr, sizeof(timeString), "%x %H:%M:%S", localtime(&timeVal.tv_sec) ); + snprintf( timePtr, sizeof(timeString)-(timePtr-timeString), ".%06ld", timeVal.tv_usec ); #if 0 - } + } #endif - pid_t tid; + pid_t tid; #ifdef __FreeBSD__ - long lwpid; - thr_self(&lwpid); - tid = lwpid; + long lwpid; + thr_self(&lwpid); + tid = lwpid; - if (tid < 0 ) // Thread/Process id + if (tid < 0 ) // Thread/Process id #else #ifdef HAVE_SYSCALL #ifdef __FreeBSD_kernel__ - if ( (syscall(SYS_thr_self, &tid)) < 0 ) // Thread/Process id + if ( (syscall(SYS_thr_self, &tid)) < 0 ) // Thread/Process id # else - // SOLARIS doesn't have SYS_gettid; don't assume + // SOLARIS doesn't have SYS_gettid; don't assume #ifdef SYS_gettid - if ( (tid = syscall(SYS_gettid)) < 0 ) // Thread/Process id + if ( (tid = syscall(SYS_gettid)) < 0 ) // Thread/Process id #endif // SYS_gettid #endif #endif // HAVE_SYSCALL #endif - tid = getpid(); // Process id + tid = getpid(); // Process id - char *logPtr = logString; - logPtr += snprintf( logPtr, sizeof(logString), "%s %s[%d].%s-%s/%d [", - timeString, - mId.c_str(), - tid, - classString, - file, - line - ); - char *syslogStart = logPtr; + char *logPtr = logString; + logPtr += snprintf( logPtr, sizeof(logString), "%s %s[%d].%s-%s/%d [", + timeString, + mId.c_str(), + tid, + classString, + file, + line + ); + char *syslogStart = logPtr; - va_start( argPtr, fstring ); - if ( hex ) { - unsigned char *data = va_arg( argPtr, unsigned char * ); - int len = va_arg( argPtr, int ); - int i; - logPtr += snprintf( logPtr, sizeof(logString)-(logPtr-logString), "%d:", len ); - for ( i = 0; i < len; i++ ) { - logPtr += snprintf( logPtr, sizeof(logString)-(logPtr-logString), " %02x", data[i] ); - } - } else { - logPtr += vsnprintf( logPtr, sizeof(logString)-(logPtr-logString), fstring, argPtr ); + va_start( argPtr, fstring ); + if ( hex ) { + unsigned char *data = va_arg( argPtr, unsigned char * ); + int len = va_arg( argPtr, int ); + int i; + logPtr += snprintf( logPtr, sizeof(logString)-(logPtr-logString), "%d:", len ); + for ( i = 0; i < len; i++ ) { + logPtr += snprintf( logPtr, sizeof(logString)-(logPtr-logString), " %02x", data[i] ); } - va_end(argPtr); - char *syslogEnd = logPtr; - strncpy( logPtr, "]\n", sizeof(logString)-(logPtr-logString) ); + } else { + logPtr += vsnprintf( logPtr, sizeof(logString)-(logPtr-logString), fstring, argPtr ); + } + va_end(argPtr); + char *syslogEnd = logPtr; + strncpy( logPtr, "]\n", sizeof(logString)-(logPtr-logString) ); - if ( level <= mTermLevel ) { - printf( "%s", logString ); - fflush( stdout ); - } - if ( level <= mFileLevel ) { - fprintf( mLogFileFP, "%s", logString ); + if ( level <= mTermLevel ) { + puts( logString ); + fflush( stdout ); + } + if ( level <= mFileLevel ) { + if ( mLogFileFP ) { + fputs( logString, mLogFileFP ); if ( mFlush ) fflush( mLogFileFP ); + } else { + puts("Logging to file, but file not open\n"); } - *syslogEnd = '\0'; - if ( level <= mDatabaseLevel ) { - char sql[ZM_SQL_MED_BUFSIZ]; - char escapedString[(strlen(syslogStart)*2)+1]; + } + *syslogEnd = '\0'; + if ( level <= mDatabaseLevel ) { + char sql[ZM_SQL_MED_BUFSIZ]; + char escapedString[(strlen(syslogStart)*2)+1]; - mysql_real_escape_string( &dbconn, escapedString, syslogStart, strlen(syslogStart) ); + mysql_real_escape_string( &dbconn, escapedString, syslogStart, strlen(syslogStart) ); - snprintf( sql, sizeof(sql), "insert into Logs ( TimeKey, Component, ServerId, Pid, Level, Code, Message, File, Line ) values ( %ld.%06ld, '%s', %d, %d, %d, '%s', '%s', '%s', %d )", timeVal.tv_sec, timeVal.tv_usec, mId.c_str(), staticConfig.SERVER_ID, tid, level, classString, escapedString, file, line ); - if ( mysql_query( &dbconn, sql ) ) { - Level tempDatabaseLevel = mDatabaseLevel; - databaseLevel( NOLOG ); - Error( "Can't insert log entry: sql(%s) error(%s)", sql, mysql_error( &dbconn ) ); - databaseLevel(tempDatabaseLevel); - } - } - if ( level <= mSyslogLevel ) { - int priority = smSyslogPriorities[level]; - //priority |= LOG_DAEMON; - syslog( priority, "%s [%s] [%s]", classString, mId.c_str(), syslogStart ); + snprintf( sql, sizeof(sql), "insert into Logs ( TimeKey, Component, ServerId, Pid, Level, Code, Message, File, Line ) values ( %ld.%06ld, '%s', %d, %d, %d, '%s', '%s', '%s', %d )", timeVal.tv_sec, timeVal.tv_usec, mId.c_str(), staticConfig.SERVER_ID, tid, level, classString, escapedString, file, line ); + if ( mysql_query( &dbconn, sql ) ) { + Level tempDatabaseLevel = mDatabaseLevel; + databaseLevel( NOLOG ); + Error( "Can't insert log entry: sql(%s) error(%s)", sql, mysql_error( &dbconn ) ); + databaseLevel(tempDatabaseLevel); } + } + if ( level <= mSyslogLevel ) { + int priority = smSyslogPriorities[level]; + //priority |= LOG_DAEMON; + syslog( priority, "%s [%s] [%s]", classString, mId.c_str(), syslogStart ); + } - free(filecopy); - if ( level <= FATAL ) { - logTerm(); - zmDbClose(); - if ( level <= PANIC ) - abort(); - exit( -1 ); - } + free(filecopy); + if ( level <= FATAL ) { + logTerm(); + zmDbClose(); + if ( level <= PANIC ) + abort(); + exit( -1 ); } } @@ -547,6 +558,8 @@ void logInit( const char *name, const Logger::Options &options ) { } void logTerm() { - if ( Logger::smInstance ) + if ( Logger::smInstance ) { delete Logger::smInstance; + Logger::smInstance = NULL; + } } diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 88683a698..698e164e3 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -396,8 +396,10 @@ Monitor::Monitor( if ( purpose == CAPTURE ) { - this->connect(); - if ( ! mem_ptr ) exit(-1); + if ( ! this->connect() ) { + Error("unable to connect, but doing capture"); + exit(-1); + } memset( mem_ptr, 0, mem_size ); shared_data->size = sizeof(SharedData); shared_data->active = enabled; @@ -486,38 +488,53 @@ bool Monitor::connect() { #if ZM_MEM_MAPPED snprintf( mem_file, sizeof(mem_file), "%s/zm.mmap.%d", staticConfig.PATH_MAP.c_str(), id ); map_fd = open( mem_file, O_RDWR|O_CREAT, (mode_t)0600 ); - if ( map_fd < 0 ) + if ( map_fd < 0 ) { Fatal( "Can't open memory map file %s, probably not enough space free: %s", mem_file, strerror(errno) ); + } else { + Debug(3, "Success opening mmap file at (%s)", mem_file ); + } struct stat map_stat; if ( fstat( map_fd, &map_stat ) < 0 ) Fatal( "Can't stat memory map file %s: %s, is the zmc process for this monitor running?", mem_file, strerror(errno) ); - if ( map_stat.st_size != mem_size && purpose == CAPTURE ) { - // Allocate the size - if ( ftruncate( map_fd, mem_size ) < 0 ) { - Fatal( "Can't extend memory map file %s to %d bytes: %s", mem_file, mem_size, strerror(errno) ); - } - } else if ( map_stat.st_size == 0 ) { - Error( "Got empty memory map file size %ld, is the zmc process for this monitor running?", map_stat.st_size, mem_size ); - return false; - } else if ( map_stat.st_size != mem_size ) { - Error( "Got unexpected memory map file size %ld, expected %d", map_stat.st_size, mem_size ); - return false; - } else { -#ifdef MAP_LOCKED - mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, map_fd, 0 ); - if ( mem_ptr == MAP_FAILED ) { - if ( errno == EAGAIN ) { - Debug( 1, "Unable to map file %s (%d bytes) to locked memory, trying unlocked", mem_file, mem_size ); -#endif - mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0 ); - Debug( 1, "Mapped file %s (%d bytes) to locked memory, unlocked", mem_file, mem_size ); -#ifdef MAP_LOCKED + + if ( map_stat.st_size != mem_size ) { + if ( purpose == CAPTURE ) { + // Allocate the size + if ( ftruncate( map_fd, mem_size ) < 0 ) { + Fatal( "Can't extend memory map file %s to %d bytes: %s", mem_file, mem_size, strerror(errno) ); } + } else if ( map_stat.st_size == 0 ) { + Error( "Got empty memory map file size %ld, is the zmc process for this monitor running?", map_stat.st_size, mem_size ); + return false; + } else { + Error( "Got unexpected memory map file size %ld, expected %d", map_stat.st_size, mem_size ); + return false; } + } + + Debug(3, "MMap file size is %ld", map_stat.st_size ); +#ifdef MAP_LOCKED + mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, map_fd, 0 ); + if ( mem_ptr == MAP_FAILED ) { + if ( errno == EAGAIN ) { + Debug( 1, "Unable to map file %s (%d bytes) to locked memory, trying unlocked", mem_file, mem_size ); + #endif - if ( mem_ptr == MAP_FAILED ) - Fatal( "Can't map file %s (%d bytes) to memory: %s(%d)", mem_file, mem_size, strerror(errno), errno ); + mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0 ); + Debug( 1, "Mapped file %s (%d bytes) to unlocked memory", mem_file, mem_size ); +#ifdef MAP_LOCKED + } else { + Error( "Unable to map file %s (%d bytes) to locked memory (%s)", mem_file, mem_size , strerror(errno) ); + } + } +#endif + if ( mem_ptr == MAP_FAILED ) + Fatal( "Can't map file %s (%d bytes) to memory: %s(%d)", mem_file, mem_size, strerror(errno), errno ); + if ( mem_ptr == NULL ) { + Error( "mmap gave a null address:" ); + } else { + Debug(3, "mmapped to %p", mem_ptr ); } #else // ZM_MEM_MAPPED shm_id = shmget( (config.shm_key&0xffff0000)|id, mem_size, IPC_CREAT|0700 ); @@ -536,26 +553,28 @@ bool Monitor::connect() { video_store_data = (VideoStoreData *)((char *)trigger_data + sizeof(TriggerData)); struct timeval *shared_timestamps = (struct timeval *)((char *)video_store_data + sizeof(VideoStoreData)); unsigned char *shared_images = (unsigned char *)((char *)shared_timestamps + (image_buffer_count*sizeof(struct timeval))); + - if(((unsigned long)shared_images % 64) != 0) { + if ( ((unsigned long)shared_images % 64) != 0 ) { /* Align images buffer to nearest 64 byte boundary */ Debug(3,"Aligning shared memory images to the next 64 byte boundary"); shared_images = (uint8_t*)((unsigned long)shared_images + (64 - ((unsigned long)shared_images % 64))); } - Debug(3, "Allocating %d image buffers", image_buffer_count ); - image_buffer = new Snapshot[image_buffer_count]; - for ( int i = 0; i < image_buffer_count; i++ ) { - image_buffer[i].timestamp = &(shared_timestamps[i]); - image_buffer[i].image = new Image( width, height, camera->Colours(), camera->SubpixelOrder(), &(shared_images[i*camera->ImageSize()]) ); - image_buffer[i].image->HoldBuffer(true); /* Don't release the internal buffer or replace it with another */ + if ( purpose == CAPTURE ) { + Debug(3, "Allocating %d image buffers", image_buffer_count ); + image_buffer = new Snapshot[image_buffer_count]; + for ( int i = 0; i < image_buffer_count; i++ ) { + image_buffer[i].timestamp = &(shared_timestamps[i]); + image_buffer[i].image = new Image( width, height, camera->Colours(), camera->SubpixelOrder(), &(shared_images[i*camera->ImageSize()]) ); + image_buffer[i].image->HoldBuffer(true); /* Don't release the internal buffer or replace it with another */ + } + if ( (deinterlacing & 0xff) == 4) { + /* Four field motion adaptive deinterlacing in use */ + /* Allocate a buffer for the next image */ + next_buffer.image = new Image( width, height, camera->Colours(), camera->SubpixelOrder()); + next_buffer.timestamp = new struct timeval; + } } - if ( (deinterlacing & 0xff) == 4) { - /* Four field motion adaptive deinterlacing in use */ - /* Allocate a buffer for the next image */ - next_buffer.image = new Image( width, height, camera->Colours(), camera->SubpixelOrder()); - next_buffer.timestamp = new struct timeval; - } - if ( ( purpose == ANALYSIS ) && analysis_fps ) { // Size of pre event buffer must be greater than pre_event_count // if alarm_frame_count > 1, because in this case the buffer contains @@ -567,7 +586,7 @@ bool Monitor::connect() { pre_event_buffer[i].image = new Image( width, height, camera->Colours(), camera->SubpixelOrder()); } } - +Debug(3, "Success connecting"); return true; } diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index d87886002..53ee3aef6 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -228,11 +228,11 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, audio_output_context = avcodec_alloc_context3( audio_output_codec ); // Copy params from inputstream to context ret = avcodec_parameters_to_context( audio_output_context, audio_input_stream->codecpar ); - if (ret < 0) { + if ( ret < 0 ) { Error("Unable to copy audio params to context %s\n", av_make_error_string(ret).c_str()); } ret = avcodec_parameters_from_context( audio_output_stream->codecpar, audio_output_context ); - if (ret < 0) { + if ( ret < 0 ) { Error("Unable to copy audio params to stream %s\n", av_make_error_string(ret).c_str()); } @@ -324,11 +324,13 @@ VideoStore::~VideoStore(){ while ( 1 ) { #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) +#if 0 ret = avcodec_send_frame( audio_output_context, NULL ); if ( ret < 0 ) { Error("Error sending flush to encoder (%d) (%s)", ret, av_err2str( ret )); break; } +#endif ret = avcodec_receive_packet( audio_output_context, &pkt ); if ( ret < 0 ) { Error("ERror encoding audio while flushing (%d) (%s)", ret, av_err2str( ret )); @@ -377,18 +379,24 @@ VideoStore::~VideoStore(){ // What if we were only doing audio recording? if ( video_output_stream ) { avcodec_close(video_output_context); - //av_free(video_output_context); video_output_context = NULL; } if (audio_output_stream) { avcodec_close(audio_output_context); - //av_free(audio_output_context); audio_output_context = NULL; #ifdef HAVE_LIBAVRESAMPLE if ( resample_context ) { avresample_close( resample_context ); avresample_free( &resample_context ); } + if ( input_frame ) { + av_frame_free( &input_frame ); + input_frame = NULL; + } + if ( output_frame ) { + av_frame_free( &output_frame ); + output_frame = NULL; + } #endif } @@ -404,15 +412,6 @@ VideoStore::~VideoStore(){ /* free the stream */ avformat_free_context(oc); - - if ( input_frame ) { - av_frame_free( &input_frame ); - input_frame = NULL; - } - if ( output_frame ) { - av_frame_free( &output_frame ); - output_frame = NULL; - } } bool VideoStore::setup_resampler() { @@ -803,8 +802,8 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) { * If we are at the end of the file, pass an empty packet to the decoder * to flush it. */ - if ((ret = avcodec_decode_audio4(audio_input_context, input_frame, - &data_present, ipkt)) < 0) { + if ( (ret = avcodec_decode_audio4(audio_input_context, input_frame, + &data_present, ipkt)) < 0 ) { Error( "Could not decode frame (error '%s')\n", av_make_error_string(ret).c_str()); dumpPacket( ipkt ); @@ -829,8 +828,10 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) { input_frame->nb_samples )) < 0 ) { Error( "Could not resample frame (error '%s')\n", av_make_error_string(ret).c_str()); + av_frame_unref( input_frame ); return 0; } + av_frame_unref( input_frame ); if ( avresample_available( resample_context ) < output_frame->nb_samples ) { Debug(1, "No enough samples yet"); @@ -864,15 +865,22 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) { zm_av_packet_unref(&opkt); return 0; } + av_frame_unref( output_frame ); if (( ret = avcodec_receive_packet( audio_output_context, &opkt )) < 0 ) { + if ( EAGAIN == ret ) { + // THe codec may need more samples than it has, perfectly valid + Debug( 3, "Could not recieve packet (error '%s')", + av_make_error_string(ret).c_str()); + } else { Error( "Could not recieve packet (error '%s')", av_make_error_string(ret).c_str()); + } zm_av_packet_unref(&opkt); + av_frame_unref( input_frame ); + av_frame_unref( output_frame ); return 0; } - av_frame_unref( input_frame ); - av_frame_unref( output_frame ); #else if (( ret = avcodec_encode_audio2( audio_output_context, &opkt, output_frame, &data_present )) < 0) { Error( "Could not encode frame (error '%s')",