From 7b86eff6d2dae6679f31b9b4923306cccf603458 Mon Sep 17 00:00:00 2001
From: Seven Du <dujinfang@gmail.com>
Date: Thu, 11 Jun 2020 10:04:05 +0800
Subject: [PATCH] [mod_av] fix some leaks in error cases

---
 src/mod/applications/mod_av/avformat.c        | 18 ++++---
 .../applications/mod_av/test/test_avformat.c  | 52 +++++++++++++++++++
 2 files changed, 63 insertions(+), 7 deletions(-)

diff --git a/src/mod/applications/mod_av/avformat.c b/src/mod/applications/mod_av/avformat.c
index 7c82913d55..f748968202 100644
--- a/src/mod/applications/mod_av/avformat.c
+++ b/src/mod/applications/mod_av/avformat.c
@@ -1173,7 +1173,7 @@ static switch_status_t open_input_file(av_file_context_t *context, switch_file_h
 	/** Get information on the input file (number of streams etc.). */
 	if ((error = avformat_find_stream_info(context->fc, opts ? &opts : NULL)) < 0) {
 		char ebuf[255] = "";
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Could not open find stream info (error '%s')\n", get_error_text(error, ebuf, sizeof(ebuf)));
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Could not find stream info in file: %s, error = %s)\n", filename, get_error_text(error, ebuf, sizeof(ebuf)));
 		if (opts) av_dict_free(&opts);
 		switch_goto_status(SWITCH_STATUS_FALSE, err);
 	}
@@ -1345,16 +1345,20 @@ GCC_DIAG_ON(deprecated-declarations)
 
 err:
 	if (context->fc) {
+		int nb_streams = context->fc->nb_streams;
+
+		if (nb_streams > 2) nb_streams = 2;
+
+		if (context->has_video) close_stream(context->fc, &context->video_st);
+
+		for (i = 0; i < nb_streams; i++) {
+			close_stream(context->fc, &context->audio_st[i]);
+		}
+
 		avformat_free_context(context->fc);
 		context->fc = NULL;
 	}
 
-	/*
-	if (context->has_video) close_stream(context->fc, &context->video_st);
-	if (context->has_audio) close_stream(context->fc, &context->audio_st);
-
-	if (context->fc) avformat_close_input(&context->fc);
-	*/
 	return status;
 }
 
diff --git a/src/mod/applications/mod_av/test/test_avformat.c b/src/mod/applications/mod_av/test/test_avformat.c
index 2304ca8c59..2c8949472f 100644
--- a/src/mod/applications/mod_av/test/test_avformat.c
+++ b/src/mod/applications/mod_av/test/test_avformat.c
@@ -197,6 +197,58 @@ FST_CORE_BEGIN("conf")
 		}
 		FST_TEST_END()
 
+		FST_TEST_BEGIN(avformat_test_read_err)
+		{
+			char *path = "$$-non-exist-file.mp4";
+			switch_status_t status;
+			switch_file_handle_t fh = { 0 };
+			uint32_t flags = SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT | SWITCH_FILE_FLAG_VIDEO;
+
+			status = switch_core_file_open(&fh, path, 1, 8000, flags, fst_pool);
+			fst_check(status == SWITCH_STATUS_GENERR);
+		}
+		FST_TEST_END()
+
+		FST_TEST_BEGIN(avformat_test_read_ok)
+		{
+			char path[1024];
+			switch_status_t status;
+			switch_file_handle_t fh = { 0 };
+			uint8_t data[SAMPLES * 2] = { 0 };
+			switch_frame_t frame = { 0 };
+			switch_size_t len = SAMPLES;
+			uint32_t flags = SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT | SWITCH_FILE_FLAG_VIDEO;
+
+			frame.data = data;
+
+			sprintf(path, "%s%s%s", SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR, "../test_RGB.mp4");
+			status = switch_core_file_open(&fh, path, 1, 8000, flags, fst_pool);
+			fst_requires(status == SWITCH_STATUS_SUCCESS);
+			fst_requires(switch_test_flag(&fh, SWITCH_FILE_OPEN));
+
+			while (1) {
+				status = switch_core_file_read(&fh, data, &len);
+				if (status != SWITCH_STATUS_SUCCESS) break;
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%d\n", len);
+				// fst_check(len == SAMPLES);
+				status = switch_core_file_read_video(&fh, &frame, SVR_FLUSH);
+
+				if (status == SWITCH_STATUS_BREAK) {
+					switch_yield(20000);
+					continue;
+				}
+
+				if (status != SWITCH_STATUS_SUCCESS) {
+					break;
+				}
+
+				switch_img_free(&frame.img);
+				switch_yield(20000);
+			}
+
+			switch_core_file_close(&fh);
+		}
+		FST_TEST_END()
 
 		FST_TEARDOWN_BEGIN()
 		{