diff --git a/include/FFmpegUtilities.h b/include/FFmpegUtilities.h index 2cab4000..d90c37c6 100644 --- a/include/FFmpegUtilities.h +++ b/include/FFmpegUtilities.h @@ -81,4 +81,15 @@ #undef av_err2str #define av_err2str(errnum) av_make_error_string(errnum).c_str() + #if LIBAVFORMAT_VERSION_MAJOR >= 55 + #define AV_ALLOCATE_FRAME() av_frame_alloc() + #define AV_RESET_FRAME(av_frame) av_frame_unref(av_frame) + #define AV_FREE_FRAME(av_frame) av_frame_free(av_frame) + #else + #define AV_ALLOCATE_FRAME() avcodec_alloc_frame() + #define AV_RESET_FRAME(av_frame) avcodec_get_frame_defaults(av_frame) + #define AV_FREE_FRAME(av_frame) avcodec_free_frame(av_frame) + #endif + + #endif diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index faeb450f..c631c6fd 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -686,7 +686,7 @@ bool FFmpegReader::GetAVFrame() int frameFinished = -1; // Decode video frame - AVFrame *next_frame = avcodec_alloc_frame(); + AVFrame *next_frame = AV_ALLOCATE_FRAME(); #pragma omp critical (packet_cache) avcodec_decode_video2(pCodecCtx, next_frame, &frameFinished, packet); @@ -722,7 +722,7 @@ bool FFmpegReader::GetAVFrame() } // deallocate the frame - avcodec_free_frame(&next_frame); + AV_FREE_FRAME(&next_frame); // Did we get a video frame? return frameFinished; @@ -822,7 +822,7 @@ void FFmpegReader::ProcessVideoPacket(long int requested_frame) uint8_t *buffer = NULL; // Allocate an AVFrame structure - pFrameRGB = avcodec_alloc_frame(); + pFrameRGB = AV_ALLOCATE_FRAME(); if (pFrameRGB == NULL) throw OutOfBoundsFrame("Convert Image Broke!", current_frame, video_length); @@ -850,7 +850,7 @@ void FFmpegReader::ProcessVideoPacket(long int requested_frame) // Free the RGB image av_free(buffer); - avcodec_free_frame(&pFrameRGB); + AV_FREE_FRAME(&pFrameRGB); // Remove frame and packet RemoveAVFrame(my_frame); @@ -898,8 +898,8 @@ void FFmpegReader::ProcessAudioPacket(long int requested_frame, long int target_ // Init an AVFrame to hold the decoded audio samples int frame_finished = 0; - AVFrame *audio_frame = avcodec_alloc_frame(); - avcodec_get_frame_defaults(audio_frame); + AVFrame *audio_frame = AV_ALLOCATE_FRAME(); + AV_RESET_FRAME(audio_frame); int packet_samples = 0; int data_size = 0; @@ -988,8 +988,8 @@ void FFmpegReader::ProcessAudioPacket(long int requested_frame, long int target_ AppendDebugMethod("FFmpegReader::ProcessAudioPacket (ReSample)", "packet_samples", packet_samples, "info.channels", info.channels, "info.sample_rate", info.sample_rate, "aCodecCtx->sample_fmt", aCodecCtx->sample_fmt, "AV_SAMPLE_FMT_S16", AV_SAMPLE_FMT_S16, "", -1); // Create output frame - AVFrame *audio_converted = avcodec_alloc_frame(); - avcodec_get_frame_defaults(audio_converted); + AVFrame *audio_converted = AV_ALLOCATE_FRAME(); + AV_RESET_FRAME(audio_converted); audio_converted->nb_samples = audio_frame->nb_samples; av_samples_alloc(audio_converted->data, audio_converted->linesize, info.channels, audio_frame->nb_samples, AV_SAMPLE_FMT_S16, 0); @@ -1028,10 +1028,9 @@ void FFmpegReader::ProcessAudioPacket(long int requested_frame, long int target_ avr = NULL; // Free AVFrames - avcodec_free_frame(&audio_frame); - av_freep(&audio_converted[0]); - avcodec_free_frame(&audio_converted); - + AV_FREE_FRAME(&audio_frame); + av_free(audio_converted->data[0]); + AV_FREE_FRAME(&audio_converted); int starting_frame_number = -1; bool partial_frame = true; diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 02f0c9af..b2aee34b 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -469,9 +469,9 @@ void FFmpegWriter::write_queued_frames() // Get AVFrame AVFrame *av_frame = av_frames[frame]; - // deallocate AVPicture and AVFrame - av_freep(&av_frame[0]); // picture buffer - avcodec_free_frame(&av_frame); + // Deallocate AVPicture and AVFrame + free(av_frame->data[0]); // TODO: Determine why av_free crashes on Windows + AV_FREE_FRAME(&av_frame); av_frames.erase(frame); } @@ -764,7 +764,7 @@ void FFmpegWriter::add_avframe(tr1::shared_ptr frame, AVFrame* av_frame) else { // Do not add, and deallocate this AVFrame - avcodec_free_frame(&av_frame); + AV_FREE_FRAME(&av_frame); } } @@ -1095,8 +1095,8 @@ void FFmpegWriter::write_audio_packets(bool final) AVFrame *audio_frame = NULL; if (!final) { // Create input frame (and allocate arrays) - audio_frame = avcodec_alloc_frame(); - avcodec_get_frame_defaults(audio_frame); + audio_frame = AV_ALLOCATE_FRAME(); + AV_RESET_FRAME(audio_frame); audio_frame->nb_samples = total_frame_samples / channels_in_frame; // Fill input frame with sample data @@ -1136,8 +1136,8 @@ void FFmpegWriter::write_audio_packets(bool final) remaining_frame_samples = total_frame_samples; // Create output frame (and allocate arrays) - AVFrame *audio_converted = avcodec_alloc_frame(); - avcodec_get_frame_defaults(audio_converted); + AVFrame *audio_converted = AV_ALLOCATE_FRAME(); + AV_RESET_FRAME(audio_converted); audio_converted->nb_samples = total_frame_samples / channels_in_frame; av_samples_alloc(audio_converted->data, audio_converted->linesize, info.channels, audio_converted->nb_samples, output_sample_fmt, 0); @@ -1174,11 +1174,11 @@ void FFmpegWriter::write_audio_packets(bool final) memcpy(all_resampled_samples, audio_converted->data[0], nb_samples * info.channels * av_get_bytes_per_sample(output_sample_fmt)); // Remove converted audio - av_freep(&audio_frame[0]); // this deletes the all_queued_samples array + free(audio_frame->data[0]); // TODO: Determine why av_free crashes on Windows + AV_FREE_FRAME(&audio_frame); + av_free(audio_converted->data[0]); + AV_FREE_FRAME(&audio_converted); all_queued_samples = NULL; // this array cleared with above call - avcodec_free_frame(&audio_frame); - av_freep(&audio_converted[0]); - avcodec_free_frame(&audio_converted); AppendDebugMethod("FFmpegWriter::write_audio_packets (Successfully completed 1st resampling)", "nb_samples", nb_samples, "remaining_frame_samples", remaining_frame_samples, "", -1, "", -1, "", -1, "", -1); } @@ -1212,8 +1212,8 @@ void FFmpegWriter::write_audio_packets(bool final) break; // Convert to planar (if needed by audio codec) - AVFrame *frame_final = avcodec_alloc_frame(); - avcodec_get_frame_defaults(frame_final); + AVFrame *frame_final = AV_ALLOCATE_FRAME(); + AV_RESET_FRAME(frame_final); if (av_sample_fmt_is_planar(audio_codec->sample_fmt)) { AppendDebugMethod("FFmpegWriter::write_audio_packets (2nd resampling for Planar formats)", "in_sample_fmt", output_sample_fmt, "out_sample_fmt", audio_codec->sample_fmt, "in_sample_rate", info.sample_rate, "out_sample_rate", info.sample_rate, "in_channels", info.channels, "out_channels", info.channels); @@ -1233,8 +1233,8 @@ void FFmpegWriter::write_audio_packets(bool final) } // Create input frame (and allocate arrays) - audio_frame = avcodec_alloc_frame(); - avcodec_get_frame_defaults(audio_frame); + audio_frame = AV_ALLOCATE_FRAME(); + AV_RESET_FRAME(audio_frame); audio_frame->nb_samples = audio_input_position / info.channels; // Create a new array @@ -1265,8 +1265,8 @@ void FFmpegWriter::write_audio_packets(bool final) memcpy(samples, frame_final->data[0], nb_samples * av_get_bytes_per_sample(audio_codec->sample_fmt) * info.channels); // deallocate AVFrame - av_freep(&audio_frame[0]); // delete final_samples_planar array - avcodec_free_frame(&audio_frame); + free(audio_frame->data[0]); // TODO: Determine why av_free crashes on Windows + AV_FREE_FRAME(&audio_frame); AppendDebugMethod("FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)", "nb_samples", nb_samples, "", -1, "", -1, "", -1, "", -1, "", -1); @@ -1286,7 +1286,7 @@ void FFmpegWriter::write_audio_packets(bool final) } // Increment PTS (in samples) - write_audio_count += audio_input_frame_size; + write_audio_count += FFMIN(audio_input_frame_size, audio_input_position); frame_final->pts = write_audio_count; // Set the AVFrame's PTS // Init the packet @@ -1335,8 +1335,8 @@ void FFmpegWriter::write_audio_packets(bool final) } // deallocate AVFrame - av_freep(&frame_final[0]); // delete AVFrame internal array OR final_samples array (depending on if its planar or not planar) - avcodec_free_frame(&frame_final); + free(frame_final->data[0]); // TODO: Determine why av_free crashes on Windows + AV_FREE_FRAME(&frame_final); // deallocate memory for packet av_free_packet(&pkt); @@ -1366,7 +1366,7 @@ AVFrame* FFmpegWriter::allocate_avframe(PixelFormat pix_fmt, int width, int heig AVFrame *new_av_frame = NULL; // Allocate an AVFrame structure - new_av_frame = avcodec_alloc_frame(); + new_av_frame = AV_ALLOCATE_FRAME(); if (new_av_frame == NULL) throw OutOfMemory("Could not allocate AVFrame", path); @@ -1435,7 +1435,7 @@ void FFmpegWriter::process_video_packet(tr1::shared_ptr frame) add_avframe(frame, frame_final); // Deallocate memory - avcodec_free_frame(&frame_source); + AV_FREE_FRAME(&frame_source); } // end task diff --git a/src/FrameMapper.cpp b/src/FrameMapper.cpp index 7512b78b..5fa688a3 100644 --- a/src/FrameMapper.cpp +++ b/src/FrameMapper.cpp @@ -635,8 +635,8 @@ void FrameMapper::ResampleMappedAudio(tr1::shared_ptr frame, long int ori // Create input frame (and allocate arrays) - AVFrame *audio_frame = avcodec_alloc_frame(); - avcodec_get_frame_defaults(audio_frame); + AVFrame *audio_frame = AV_ALLOCATE_FRAME(); + AV_RESET_FRAME(audio_frame); audio_frame->nb_samples = total_frame_samples / channels_in_frame; int error_code = avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) frame_samples, @@ -654,8 +654,8 @@ void FrameMapper::ResampleMappedAudio(tr1::shared_ptr frame, long int ori AppendDebugMethod("FrameMapper::ResampleMappedAudio (adjust # of samples)", "total_frame_samples", total_frame_samples, "info.sample_rate", info.sample_rate, "sample_rate_in_frame", sample_rate_in_frame, "info.channels", info.channels, "channels_in_frame", channels_in_frame, "original_frame_number", original_frame_number); // Create output frame (and allocate arrays) - AVFrame *audio_converted = avcodec_alloc_frame(); - avcodec_get_frame_defaults(audio_converted); + AVFrame *audio_converted = AV_ALLOCATE_FRAME(); + AV_RESET_FRAME(audio_converted); audio_converted->nb_samples = total_frame_samples; av_samples_alloc(audio_converted->data, audio_converted->linesize, info.channels, total_frame_samples, AV_SAMPLE_FMT_S16, 0); @@ -697,11 +697,11 @@ void FrameMapper::ResampleMappedAudio(tr1::shared_ptr frame, long int ori memcpy(resampled_samples, audio_converted->data[0], (nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * info.channels)); // Free frames - av_freep(&audio_frame[0]); - avcodec_free_frame(&audio_frame); + free(audio_frame->data[0]); // TODO: Determine why av_free crashes on Windows + AV_FREE_FRAME(&audio_frame); + av_free(audio_converted->data[0]); + AV_FREE_FRAME(&audio_converted); frame_samples = NULL; - av_freep(&audio_converted[0]); - avcodec_free_frame(&audio_converted); // Resize the frame to hold the right # of channels and samples int channel_buffer_size = nb_samples; diff --git a/src/examples/Example.cpp b/src/examples/Example.cpp index ddd7d6c8..eb875b05 100644 --- a/src/examples/Example.cpp +++ b/src/examples/Example.cpp @@ -60,12 +60,12 @@ int main(int argc, char* argv[]) // Open Timeline r9.Open(); -// cout << " --> 1" << endl; -// t.GetFrame(1); -// cout << " --> 500" << endl; -// t.GetFrame(500); -// cout << "1034" << endl; -// t.GetFrame(1034); + cout << " --> 1" << endl; + r9.GetFrame(1); + cout << " --> 500" << endl; + r9.GetFrame(500); + cout << "1034" << endl; + r9.GetFrame(1034); // cout << "1" << endl; // t.GetFrame(1); // cout << "1200" << endl; @@ -186,15 +186,17 @@ int main(int argc, char* argv[]) //map.Open(); /* WRITER ---------------- */ - FFmpegWriter w9("C:\\Users\\Jonathan\\test-output.webm"); - w9.debug = true; + FFmpegWriter w9("C:\\Users\\Jonathan\\test-output.avi"); + w9.debug = false; //ImageWriter w9("/home/jonathan/output.gif"); // Set options //w9.SetVideoOptions(true, "mpeg4", r9.info.fps, r9.info.width, r9.info.height, Fraction(1,1), false, false, 1000000); //w9.SetAudioOptions(true, "mp2", r9.info.sample_rate, r9.info.channels, r9.info.channel_layout, 64000); - w9.SetAudioOptions(true, "libvorbis", r9.info.sample_rate, r9.info.channels, r9.info.channel_layout, 128000); - w9.SetVideoOptions(true, "libvpx", r9.info.fps, r9.info.width, r9.info.height, Fraction(1,1), false, false, 3000000); + w9.SetVideoOptions(true, "libx264", r9.info.fps, r9.info.width, r9.info.height, Fraction(1,1), false, false, 1000000); + w9.SetAudioOptions(true, "mp2", r9.info.sample_rate, r9.info.channels, r9.info.channel_layout, 64000); + //w9.SetAudioOptions(true, "libvorbis", r9.info.sample_rate, r9.info.channels, r9.info.channel_layout, 128000); + //w9.SetVideoOptions(true, "libvpx", r9.info.fps, r9.info.width, r9.info.height, Fraction(1,1), false, false, 3000000); //w9.SetAudioOptions(true, "libmp3lame", 22050, r9.info.channels, r9.info.channel_layout, 120000); //w9.SetVideoOptions(true, "libx264", t10.info.fps, t10.info.width, t10.info.height, t10.info.pixel_ratio, false, false, 1500000); //w9.SetVideoOptions(true, "rawvideo", r9.info.fps, 400, 2, r9.info.pixel_ratio, false, false, 20000000); @@ -208,7 +210,7 @@ int main(int argc, char* argv[]) // w9.SetOption(VIDEO_STREAM, "qmin", "2" ); // w9.SetOption(VIDEO_STREAM, "qmax", "30" ); - w9.SetOption(VIDEO_STREAM, "crf", "10" ); +// w9.SetOption(VIDEO_STREAM, "crf", "10" ); // w9.SetOption(VIDEO_STREAM, "rc_min_rate", "2000000" ); // w9.SetOption(VIDEO_STREAM, "rc_max_rate", "4000000" ); // w9.SetOption(VIDEO_STREAM, "max_b_frames", "10" );