[packages/libopenshot] - up to 0.2.0

arekm arekm at pld-linux.org
Tue Jul 3 12:04:22 CEST 2018


commit bdb3122b46dff51d73d2cdbfc0d61281c20f6b84
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date:   Tue Jul 3 12:04:14 2018 +0200

    - up to 0.2.0

 libopenshot-ffmpeg.patch | 1111 ----------------------------------------------
 libopenshot.spec         |    8 +-
 2 files changed, 4 insertions(+), 1115 deletions(-)
---
diff --git a/libopenshot.spec b/libopenshot.spec
index 20957dd..4c1ec1d 100644
--- a/libopenshot.spec
+++ b/libopenshot.spec
@@ -1,11 +1,11 @@
 Summary:	Library for creating and editing videos
 Name:		libopenshot
-Version:	0.1.9
-Release:	3
+Version:	0.2.0
+Release:	1
 License:	LGPL-3.0+
 Group:		Libraries
 Source0:	https://github.com/OpenShot/libopenshot/archive/v%{version}.tar.gz
-# Source0-md5:	74012e7260c91c3413b45401c46bfcc0
+# Source0-md5:	09b05e23356d53777bcb2cad1615683b
 Patch0:		imagemagick7.patch
 Patch1:		%{name}-ffmpeg.patch
 Group:		Development/Libraries
@@ -82,7 +82,7 @@ rm -rf $RPM_BUILD_ROOT
 %files
 %defattr(644,root,root,755)
 %attr(755,root,root) %{_libdir}/libopenshot.so.*.*
-%attr(755,root,root) %ghost %{_libdir}/libopenshot.so.14
+%attr(755,root,root) %ghost %{_libdir}/libopenshot.so.15
 
 %files devel
 %defattr(644,root,root,755)
diff --git a/libopenshot-ffmpeg.patch b/libopenshot-ffmpeg.patch
index 82569fb..4436219 100644
--- a/libopenshot-ffmpeg.patch
+++ b/libopenshot-ffmpeg.patch
@@ -1,1114 +1,3 @@
-From 774eb365b3f663b1f53dd24c1650fafb3c445ea6 Mon Sep 17 00:00:00 2001
-From: Jonathan Thomas <jonathan at openshot.org>
-Date: Wed, 21 Mar 2018 02:10:46 -0500
-Subject: [PATCH] FFMPEG 3.2 support for FFmpegReader (writer support coming
- soon)
-
----
- include/FFmpegReader.h       |   7 +-
- include/FFmpegUtilities.h    |  49 ++++++++++-
- src/FFmpegReader.cpp         | 195 +++++++++++++++++++++++++++++--------------
- tests/FFmpegReader_Tests.cpp |   4 +-
- 4 files changed, 183 insertions(+), 72 deletions(-)
-
-diff --git a/include/FFmpegReader.h b/include/FFmpegReader.h
-index beed9bc..6072756 100644
---- a/include/FFmpegReader.h
-+++ b/include/FFmpegReader.h
-@@ -99,7 +99,7 @@ namespace openshot
- 		AVCodecContext *pCodecCtx, *aCodecCtx;
- 		AVStream *pStream, *aStream;
- 		AVPacket *packet;
--		AVPicture *pFrame;
-+		AVFrame *pFrame;
- 		bool is_open;
- 		bool is_duration_known;
- 		bool check_interlace;
-@@ -154,9 +154,6 @@ namespace openshot
- 		/// Check the working queue, and move finished frames to the finished queue
- 		void CheckWorkingFrames(bool end_of_stream, int64_t requested_frame);
- 
--		/// Convert image to RGB format
--		void convert_image(int64_t current_frame, AVPicture *copyFrame, int width, int height, PixelFormat pix_fmt);
--
- 		/// Convert Frame Number into Audio PTS
- 		int64_t ConvertFrameToAudioPTS(int64_t frame_number);
- 
-@@ -200,7 +197,7 @@ namespace openshot
- 		std::shared_ptr<Frame> ReadStream(int64_t requested_frame);
- 
- 		/// Remove AVFrame from cache (and deallocate it's memory)
--		void RemoveAVFrame(AVPicture*);
-+		void RemoveAVFrame(AVFrame*);
- 
- 		/// Remove AVPacket from cache (and deallocate it's memory)
- 		void RemoveAVPacket(AVPacket*);
-diff --git a/include/FFmpegUtilities.h b/include/FFmpegUtilities.h
-index 103aceb..b38132f 100644
---- a/include/FFmpegUtilities.h
-+++ b/include/FFmpegUtilities.h
-@@ -34,6 +34,10 @@
- 	#define UINT64_C(c) (c ## ULL)
- 	#endif
- 
-+	#ifndef IS_FFMPEG_3_2
-+	#define IS_FFMPEG_3_2 (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 64, 101))
-+	#endif
-+
- 	// Include the FFmpeg headers
- 	extern "C" {
- 		#include <libavcodec/avcodec.h>
-@@ -55,6 +59,10 @@
- 		#if LIBAVFORMAT_VERSION_MAJOR >= 54
- 			#include <libavutil/channel_layout.h>
- 		#endif
-+
-+		#if IS_FFMPEG_3_2
-+			#include "libavutil/imgutils.h"
-+		#endif
- 	}
- 
- 	// This was removed from newer versions of FFmpeg (but still used in libopenshot)
-@@ -98,16 +106,55 @@
- 		#define PIX_FMT_YUV420P AV_PIX_FMT_YUV420P
- 	#endif
- 
--	#if LIBAVFORMAT_VERSION_MAJOR >= 55
-+	#if IS_FFMPEG_3_2
-+		#define AV_ALLOCATE_FRAME() av_frame_alloc()
-+		#define AV_ALLOCATE_IMAGE(av_frame, pix_fmt, width, height) av_image_alloc(av_frame->data, av_frame->linesize, width, height, pix_fmt, 1);
-+		#define AV_RESET_FRAME(av_frame) av_frame_unref(av_frame)
-+    	#define AV_FREE_FRAME(av_frame) av_frame_free(av_frame)
-+		#define AV_FREE_PACKET(av_packet) av_packet_unref(av_packet)
-+		#define AV_FREE_CONTEXT(av_context) avcodec_free_context(&av_context);
-+		#define AV_GET_CODEC_TYPE(av_stream) av_stream->codecpar->codec_type
-+		#define AV_FIND_DECODER_CODEC_ID(av_stream) av_stream->codecpar->codec_id;
-+		auto AV_GET_CODEC_CONTEXT = [](AVStream* av_stream, AVCodec* av_codec) { \
-+			AVCodecContext *context = avcodec_alloc_context3(av_codec); \
-+			avcodec_parameters_to_context(context, av_stream->codecpar); \
-+			return context; \
-+		};
-+		#define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context) av_stream->codecpar
-+		#define AV_GET_CODEC_PIXEL_FORMAT(av_stream, av_context) (AVPixelFormat) av_stream->codecpar->format
-+		#define AV_GET_SAMPLE_FORMAT(av_stream, av_context) av_stream->codecpar->format
-+		#define AV_GET_IMAGE_SIZE(pix_fmt, width, height) av_image_get_buffer_size(pix_fmt, width, height, 1)
-+		#define AV_COPY_PICTURE_DATA(av_frame, buffer, pix_fmt, width, height) av_image_fill_arrays(av_frame->data, av_frame->linesize, buffer, pix_fmt, width, height, 1);
-+	#elif LIBAVFORMAT_VERSION_MAJOR >= 55
- 		#define AV_ALLOCATE_FRAME() av_frame_alloc()
-+		#define AV_ALLOCATE_IMAGE(av_frame, pix_fmt, width, height) avpicture_alloc((AVPicture *) av_frame, pix_fmt, width, height);
- 		#define AV_RESET_FRAME(av_frame) av_frame_unref(av_frame)
-     	#define AV_FREE_FRAME(av_frame) av_frame_free(av_frame)
- 		#define AV_FREE_PACKET(av_packet) av_packet_unref(av_packet)
-+		#define AV_FREE_CONTEXT(av_context) avcodec_close(av_context);
-+		#define AV_GET_CODEC_TYPE(av_stream) av_stream->codec->codec_type
-+		#define AV_FIND_DECODER_CODEC_ID(av_stream) av_stream->codec->codec_id;
-+		#define AV_GET_CODEC_CONTEXT(av_stream, av_codec) av_stream->codec;
-+		#define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context) av_context
-+		#define AV_GET_CODEC_PIXEL_FORMAT(av_stream, av_context) av_context->pix_fmt
-+		#define AV_GET_SAMPLE_FORMAT(av_stream, av_context) av_context->sample_fmt
-+		#define AV_GET_IMAGE_SIZE(pix_fmt, width, height) avpicture_get_size(pix_fmt, width, height)
-+		#define AV_COPY_PICTURE_DATA(av_frame, buffer, pix_fmt, width, height) avpicture_fill((AVPicture *) av_frame, buffer, pix_fmt, width, height);
- 	#else
- 		#define AV_ALLOCATE_FRAME() avcodec_alloc_frame()
-+		#define AV_ALLOCATE_IMAGE(av_frame, pix_fmt, width, height) avpicture_alloc((AVPicture *) av_frame, pix_fmt, width, height);
- 		#define AV_RESET_FRAME(av_frame) avcodec_get_frame_defaults(av_frame)
- 		#define AV_FREE_FRAME(av_frame) avcodec_free_frame(av_frame)
- 		#define AV_FREE_PACKET(av_packet) av_free_packet(av_packet)
-+		#define AV_FREE_CONTEXT(av_context) avcodec_close(av_context);
-+		#define AV_GET_CODEC_TYPE(av_stream) av_stream->codec->codec_type
-+		#define AV_FIND_DECODER_CODEC_ID(av_stream) av_stream->codec->codec_id;
-+		#define AV_GET_CODEC_CONTEXT(av_stream, av_codec) av_stream->codec;
-+		#define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context) av_context
-+		#define AV_GET_CODEC_PIXEL_FORMAT(av_stream, av_context) av_context->pix_fmt
-+		#define AV_GET_SAMPLE_FORMAT(av_stream, av_context) av_context->sample_fmt
-+		#define AV_GET_IMAGE_SIZE(pix_fmt, width, height) avpicture_get_size(pix_fmt, width, height)
-+		#define AV_COPY_PICTURE_DATA(av_frame, buffer, pix_fmt, width, height) avpicture_fill((AVPicture *) av_frame, buffer, pix_fmt, width, height);
- 	#endif
- 
- 
-diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp
-index f803c86..57dffc2 100644
---- a/src/FFmpegReader.cpp
-+++ b/src/FFmpegReader.cpp
-@@ -123,11 +123,11 @@ void FFmpegReader::Open()
- 		for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++)
- 		{
- 			// Is this a video stream?
--			if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && videoStream < 0) {
-+			if (AV_GET_CODEC_TYPE(pFormatCtx->streams[i]) == AVMEDIA_TYPE_VIDEO && videoStream < 0) {
- 				videoStream = i;
- 			}
- 			// Is this an audio stream?
--			if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && audioStream < 0) {
-+			if (AV_GET_CODEC_TYPE(pFormatCtx->streams[i]) == AVMEDIA_TYPE_AUDIO && audioStream < 0) {
- 				audioStream = i;
- 			}
- 		}
-@@ -142,13 +142,17 @@ void FFmpegReader::Open()
- 
- 			// Set the codec and codec context pointers
- 			pStream = pFormatCtx->streams[videoStream];
--			pCodecCtx = pFormatCtx->streams[videoStream]->codec;
-+
-+			// Find the codec ID from stream
-+			AVCodecID codecId = AV_FIND_DECODER_CODEC_ID(pStream);
-+
-+			// Get codec and codec context from stream
-+			AVCodec *pCodec = avcodec_find_decoder(codecId);
-+			pCodecCtx = AV_GET_CODEC_CONTEXT(pStream, pCodec);
- 
- 			// Set number of threads equal to number of processors (not to exceed 16)
- 			pCodecCtx->thread_count = min(OPEN_MP_NUM_PROCESSORS, 16);
- 
--			// Find the decoder for the video stream
--			AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
- 			if (pCodec == NULL) {
- 				throw InvalidCodec("A valid video codec could not be found for this file.", path);
- 			}
-@@ -168,13 +172,17 @@ void FFmpegReader::Open()
- 
- 			// Get a pointer to the codec context for the audio stream
- 			aStream = pFormatCtx->streams[audioStream];
--			aCodecCtx = pFormatCtx->streams[audioStream]->codec;
-+
-+			// Find the codec ID from stream
-+			AVCodecID codecId = AV_FIND_DECODER_CODEC_ID(aStream);
-+
-+			// Get codec and codec context from stream
-+			AVCodec *aCodec = avcodec_find_decoder(codecId);
-+			aCodecCtx = AV_GET_CODEC_CONTEXT(aStream, aCodec);
- 
- 			// Set number of threads equal to number of processors (not to exceed 16)
- 			aCodecCtx->thread_count = min(OPEN_MP_NUM_PROCESSORS, 16);
- 
--			// Find the decoder for the audio stream
--			AVCodec *aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
- 			if (aCodec == NULL) {
- 				throw InvalidCodec("A valid audio codec could not be found for this file.", path);
- 			}
-@@ -222,12 +230,12 @@ void FFmpegReader::Close()
- 		if (info.has_video)
- 		{
- 			avcodec_flush_buffers(pCodecCtx);
--			avcodec_close(pCodecCtx);
-+			AV_FREE_CONTEXT(pCodecCtx);
- 		}
- 		if (info.has_audio)
- 		{
- 			avcodec_flush_buffers(aCodecCtx);
--			avcodec_close(aCodecCtx);
-+			AV_FREE_CONTEXT(aCodecCtx);
- 		}
- 
- 		// Clear final cache
-@@ -269,12 +277,12 @@ void FFmpegReader::UpdateAudioInfo()
- 	info.has_audio = true;
- 	info.file_size = pFormatCtx->pb ? avio_size(pFormatCtx->pb) : -1;
- 	info.acodec = aCodecCtx->codec->name;
--	info.channels = aCodecCtx->channels;
--	if (aCodecCtx->channel_layout == 0)
--		aCodecCtx->channel_layout = av_get_default_channel_layout( aCodecCtx->channels );
--	info.channel_layout = (ChannelLayout) aCodecCtx->channel_layout;
--	info.sample_rate = aCodecCtx->sample_rate;
--	info.audio_bit_rate = aCodecCtx->bit_rate;
-+	info.channels = AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channels;
-+	if (AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout == 0)
-+		AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout = av_get_default_channel_layout( AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channels );
-+	info.channel_layout = (ChannelLayout) AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout;
-+	info.sample_rate = AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->sample_rate;
-+	info.audio_bit_rate = AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->bit_rate;
- 
- 	// Set audio timebase
- 	info.audio_timebase.num = aStream->time_base.num;
-@@ -318,8 +326,8 @@ void FFmpegReader::UpdateVideoInfo()
- 	// Set values of FileInfo struct
- 	info.has_video = true;
- 	info.file_size = pFormatCtx->pb ? avio_size(pFormatCtx->pb) : -1;
--	info.height = pCodecCtx->height;
--	info.width = pCodecCtx->width;
-+	info.height = AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->height;
-+	info.width = AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->width;
- 	info.vcodec = pCodecCtx->codec->name;
- 	info.video_bit_rate = pFormatCtx->bit_rate;
- 	if (!check_fps)
-@@ -334,18 +342,17 @@ void FFmpegReader::UpdateVideoInfo()
- 		info.pixel_ratio.num = pStream->sample_aspect_ratio.num;
- 		info.pixel_ratio.den = pStream->sample_aspect_ratio.den;
- 	}
--	else if (pCodecCtx->sample_aspect_ratio.num != 0)
-+	else if (AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->sample_aspect_ratio.num != 0)
- 	{
--		info.pixel_ratio.num = pCodecCtx->sample_aspect_ratio.num;
--		info.pixel_ratio.den = pCodecCtx->sample_aspect_ratio.den;
-+		info.pixel_ratio.num = AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->sample_aspect_ratio.num;
-+		info.pixel_ratio.den = AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->sample_aspect_ratio.den;
- 	}
- 	else
- 	{
- 		info.pixel_ratio.num = 1;
- 		info.pixel_ratio.den = 1;
- 	}
--
--	info.pixel_format = pCodecCtx->pix_fmt;
-+	info.pixel_format = AV_GET_CODEC_PIXEL_FORMAT(pStream, pCodecCtx);
- 
- 	// Calculate the DAR (display aspect ratio)
- 	Fraction size(info.width * info.pixel_ratio.num, info.height * info.pixel_ratio.den);
-@@ -697,28 +704,60 @@ int FFmpegReader::GetNextPacket()
- bool FFmpegReader::GetAVFrame()
- {
- 	int frameFinished = -1;
-+	int ret = 0;
- 
- 	// Decode video frame
- 	AVFrame *next_frame = AV_ALLOCATE_FRAME();
- 	#pragma omp critical (packet_cache)
--	avcodec_decode_video2(pCodecCtx, next_frame, &frameFinished, packet);
--
--	// is frame finished
--	if (frameFinished)
- 	{
--		// AVFrames are clobbered on the each call to avcodec_decode_video, so we
--		// must make a copy of the image data before this method is called again.
--		pFrame = new AVPicture();
--		avpicture_alloc(pFrame, pCodecCtx->pix_fmt, info.width, info.height);
--		av_picture_copy(pFrame, (AVPicture *) next_frame, pCodecCtx->pix_fmt, info.width, info.height);
--
--		// Detect interlaced frame (only once)
--		if (!check_interlace)
--		{
--			check_interlace = true;
--			info.interlaced_frame = next_frame->interlaced_frame;
--			info.top_field_first = next_frame->top_field_first;
-+	#if IS_FFMPEG_3_2
-+		frameFinished = 0;
-+		ret = avcodec_send_packet(pCodecCtx, packet);
-+		if (ret < 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
-+			ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::GetAVFrame (Packet not sent)", "", -1, "", -1, "", -1, "", -1, "", -1, "", -1);
-+		}
-+		else {
-+			pFrame = new AVFrame();
-+			while (ret >= 0) {
-+				ret =  avcodec_receive_frame(pCodecCtx, next_frame);
-+		  if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
-+		  break;
-+				}
-+				// TODO also handle possible further frames
-+				// Use only the first frame like avcodec_decode_video2
-+				if (frameFinished == 0 ) {
-+					frameFinished = 1;
-+					av_image_alloc(pFrame->data, pFrame->linesize, info.width, info.height, (AVPixelFormat)(pStream->codecpar->format), 1);
-+					av_image_copy(pFrame->data, pFrame->linesize, (const uint8_t**)next_frame->data, next_frame->linesize,
-+												(AVPixelFormat)(pStream->codecpar->format), info.width, info.height);
-+					if (!check_interlace)	{
-+						check_interlace = true;
-+						info.interlaced_frame = next_frame->interlaced_frame;
-+						info.top_field_first = next_frame->top_field_first;
-+					}
-+				}
-+			}
-+		}
-+	#else
-+		avcodec_decode_video2(pCodecCtx, next_frame, &frameFinished, packet);
-+
-+		// is frame finished
-+		if (frameFinished) {
-+			// AVFrames are clobbered on the each call to avcodec_decode_video, so we
-+			// must make a copy of the image data before this method is called again.
-+			pFrame = AV_ALLOCATE_FRAME();
-+			avpicture_alloc((AVPicture *) pFrame, pCodecCtx->pix_fmt, info.width, info.height);
-+			av_picture_copy((AVPicture *) pFrame, (AVPicture *) next_frame, pCodecCtx->pix_fmt, info.width,
-+							info.height);
-+
-+			// Detect interlaced frame (only once)
-+			if (!check_interlace) {
-+				check_interlace = true;
-+				info.interlaced_frame = next_frame->interlaced_frame;
-+				info.top_field_first = next_frame->top_field_first;
-+			}
- 		}
-+	#endif
- 	}
- 
- 	// deallocate the frame
-@@ -800,11 +839,11 @@ void FFmpegReader::ProcessVideoPacket(int64_t requested_frame)
- 	ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ProcessVideoPacket (Before)", "requested_frame", requested_frame, "current_frame", current_frame, "", -1, "", -1, "", -1, "", -1);
- 
- 	// Init some things local (for OpenMP)
--	PixelFormat pix_fmt = pCodecCtx->pix_fmt;
-+	PixelFormat pix_fmt = AV_GET_CODEC_PIXEL_FORMAT(pStream, pCodecCtx);
- 	int height = info.height;
- 	int width = info.width;
- 	int64_t video_length = info.video_length;
--    AVPicture *my_frame = pFrame;
-+	AVFrame *my_frame = pFrame;
- 
- 	// Add video frame to list of processing video frames
- 	const GenericScopedLock<CriticalSection> lock(processingCriticalSection);
-@@ -844,17 +883,16 @@ void FFmpegReader::ProcessVideoPacket(int64_t requested_frame)
- 		}
- 
- 		// Determine required buffer size and allocate buffer
--		numBytes = avpicture_get_size(PIX_FMT_RGBA, width, height);
-+		numBytes = AV_GET_IMAGE_SIZE(PIX_FMT_RGBA, width, height);
-+
- 		#pragma omp critical (video_buffer)
- 		buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
- 
--		// Assign appropriate parts of buffer to image planes in pFrameRGB
--		// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
--		// of AVPicture
--		avpicture_fill((AVPicture *) pFrameRGB, buffer, PIX_FMT_RGBA, width, height);
-+		// Copy picture data from one AVFrame (or AVPicture) to another one.
-+		AV_COPY_PICTURE_DATA(pFrameRGB, buffer, PIX_FMT_RGBA, width, height);
- 
--		SwsContext *img_convert_ctx = sws_getContext(info.width, info.height, pCodecCtx->pix_fmt, width,
--													  height, PIX_FMT_RGBA, SWS_BILINEAR, NULL, NULL, NULL);
-+		SwsContext *img_convert_ctx = sws_getContext(info.width, info.height, AV_GET_CODEC_PIXEL_FORMAT(pStream, pCodecCtx), width,
-+															  height, PIX_FMT_RGBA, SWS_BILINEAR, NULL, NULL, NULL);
- 
- 		// Resize / Convert to RGB
- 		sws_scale(img_convert_ctx, my_frame->data, my_frame->linesize, 0,
-@@ -925,20 +963,52 @@ void FFmpegReader::ProcessAudioPacket(int64_t requested_frame, int64_t target_fr
- 
- 	// re-initialize buffer size (it gets changed in the avcodec_decode_audio2 method call)
- 	int buf_size = AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE;
--	int used = avcodec_decode_audio4(aCodecCtx, audio_frame, &frame_finished, packet);
-+	#pragma omp critical (ProcessAudioPacket)
-+	{
-+	#if IS_FFMPEG_3_2
-+		int ret = 0;
-+		frame_finished = 1;
-+		while((packet->size > 0 || (!packet->data && frame_finished)) && ret >= 0) {
-+			frame_finished = 0;
-+			ret =  avcodec_send_packet(aCodecCtx, packet);
-+			if (ret < 0 && ret !=  AVERROR(EINVAL) && ret != AVERROR_EOF) {
-+				avcodec_send_packet(aCodecCtx, NULL);
-+				break;
-+			}
-+			if (ret >= 0)
-+				packet->size = 0;
-+			ret =  avcodec_receive_frame(aCodecCtx, audio_frame);
-+			if (ret >= 0)
-+				frame_finished = 1;
-+			if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
-+				avcodec_flush_buffers(aCodecCtx);
-+				ret = 0;
-+			}
-+			if (ret >= 0) {
-+				ret = frame_finished;
-+			}
-+		}
-+		if (!packet->data && !frame_finished)
-+		{
-+			ret = -1;
-+		}
-+	#else
-+		int used = avcodec_decode_audio4(aCodecCtx, audio_frame, &frame_finished, packet);
-+#endif
-+	}
- 
- 	if (frame_finished) {
- 
- 		// determine how many samples were decoded
--		int planar = av_sample_fmt_is_planar(aCodecCtx->sample_fmt);
-+		int planar = av_sample_fmt_is_planar((AVSampleFormat)AV_GET_CODEC_PIXEL_FORMAT(aStream, aCodecCtx));
- 		int plane_size = -1;
- 		data_size = av_samples_get_buffer_size(&plane_size,
--				aCodecCtx->channels,
-+				AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channels,
- 				audio_frame->nb_samples,
--				aCodecCtx->sample_fmt, 1);
-+				(AVSampleFormat)(AV_GET_SAMPLE_FORMAT(aStream, aCodecCtx)), 1);
- 
- 		// Calculate total number of samples
--		packet_samples = audio_frame->nb_samples * aCodecCtx->channels;
-+		packet_samples = audio_frame->nb_samples * AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channels;
- 	}
- 
- 	// Estimate the # of samples and the end of this packet's location (to prevent GAPS for the next timestamp)
-@@ -999,7 +1069,7 @@ void FFmpegReader::ProcessAudioPacket(int64_t requested_frame, int64_t target_fr
- 	// Allocate audio buffer
- 	int16_t *audio_buf = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
- 
--	ZmqLogger::Instance()->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);
-+	ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ProcessAudioPacket (ReSample)", "packet_samples", packet_samples, "info.channels", info.channels, "info.sample_rate", info.sample_rate, "aCodecCtx->sample_fmt", AV_GET_SAMPLE_FORMAT(aStream, aCodecCtx), "AV_SAMPLE_FMT_S16", AV_SAMPLE_FMT_S16, "", -1);
- 
- 	// Create output frame
- 	AVFrame *audio_converted = AV_ALLOCATE_FRAME();
-@@ -1012,9 +1082,9 @@ void FFmpegReader::ProcessAudioPacket(int64_t requested_frame, int64_t target_fr
- 
- 	// setup resample context
- 	avr = avresample_alloc_context();
--	av_opt_set_int(avr,  "in_channel_layout", aCodecCtx->channel_layout, 0);
--	av_opt_set_int(avr, "out_channel_layout", aCodecCtx->channel_layout, 0);
--	av_opt_set_int(avr,  "in_sample_fmt",     aCodecCtx->sample_fmt,     0);
-+	av_opt_set_int(avr,  "in_channel_layout", AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout, 0);
-+	av_opt_set_int(avr, "out_channel_layout", AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout, 0);
-+	av_opt_set_int(avr,  "in_sample_fmt",     AV_GET_SAMPLE_FORMAT(aStream, aCodecCtx), 0);
- 	av_opt_set_int(avr, "out_sample_fmt",     AV_SAMPLE_FMT_S16,     0);
- 	av_opt_set_int(avr,  "in_sample_rate",    info.sample_rate,    0);
- 	av_opt_set_int(avr, "out_sample_rate",    info.sample_rate,    0);
-@@ -1767,7 +1837,7 @@ void FFmpegReader::CheckWorkingFrames(bool end_of_stream, int64_t requested_fram
- void FFmpegReader::CheckFPS()
- {
- 	check_fps = true;
--	avpicture_alloc(pFrame, pCodecCtx->pix_fmt, info.width, info.height);
-+	AV_ALLOCATE_IMAGE(pFrame, AV_GET_CODEC_PIXEL_FORMAT(pStream, pCodecCtx), info.width, info.height);
- 
- 	int first_second_counter = 0;
- 	int second_second_counter = 0;
-@@ -1878,17 +1948,14 @@ void FFmpegReader::CheckFPS()
- }
- 
- // Remove AVFrame from cache (and deallocate it's memory)
--void FFmpegReader::RemoveAVFrame(AVPicture* remove_frame)
-+void FFmpegReader::RemoveAVFrame(AVFrame* remove_frame)
- {
-     // Remove pFrame (if exists)
-     if (remove_frame)
-     {
-         // Free memory
--        avpicture_free(remove_frame);
--
--        // Delete the object
--        delete remove_frame;
--    }
-+		av_freep(&remove_frame->data[0]);
-+	}
- }
- 
- // Remove AVPacket from cache (and deallocate it's memory)
-diff --git a/tests/FFmpegReader_Tests.cpp b/tests/FFmpegReader_Tests.cpp
-index 54017e8..82e8573 100644
---- a/tests/FFmpegReader_Tests.cpp
-+++ b/tests/FFmpegReader_Tests.cpp
-@@ -72,8 +72,8 @@ TEST(FFmpegReader_Check_Audio_File)
- 	CHECK_CLOSE(0.0f, samples[50], 0.00001);
- 	CHECK_CLOSE(0.0f, samples[100], 0.00001);
- 	CHECK_CLOSE(0.0f, samples[200], 0.00001);
--	CHECK_CLOSE(0.160781, samples[230], 0.00001);
--	CHECK_CLOSE(-0.06125f, samples[300], 0.00001);
-+	CHECK_CLOSE(0.164062f, samples[230], 0.00001);
-+	CHECK_CLOSE(-0.0625f, samples[300], 0.00001);
- 
- 	// Close reader
- 	r.Close();
-From 22384c770501b9d737501847400f571f67edf385 Mon Sep 17 00:00:00 2001
-From: Jonathan Thomas <jonathan at openshot.org>
-Date: Wed, 28 Mar 2018 15:09:55 -0500
-Subject: [PATCH] FFMPEG 3.2 support for FFmpegWriter (Thanks Peter!)
-
----
- include/FFmpegUtilities.h |  62 +++++++++---
- src/FFmpegWriter.cpp      | 252 +++++++++++++++++++++++++++++-----------------
- 2 files changed, 210 insertions(+), 104 deletions(-)
-
-diff --git a/include/FFmpegUtilities.h b/include/FFmpegUtilities.h
-index b38132f..578c658 100644
---- a/include/FFmpegUtilities.h
-+++ b/include/FFmpegUtilities.h
-@@ -108,53 +108,87 @@
- 
- 	#if IS_FFMPEG_3_2
- 		#define AV_ALLOCATE_FRAME() av_frame_alloc()
--		#define AV_ALLOCATE_IMAGE(av_frame, pix_fmt, width, height) av_image_alloc(av_frame->data, av_frame->linesize, width, height, pix_fmt, 1);
-+		#define AV_ALLOCATE_IMAGE(av_frame, pix_fmt, width, height) av_image_alloc(av_frame->data, av_frame->linesize, width, height, pix_fmt, 1)
- 		#define AV_RESET_FRAME(av_frame) av_frame_unref(av_frame)
-     	#define AV_FREE_FRAME(av_frame) av_frame_free(av_frame)
- 		#define AV_FREE_PACKET(av_packet) av_packet_unref(av_packet)
--		#define AV_FREE_CONTEXT(av_context) avcodec_free_context(&av_context);
-+		#define AV_FREE_CONTEXT(av_context) avcodec_free_context(&av_context)
- 		#define AV_GET_CODEC_TYPE(av_stream) av_stream->codecpar->codec_type
--		#define AV_FIND_DECODER_CODEC_ID(av_stream) av_stream->codecpar->codec_id;
-+		#define AV_FIND_DECODER_CODEC_ID(av_stream) av_stream->codecpar->codec_id
- 		auto AV_GET_CODEC_CONTEXT = [](AVStream* av_stream, AVCodec* av_codec) { \
- 			AVCodecContext *context = avcodec_alloc_context3(av_codec); \
- 			avcodec_parameters_to_context(context, av_stream->codecpar); \
- 			return context; \
- 		};
-+		#define AV_GET_CODEC_PAR_CONTEXT(av_stream, av_codec) av_codec;
-+		#define AV_GET_CODEC_FROM_STREAM(av_stream,codec_in)
- 		#define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context) av_stream->codecpar
- 		#define AV_GET_CODEC_PIXEL_FORMAT(av_stream, av_context) (AVPixelFormat) av_stream->codecpar->format
- 		#define AV_GET_SAMPLE_FORMAT(av_stream, av_context) av_stream->codecpar->format
- 		#define AV_GET_IMAGE_SIZE(pix_fmt, width, height) av_image_get_buffer_size(pix_fmt, width, height, 1)
--		#define AV_COPY_PICTURE_DATA(av_frame, buffer, pix_fmt, width, height) av_image_fill_arrays(av_frame->data, av_frame->linesize, buffer, pix_fmt, width, height, 1);
-+		#define AV_COPY_PICTURE_DATA(av_frame, buffer, pix_fmt, width, height) av_image_fill_arrays(av_frame->data, av_frame->linesize, buffer, pix_fmt, width, height, 1)
-+		#define AV_OUTPUT_CONTEXT(output_context, path) avformat_alloc_output_context2( output_context, NULL, NULL, path)
-+		#define AV_OPTION_FIND(priv_data, name) av_opt_find(priv_data, name, NULL, 0, 0)
-+		#define AV_OPTION_SET( av_stream, priv_data, name, value, avcodec) 	av_opt_set(priv_data, name, value, 0); avcodec_parameters_from_context(av_stream->codecpar, avcodec);
-+		#define AV_FORMAT_NEW_STREAM(oc, st_codec, av_codec, av_st) 	av_st = avformat_new_stream(oc, NULL);\
-+			if (!av_st) \
-+				throw OutOfMemory("Could not allocate memory for the video stream.", path); \
-+			c = avcodec_alloc_context3(av_codec); \
-+			st_codec = c; \
-+			av_st->codecpar->codec_id = av_codec->id;
-+		#define AV_COPY_PARAMS_FROM_CONTEXT(av_stream, av_codec) avcodec_parameters_from_context(av_stream->codecpar, av_codec);
- 	#elif LIBAVFORMAT_VERSION_MAJOR >= 55
- 		#define AV_ALLOCATE_FRAME() av_frame_alloc()
--		#define AV_ALLOCATE_IMAGE(av_frame, pix_fmt, width, height) avpicture_alloc((AVPicture *) av_frame, pix_fmt, width, height);
-+		#define AV_ALLOCATE_IMAGE(av_frame, pix_fmt, width, height) avpicture_alloc((AVPicture *) av_frame, pix_fmt, width, height)
- 		#define AV_RESET_FRAME(av_frame) av_frame_unref(av_frame)
-     	#define AV_FREE_FRAME(av_frame) av_frame_free(av_frame)
- 		#define AV_FREE_PACKET(av_packet) av_packet_unref(av_packet)
--		#define AV_FREE_CONTEXT(av_context) avcodec_close(av_context);
-+		#define AV_FREE_CONTEXT(av_context) avcodec_close(av_context)
- 		#define AV_GET_CODEC_TYPE(av_stream) av_stream->codec->codec_type
--		#define AV_FIND_DECODER_CODEC_ID(av_stream) av_stream->codec->codec_id;
--		#define AV_GET_CODEC_CONTEXT(av_stream, av_codec) av_stream->codec;
-+		#define AV_FIND_DECODER_CODEC_ID(av_stream) av_stream->codec->codec_id
-+		#define AV_GET_CODEC_CONTEXT(av_stream, av_codec) av_stream->codec
-+		#define AV_GET_CODEC_PAR_CONTEXT(av_stream, av_codec) av_stream->codec
-+		#define AV_GET_CODEC_FROM_STREAM(av_stream, codec_in) codec_in = av_stream->codec;
- 		#define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context) av_context
- 		#define AV_GET_CODEC_PIXEL_FORMAT(av_stream, av_context) av_context->pix_fmt
- 		#define AV_GET_SAMPLE_FORMAT(av_stream, av_context) av_context->sample_fmt
- 		#define AV_GET_IMAGE_SIZE(pix_fmt, width, height) avpicture_get_size(pix_fmt, width, height)
--		#define AV_COPY_PICTURE_DATA(av_frame, buffer, pix_fmt, width, height) avpicture_fill((AVPicture *) av_frame, buffer, pix_fmt, width, height);
-+		#define AV_COPY_PICTURE_DATA(av_frame, buffer, pix_fmt, width, height) avpicture_fill((AVPicture *) av_frame, buffer, pix_fmt, width, height)
-+		#define AV_OUTPUT_CONTEXT(output_context, path) oc = avformat_alloc_context()
-+		#define AV_OPTION_FIND(priv_data, name) av_opt_find(priv_data, name, NULL, 0, 0)
-+		#define AV_OPTION_SET(av_stream, priv_data, name, value, avcodec) av_opt_set (priv_data, name, value, 0)
-+		#define AV_FORMAT_NEW_STREAM( oc,  av_context,  av_codec, av_st) av_st = avformat_new_stream(oc, av_codec); \
-+			if (!av_st) \
-+				throw OutOfMemory("Could not allocate memory for the video stream.", path); \
-+			avcodec_get_context_defaults3(av_st->codec, av_codec); \
-+			c = av_st->codec;
-+		#define AV_COPY_PARAMS_FROM_CONTEXT(av_stream, av_codec)
- 	#else
- 		#define AV_ALLOCATE_FRAME() avcodec_alloc_frame()
--		#define AV_ALLOCATE_IMAGE(av_frame, pix_fmt, width, height) avpicture_alloc((AVPicture *) av_frame, pix_fmt, width, height);
-+		#define AV_ALLOCATE_IMAGE(av_frame, pix_fmt, width, height) avpicture_alloc((AVPicture *) av_frame, pix_fmt, width, height)
- 		#define AV_RESET_FRAME(av_frame) avcodec_get_frame_defaults(av_frame)
- 		#define AV_FREE_FRAME(av_frame) avcodec_free_frame(av_frame)
- 		#define AV_FREE_PACKET(av_packet) av_free_packet(av_packet)
--		#define AV_FREE_CONTEXT(av_context) avcodec_close(av_context);
-+		#define AV_FREE_CONTEXT(av_context) avcodec_close(av_context)
- 		#define AV_GET_CODEC_TYPE(av_stream) av_stream->codec->codec_type
--		#define AV_FIND_DECODER_CODEC_ID(av_stream) av_stream->codec->codec_id;
--		#define AV_GET_CODEC_CONTEXT(av_stream, av_codec) av_stream->codec;
-+		#define AV_FIND_DECODER_CODEC_ID(av_stream) av_stream->codec->codec_id
-+		#define AV_GET_CODEC_CONTEXT(av_stream, av_codec) av_stream->codec
-+		#define AV_GET_CODEC_PAR_CONTEXT(av_stream, av_codec) av_stream->codec
-+		#define AV_GET_CODEC_FROM_STREAM(av_stream, codec_in ) codec_in = av_stream->codec;
- 		#define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context) av_context
- 		#define AV_GET_CODEC_PIXEL_FORMAT(av_stream, av_context) av_context->pix_fmt
- 		#define AV_GET_SAMPLE_FORMAT(av_stream, av_context) av_context->sample_fmt
- 		#define AV_GET_IMAGE_SIZE(pix_fmt, width, height) avpicture_get_size(pix_fmt, width, height)
--		#define AV_COPY_PICTURE_DATA(av_frame, buffer, pix_fmt, width, height) avpicture_fill((AVPicture *) av_frame, buffer, pix_fmt, width, height);
-+		#define AV_COPY_PICTURE_DATA(av_frame, buffer, pix_fmt, width, height) avpicture_fill((AVPicture *) av_frame, buffer, pix_fmt, width, height)
-+		#define AV_OUTPUT_CONTEXT(output_context, path) oc = avformat_alloc_context()
-+		#define AV_OPTION_FIND(priv_data, name) av_opt_find(priv_data, name, NULL, 0, 0)
-+		#define AV_OPTION_SET(av_stream, priv_data, name, value, avcodec) av_opt_set (priv_data, name, value, 0)
-+		#define AV_FORMAT_NEW_STREAM( oc,  av_context,  av_codec, av_st) av_st = avformat_new_stream(oc, av_codec); \
-+			if (!av_st) \
-+				throw OutOfMemory("Could not allocate memory for the video stream.", path); \
-+			avcodec_get_context_defaults3(av_st->codec, av_codec); \
-+			c = av_st->codec;
-+		#define AV_COPY_PARAMS_FROM_CONTEXT(av_stream, av_codec)
- 	#endif
- 
- 
-diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp
-index e83e478..889e262 100644
---- a/src/FFmpegWriter.cpp
-+++ b/src/FFmpegWriter.cpp
-@@ -76,7 +76,7 @@ void FFmpegWriter::auto_detect_format()
- 		throw InvalidFormat("Could not deduce output format from file extension.", path);
- 
- 	// Allocate the output media context
--	oc = avformat_alloc_context();
-+	AV_OUTPUT_CONTEXT(&oc, path.c_str());
- 	if (!oc)
- 		throw OutOfMemory("Could not allocate memory for AVFormatContext.", path);
- 
-@@ -211,12 +211,19 @@ void FFmpegWriter::SetOption(StreamType stream, string name, string value)
- {
- 	// Declare codec context
- 	AVCodecContext *c = NULL;
-+	AVStream *st = NULL;
- 	stringstream convert(value);
- 
--	if (info.has_video && stream == VIDEO_STREAM && video_st)
--		c = video_st->codec;
--	else if (info.has_audio && stream == AUDIO_STREAM && audio_st)
--		c = audio_st->codec;
-+	if (info.has_video && stream == VIDEO_STREAM && video_st) {
-+		st = video_st;
-+		// Get codec context
-+		c = AV_GET_CODEC_PAR_CONTEXT(st, video_codec);
-+	}
-+	else if (info.has_audio && stream == AUDIO_STREAM && audio_st) {
-+		st = audio_st;
-+		// Get codec context
-+		c = AV_GET_CODEC_PAR_CONTEXT(st, audio_codec);
-+	}
- 	else
- 		throw NoStreamsFound("The stream was not found. Be sure to call PrepareStreams() first.", path);
- 
-@@ -226,11 +233,7 @@ void FFmpegWriter::SetOption(StreamType stream, string name, string value)
- 	// Was a codec / stream found?
- 	if (c)
- 		// Find AVOption (if it exists)
--		#if LIBAVFORMAT_VERSION_MAJOR <= 53
--			option = av_find_opt(c->priv_data, name.c_str(), NULL, NULL, NULL);
--		#else
--			option = av_opt_find(c->priv_data, name.c_str(), NULL, 0, 0);
--		#endif
-+		option = AV_OPTION_FIND(c->priv_data, name.c_str());
- 
- 	// Was option found?
- 	if (option || (name == "g" || name == "qmin" || name == "qmax" || name == "max_b_frames" || name == "mb_decision" ||
-@@ -283,11 +286,7 @@ void FFmpegWriter::SetOption(StreamType stream, string name, string value)
- 
- 		else
- 			// Set AVOption
--			#if LIBAVFORMAT_VERSION_MAJOR <= 53
--				av_set_string3 (c->priv_data, name.c_str(), value.c_str(), 0, NULL);
--			#else
--				av_opt_set (c->priv_data, name.c_str(), value.c_str(), 0);
--			#endif
-+			AV_OPTION_SET(st, c->priv_data, name.c_str(), value.c_str(), c);
- 
- 		ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::SetOption (" + (string)name + ")", "stream == VIDEO_STREAM", stream == VIDEO_STREAM, "", -1, "", -1, "", -1, "", -1, "", -1);
- 
-@@ -334,7 +333,9 @@ void FFmpegWriter::WriteHeader()
- 
- 	// Write the stream header, if any
- 	// TODO: add avoptions / parameters instead of NULL
--	avformat_write_header(oc, NULL);
-+	if (avformat_write_header(oc, NULL) != 0) {
-+	    throw InvalidFile("Could not write header to file.", path);
-+	}
- 
- 	// Mark as 'written'
- 	write_header = true;
-@@ -548,10 +549,10 @@ void FFmpegWriter::WriteTrailer()
- // Flush encoders
- void FFmpegWriter::flush_encoders()
- {
--    if (info.has_audio && audio_codec && audio_st->codec->codec_type == AVMEDIA_TYPE_AUDIO && audio_codec->frame_size <= 1)
--        return;
--    if (info.has_video && video_st->codec->codec_type == AVMEDIA_TYPE_VIDEO && (oc->oformat->flags & AVFMT_RAWPICTURE) && video_codec->codec->id == AV_CODEC_ID_RAWVIDEO)
--        return;
-+	if (info.has_audio && audio_codec && AV_GET_CODEC_TYPE(audio_st) == AVMEDIA_TYPE_AUDIO && AV_GET_CODEC_ATTRIBUTES(audio_st, audio_codec)->frame_size <= 1)
-+		return;
-+	if (info.has_video && video_codec && AV_GET_CODEC_TYPE(video_st) == AVMEDIA_TYPE_VIDEO && (oc->oformat->flags & AVFMT_RAWPICTURE) && AV_FIND_DECODER_CODEC_ID(video_st) == AV_CODEC_ID_RAWVIDEO)
-+		return;
- 
-     int error_code = 0;
-     int stop_encoding = 1;
-@@ -575,29 +576,37 @@ void FFmpegWriter::flush_encoders()
- 			int got_packet = 0;
- 			int error_code = 0;
- 
--			#if LIBAVFORMAT_VERSION_MAJOR >= 54
--				// Newer versions of FFMpeg
--			error_code = avcodec_encode_video2(video_codec, &pkt, NULL, &got_packet);
--
-+			#if IS_FFMPEG_3_2
-+			#pragma omp critical (write_video_packet)
-+			{
-+				// Encode video packet (latest version of FFmpeg)
-+				error_code = avcodec_send_frame(video_codec, NULL);
-+				got_packet = 0;
-+			}
- 			#else
--				// Older versions of FFmpeg (much sloppier)
- 
--				// Encode Picture and Write Frame
--				int video_outbuf_size = 0;
-+				#if LIBAVFORMAT_VERSION_MAJOR >= 54
-+				// Encode video packet (older than FFmpeg 3.2)
-+				error_code = avcodec_encode_video2(video_codec, &pkt, NULL, &got_packet);
- 
--				/* encode the image */
--				int out_size = avcodec_encode_video(video_codec, NULL, video_outbuf_size, NULL);
-+				#else
-+					// Encode video packet (even older version of FFmpeg)
-+					int video_outbuf_size = 0;
- 
--				/* if zero size, it means the image was buffered */
--				if (out_size > 0) {
--					if(video_codec->coded_frame->key_frame)
--						pkt.flags |= AV_PKT_FLAG_KEY;
--					pkt.data= video_outbuf;
--					pkt.size= out_size;
-+					/* encode the image */
-+					int out_size = avcodec_encode_video(video_codec, NULL, video_outbuf_size, NULL);
- 
--					// got data back (so encode this frame)
--					got_packet = 1;
--				}
-+					/* if zero size, it means the image was buffered */
-+					if (out_size > 0) {
-+						if(video_codec->coded_frame->key_frame)
-+							pkt.flags |= AV_PKT_FLAG_KEY;
-+						pkt.data= video_outbuf;
-+						pkt.size= out_size;
-+
-+						// got data back (so encode this frame)
-+						got_packet = 1;
-+					}
-+				#endif
- 			#endif
- 
- 			if (error_code < 0) {
-@@ -651,7 +660,12 @@ void FFmpegWriter::flush_encoders()
- 
- 			/* encode the image */
- 			int got_packet = 0;
-+			#if IS_FFMPEG_3_2
-+			avcodec_send_frame(audio_codec, NULL);
-+			got_packet = 0;
-+			#else
- 			error_code = avcodec_encode_audio2(audio_codec, &pkt, NULL, &got_packet);
-+			#endif
- 			if (error_code < 0) {
- 				ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::flush_encoders ERROR [" + (string)av_err2str(error_code) + "]", "error_code", error_code, "", -1, "", -1, "", -1, "", -1, "", -1);
- 			}
-@@ -692,14 +706,14 @@ void FFmpegWriter::flush_encoders()
- // Close the video codec
- void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
- {
--	avcodec_close(st->codec);
-+	AV_FREE_CONTEXT(video_codec);
- 	video_codec = NULL;
- }
- 
- // Close the audio codec
- void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
- {
--	avcodec_close(st->codec);
-+	AV_FREE_CONTEXT(audio_codec);
- 	audio_codec = NULL;
- 
- 	// Clear buffers
-@@ -743,7 +757,7 @@ void FFmpegWriter::Close()
- 
- 	// Free the streams
- 	for (int i = 0; i < oc->nb_streams; i++) {
--		av_freep(&oc->streams[i]->codec);
-+		av_freep(AV_GET_CODEC_ATTRIBUTES(&oc->streams[i], &oc->streams[i]));
- 		av_freep(&oc->streams[i]);
- 	}
- 
-@@ -796,14 +810,8 @@ AVStream* FFmpegWriter::add_audio_stream()
- 		throw InvalidCodec("A valid audio codec could not be found for this file.", path);
- 
- 	// Create a new audio stream
--	st = avformat_new_stream(oc, codec);
--	if (!st)
--		throw OutOfMemory("Could not allocate memory for the audio stream.", path);
-+	AV_FORMAT_NEW_STREAM(oc, audio_codec, codec, st)
- 
--	// Set default values
--    avcodec_get_context_defaults3(st->codec, codec);
--
--	c = st->codec;
- 	c->codec_id = codec->id;
- #if LIBAVFORMAT_VERSION_MAJOR >= 53
- 	c->codec_type = AVMEDIA_TYPE_AUDIO;
-@@ -867,6 +875,7 @@ AVStream* FFmpegWriter::add_audio_stream()
- 	if (oc->oformat->flags & AVFMT_GLOBALHEADER)
- 		c->flags |= CODEC_FLAG_GLOBAL_HEADER;
- 
-+	AV_COPY_PARAMS_FROM_CONTEXT(st, c);
- 	ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::add_audio_stream", "c->codec_id", c->codec_id, "c->bit_rate", c->bit_rate, "c->channels", c->channels, "c->sample_fmt", c->sample_fmt, "c->channel_layout", c->channel_layout, "c->sample_rate", c->sample_rate);
- 
- 	return st;
-@@ -878,20 +887,14 @@ AVStream* FFmpegWriter::add_video_stream()
- 	AVCodecContext *c;
- 	AVStream *st;
- 
--	// Find the audio codec
-+	// Find the video codec
- 	AVCodec *codec = avcodec_find_encoder_by_name(info.vcodec.c_str());
- 	if (codec == NULL)
- 		throw InvalidCodec("A valid video codec could not be found for this file.", path);
- 
--	// Create a new stream
--	st = avformat_new_stream(oc, codec);
--	if (!st)
--		throw OutOfMemory("Could not allocate memory for the video stream.", path);
-+	// Create a new video stream
-+	AV_FORMAT_NEW_STREAM(oc, video_codec, codec, st)
- 
--	// Set default values
--    avcodec_get_context_defaults3(st->codec, codec);
--
--	c = st->codec;
- 	c->codec_id = codec->id;
- #if LIBAVFORMAT_VERSION_MAJOR >= 53
- 	c->codec_type = AVMEDIA_TYPE_VIDEO;
-@@ -923,6 +926,10 @@ AVStream* FFmpegWriter::add_video_stream()
- 	 identically 1. */
- 	c->time_base.num = info.video_timebase.num;
- 	c->time_base.den = info.video_timebase.den;
-+	#if LIBAVFORMAT_VERSION_MAJOR >= 55
-+	c->framerate = av_inv_q(c->time_base);
-+	#endif
-+	st->avg_frame_rate = av_inv_q(c->time_base);
- 	st->time_base.num = info.video_timebase.num;
- 	st->time_base.den = info.video_timebase.den;
- 
-@@ -965,6 +972,7 @@ AVStream* FFmpegWriter::add_video_stream()
-         }
-     }
- 
-+	AV_COPY_PARAMS_FROM_CONTEXT(st, c);
- 	ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::add_video_stream (" + (string)fmt->name + " : " + (string)av_get_pix_fmt_name(c->pix_fmt) + ")", "c->codec_id", c->codec_id, "c->bit_rate", c->bit_rate, "c->pix_fmt", c->pix_fmt, "oc->oformat->flags", oc->oformat->flags, "AVFMT_RAWPICTURE", AVFMT_RAWPICTURE, "", -1);
- 
- 	return st;
-@@ -974,7 +982,7 @@ AVStream* FFmpegWriter::add_video_stream()
- void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st)
- {
- 	AVCodec *codec;
--	audio_codec = st->codec;
-+	AV_GET_CODEC_FROM_STREAM(st, audio_codec)
- 
- 	// Set number of threads equal to number of processors (not to exceed 16)
- 	audio_codec->thread_count = min(OPEN_MP_NUM_PROCESSORS, 16);
-@@ -989,6 +997,7 @@ void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st)
- 	// Open the codec
- 	if (avcodec_open2(audio_codec, codec, NULL) < 0)
- 		throw InvalidCodec("Could not open codec", path);
-+	AV_COPY_PARAMS_FROM_CONTEXT(st, audio_codec);
- 
- 	// Calculate the size of the input frame (i..e how many samples per packet), and the output buffer
- 	// TODO: Ugly hack for PCM codecs (will be removed ASAP with new PCM support to compute the input frame size in samples
-@@ -996,7 +1005,8 @@ void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st)
- 		// No frame size found... so calculate
- 		audio_input_frame_size = 50000 / info.channels;
- 
--		switch (st->codec->codec_id) {
-+		int s = AV_FIND_DECODER_CODEC_ID(st);
-+		switch (s) {
- 		case AV_CODEC_ID_PCM_S16LE:
- 		case AV_CODEC_ID_PCM_S16BE:
- 		case AV_CODEC_ID_PCM_U16LE:
-@@ -1039,7 +1049,7 @@ void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st)
- void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st)
- {
- 	AVCodec *codec;
--	video_codec = st->codec;
-+	AV_GET_CODEC_FROM_STREAM(st, video_codec)
- 
- 	// Set number of threads equal to number of processors (not to exceed 16)
- 	video_codec->thread_count = min(OPEN_MP_NUM_PROCESSORS, 16);
-@@ -1047,7 +1057,7 @@ void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st)
- 	/* find the video encoder */
- 	codec = avcodec_find_encoder_by_name(info.vcodec.c_str());
- 	if (!codec)
--		codec = avcodec_find_encoder(video_codec->codec_id);
-+		codec = avcodec_find_encoder(AV_FIND_DECODER_CODEC_ID(st));
- 	if (!codec)
- 		throw InvalidCodec("Could not find codec", path);
- 
-@@ -1058,6 +1068,7 @@ void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st)
- 	/* open the codec */
- 	if (avcodec_open2(video_codec, codec, NULL) < 0)
- 		throw InvalidCodec("Could not open codec", path);
-+	AV_COPY_PARAMS_FROM_CONTEXT(st, video_codec);
- 
- 	// Add video metadata (if any)
- 	for(std::map<string, string>::iterator iter = info.metadata.begin(); iter != info.metadata.end(); ++iter)
-@@ -1345,8 +1356,39 @@ void FFmpegWriter::write_audio_packets(bool final)
- 
- 			/* encode the audio samples */
- 			int got_packet_ptr = 0;
--			int error_code = avcodec_encode_audio2(audio_codec, &pkt, frame_final, &got_packet_ptr);
- 
-+			#if IS_FFMPEG_3_2
-+			// Encode audio (latest version of FFmpeg)
-+			int error_code;
-+			int ret = 0;
-+			int frame_finished = 0;
-+			error_code = ret =  avcodec_send_frame(audio_codec, frame_final);
-+			if (ret < 0 && ret !=  AVERROR(EINVAL) && ret != AVERROR_EOF) {
-+				avcodec_send_frame(audio_codec, NULL);
-+			}
-+			else {
-+				if (ret >= 0)
-+					pkt.size = 0;
-+				ret =  avcodec_receive_packet(audio_codec, &pkt);
-+				if (ret >= 0)
-+					frame_finished = 1;
-+				if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
-+					avcodec_flush_buffers(audio_codec);
-+					ret = 0;
-+				}
-+				if (ret >= 0) {
-+					ret = frame_finished;
-+				}
-+			}
-+			if (!pkt.data && !frame_finished)
-+			{
-+				ret = -1;
-+			}
-+			got_packet_ptr = ret;
-+			#else
-+			// Encode audio (older versions of FFmpeg)
-+			int error_code = avcodec_encode_audio2(audio_codec, &pkt, frame_final, &got_packet_ptr);
-+			#endif
- 			/* if zero size, it means the image was buffered */
- 			if (error_code == 0 && got_packet_ptr) {
- 
-@@ -1416,7 +1458,7 @@ AVFrame* FFmpegWriter::allocate_avframe(PixelFormat pix_fmt, int width, int heig
- 		throw OutOfMemory("Could not allocate AVFrame", path);
- 
- 	// Determine required buffer size and allocate buffer
--	*buffer_size = avpicture_get_size(pix_fmt, width, height);
-+	*buffer_size = AV_GET_IMAGE_SIZE(pix_fmt, width, height);
- 
- 	// Create buffer (if not provided)
- 	if (!new_buffer)
-@@ -1424,7 +1466,7 @@ AVFrame* FFmpegWriter::allocate_avframe(PixelFormat pix_fmt, int width, int heig
- 		// New Buffer
- 		new_buffer = (uint8_t*)av_malloc(*buffer_size * sizeof(uint8_t));
- 		// Attach buffer to AVFrame
--		avpicture_fill((AVPicture *)new_av_frame, new_buffer, pix_fmt, width, height);
-+		AV_COPY_PICTURE_DATA(new_av_frame, new_buffer, pix_fmt, width, height);
- 		new_av_frame->width = width;
- 		new_av_frame->height = height;
- 		new_av_frame->format = pix_fmt;
-@@ -1468,10 +1510,14 @@ void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame)
- 
- 		// Init AVFrame for source image & final (converted image)
- 		frame_source = allocate_avframe(PIX_FMT_RGBA, source_image_width, source_image_height, &bytes_source, (uint8_t*) pixels);
-+		#if IS_FFMPEG_3_2
-+		AVFrame *frame_final = allocate_avframe((AVPixelFormat)(video_st->codecpar->format), info.width, info.height, &bytes_final, NULL);
-+		#else
- 		AVFrame *frame_final = allocate_avframe(video_codec->pix_fmt, info.width, info.height, &bytes_final, NULL);
-+		#endif
- 
- 		// Fill with data
--		avpicture_fill((AVPicture *) frame_source, (uint8_t*)pixels, PIX_FMT_RGBA, source_image_width, source_image_height);
-+        AV_COPY_PICTURE_DATA(frame_source, (uint8_t*)pixels, PIX_FMT_RGBA, source_image_width, source_image_height);
- 		ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::process_video_packet", "frame->number", frame->number, "bytes_source", bytes_source, "bytes_final", bytes_final, "", -1, "", -1, "", -1);
- 
- 		// Resize & convert pixel format
-@@ -1539,30 +1585,60 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame* fra
- 		/* encode the image */
- 		int got_packet_ptr = 0;
- 		int error_code = 0;
--		#if LIBAVFORMAT_VERSION_MAJOR >= 54
--			// Newer versions of FFMpeg
--			error_code = avcodec_encode_video2(video_codec, &pkt, frame_final, &got_packet_ptr);
--
-+		#if IS_FFMPEG_3_2
-+		// Write video packet (latest version of FFmpeg)
-+		int frameFinished = 0;
-+		int ret = avcodec_send_frame(video_codec, frame_final);
-+		error_code = ret;
-+		if (ret < 0 ) {
-+			ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet (Frame not sent)", "", -1, "", -1, "", -1, "", -1, "", -1, "", -1);
-+			if (ret == AVERROR(EAGAIN) )
-+				cerr << "Frame EAGAIN" << "\n";
-+			if (ret == AVERROR_EOF )
-+				cerr << "Frame AVERROR_EOF" << "\n";
-+			avcodec_send_frame(video_codec, NULL);
-+		}
-+		else {
-+			while (ret >= 0) {
-+				ret = avcodec_receive_packet(video_codec, &pkt);
-+		if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
-+					avcodec_flush_buffers(video_codec);
-+					got_packet_ptr = 0;
-+		break;
-+				}
-+				if (ret == 0) {
-+					got_packet_ptr = 1;
-+					break;
-+				}
-+			}
-+		}
- 		#else
--			// Older versions of FFmpeg (much sloppier)
-+			#if LIBAVFORMAT_VERSION_MAJOR >= 54
-+				// Write video packet (older than FFmpeg 3.2)
-+				error_code = avcodec_encode_video2(video_codec, &pkt, frame_final, &got_packet_ptr);
-+				if (error_code != 0 )
-+					cerr << "Frame AVERROR_EOF" << "\n";
-+				if (got_packet_ptr == 0 )
-+					cerr << "Frame gotpacket error" << "\n";
-+			#else
-+				// Write video packet (even older versions of FFmpeg)
-+				int video_outbuf_size = 200000;
-+				video_outbuf = (uint8_t*) av_malloc(200000);
- 
--			// Encode Picture and Write Frame
--			int video_outbuf_size = 200000;
--			video_outbuf = (uint8_t*) av_malloc(200000);
-+				/* encode the image */
-+				int out_size = avcodec_encode_video(video_codec, video_outbuf, video_outbuf_size, frame_final);
- 
--			/* encode the image */
--			int out_size = avcodec_encode_video(video_codec, video_outbuf, video_outbuf_size, frame_final);
-+				/* if zero size, it means the image was buffered */
-+				if (out_size > 0) {
-+					if(video_codec->coded_frame->key_frame)
-+						pkt.flags |= AV_PKT_FLAG_KEY;
-+					pkt.data= video_outbuf;
-+					pkt.size= out_size;
- 
--			/* if zero size, it means the image was buffered */
--			if (out_size > 0) {
--				if(video_codec->coded_frame->key_frame)
--					pkt.flags |= AV_PKT_FLAG_KEY;
--				pkt.data= video_outbuf;
--				pkt.size= out_size;
--
--				// got data back (so encode this frame)
--				got_packet_ptr = 1;
--			}
-+					// got data back (so encode this frame)
-+					got_packet_ptr = 1;
-+				}
-+			#endif
- 		#endif
- 
- 		/* if zero size, it means the image was buffered */
-@@ -1612,15 +1688,11 @@ void FFmpegWriter::OutputStreamInfo()
- // Init a collection of software rescalers (thread safe)
- void FFmpegWriter::InitScalers(int source_width, int source_height)
- {
--	// Get the codec
--	AVCodecContext *c;
--	c = video_st->codec;
--
- 	// Init software rescalers vector (many of them, one for each thread)
- 	for (int x = 0; x < num_of_rescalers; x++)
- 	{
- 		// Init the software scaler from FFMpeg
--		img_convert_ctx = sws_getContext(source_width, source_height, PIX_FMT_RGBA, info.width, info.height, c->pix_fmt, SWS_BILINEAR, NULL, NULL, NULL);
-+		img_convert_ctx = sws_getContext(source_width, source_height, PIX_FMT_RGBA, info.width, info.height, AV_GET_CODEC_PIXEL_FORMAT(video_st, video_st->codec), SWS_BILINEAR, NULL, NULL, NULL);
- 
- 		// Add rescaler to vector
- 		image_rescalers.push_back(img_convert_ctx);
-From 0db54c8a2c1becc6c0f56807e178c5ba93cda3c5 Mon Sep 17 00:00:00 2001
-From: Jonathan Thomas <jonathan at openshot.org>
-Date: Thu, 29 Mar 2018 01:29:10 -0500
-Subject: [PATCH] Fixing FFmpeg version breakage in FFmpegWriter
-
----
- src/FFmpegWriter.cpp | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp
-index 889e262..5f50b85 100644
---- a/src/FFmpegWriter.cpp
-+++ b/src/FFmpegWriter.cpp
-@@ -926,7 +926,7 @@ AVStream* FFmpegWriter::add_video_stream()
- 	 identically 1. */
- 	c->time_base.num = info.video_timebase.num;
- 	c->time_base.den = info.video_timebase.den;
--	#if LIBAVFORMAT_VERSION_MAJOR >= 55
-+	#if LIBAVFORMAT_VERSION_MAJOR >= 56
- 	c->framerate = av_inv_q(c->time_base);
- 	#endif
- 	st->avg_frame_rate = av_inv_q(c->time_base);
 --- a/src/FFmpegReader.cpp~	2018-04-29 21:29:04.000000000 +0200
 +++ b/src/FFmpegReader.cpp	2018-04-29 21:30:32.336155455 +0200
 @@ -941,7 +941,7 @@ void FFmpegReader::ProcessAudioPacket(in
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/libopenshot.git/commitdiff/bdb3122b46dff51d73d2cdbfc0d61281c20f6b84



More information about the pld-cvs-commit mailing list