瀏覽代碼

obs-ffmpeg: Use av_packet_alloc instead of av_init_packet

sizeof(AVPacket) being a part of the public ABI is deprecated. once
av_init_packet() is removed, new packets will only be able to be
allocated with av_packet_alloc().
In ffmpeg-mux, ffmpeg-vaapi, and obs-ffmpeg-nvenc, AVPacket is allocated
at the initialization to avoid frequent allocation of AVPacket.

Includes changes to win-dshow.
Norihiro Kamae 3 年之前
父節點
當前提交
ba68eda590

+ 12 - 10
plugins/obs-ffmpeg/ffmpeg-mux/ffmpeg-mux.c

@@ -119,6 +119,7 @@ struct ffmpeg_mux {
 	AVFormatContext *output;
 	AVFormatContext *output;
 	AVStream *video_stream;
 	AVStream *video_stream;
 	AVCodecContext *video_ctx;
 	AVCodecContext *video_ctx;
+	AVPacket *packet;
 	struct audio_info *audio_infos;
 	struct audio_info *audio_infos;
 	struct main_params params;
 	struct main_params params;
 	struct audio_params *audio;
 	struct audio_params *audio;
@@ -181,6 +182,8 @@ static void ffmpeg_mux_free(struct ffmpeg_mux *ffm)
 
 
 	dstr_free(&ffm->params.printable_file);
 	dstr_free(&ffm->params.printable_file);
 
 
+	av_packet_free(&ffm->packet);
+
 	memset(ffm, 0, sizeof(*ffm));
 	memset(ffm, 0, sizeof(*ffm));
 }
 }
 
 
@@ -717,6 +720,8 @@ static int ffmpeg_mux_init_internal(struct ffmpeg_mux *ffm, int argc,
 	if (!ffmpeg_mux_get_extra_data(ffm))
 	if (!ffmpeg_mux_get_extra_data(ffm))
 		return FFM_ERROR;
 		return FFM_ERROR;
 
 
+	ffm->packet = av_packet_alloc();
+
 	/* ffmpeg does not have a way of telling what's supported
 	/* ffmpeg does not have a way of telling what's supported
 	 * for a given output format, so we try each possibility */
 	 * for a given output format, so we try each possibility */
 	return ffmpeg_mux_init_context(ffm);
 	return ffmpeg_mux_init_context(ffm);
@@ -786,7 +791,6 @@ static inline bool ffmpeg_mux_packet(struct ffmpeg_mux *ffm, uint8_t *buf,
 				     struct ffm_packet_info *info)
 				     struct ffm_packet_info *info)
 {
 {
 	int idx = get_index(ffm, info);
 	int idx = get_index(ffm, info);
-	AVPacket packet = {0};
 
 
 	/* The muxer might not support video/audio, or multiple audio tracks */
 	/* The muxer might not support video/audio, or multiple audio tracks */
 	if (idx == -1) {
 	if (idx == -1) {
@@ -796,18 +800,16 @@ static inline bool ffmpeg_mux_packet(struct ffmpeg_mux *ffm, uint8_t *buf,
 	const AVRational codec_time_base =
 	const AVRational codec_time_base =
 		get_codec_context(ffm, info)->time_base;
 		get_codec_context(ffm, info)->time_base;
 
 
-	av_init_packet(&packet);
-
-	packet.data = buf;
-	packet.size = (int)info->size;
-	packet.stream_index = idx;
-	packet.pts = rescale_ts(ffm, codec_time_base, info->pts, idx);
-	packet.dts = rescale_ts(ffm, codec_time_base, info->dts, idx);
+	ffm->packet->data = buf;
+	ffm->packet->size = (int)info->size;
+	ffm->packet->stream_index = idx;
+	ffm->packet->pts = rescale_ts(ffm, codec_time_base, info->pts, idx);
+	ffm->packet->dts = rescale_ts(ffm, codec_time_base, info->dts, idx);
 
 
 	if (info->keyframe)
 	if (info->keyframe)
-		packet.flags = AV_PKT_FLAG_KEY;
+		ffm->packet->flags = AV_PKT_FLAG_KEY;
 
 
-	int ret = av_interleaved_write_frame(ffm->output, &packet);
+	int ret = av_interleaved_write_frame(ffm->output, ffm->packet);
 
 
 	if (ret < 0) {
 	if (ret < 0) {
 		fprintf(stderr, "av_interleaved_write_frame failed: %d: %s\n",
 		fprintf(stderr, "av_interleaved_write_frame failed: %d: %s\n",

+ 36 - 29
plugins/obs-ffmpeg/obs-ffmpeg-nvenc.c

@@ -43,6 +43,8 @@ struct nvenc_encoder {
 	AVCodec *nvenc;
 	AVCodec *nvenc;
 	AVCodecContext *context;
 	AVCodecContext *context;
 
 
+	AVPacket *packet;
+
 	AVFrame *vframe;
 	AVFrame *vframe;
 
 
 	DARRAY(uint8_t) buffer;
 	DARRAY(uint8_t) buffer;
@@ -163,6 +165,8 @@ static bool nvenc_init_codec(struct nvenc_encoder *enc, bool psycho_aq)
 		return false;
 		return false;
 	}
 	}
 
 
+	enc->packet = av_packet_alloc();
+
 	enc->initialized = true;
 	enc->initialized = true;
 	return true;
 	return true;
 }
 }
@@ -318,29 +322,33 @@ static bool nvenc_reconfigure(void *data, obs_data_t *settings)
 	return true;
 	return true;
 }
 }
 
 
-static void nvenc_destroy(void *data)
+static inline void flush_remaining_packets(struct nvenc_encoder *enc)
 {
 {
-	struct nvenc_encoder *enc = data;
+	int r_pkt = 1;
 
 
-	if (enc->initialized) {
-		AVPacket pkt = {0};
-		int r_pkt = 1;
-
-		while (r_pkt) {
+	while (r_pkt) {
 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
-			if (avcodec_receive_packet(enc->context, &pkt) < 0)
-				break;
+		if (avcodec_receive_packet(enc->context, enc->packet) < 0)
+			break;
 #else
 #else
-			if (avcodec_encode_video2(enc->context, &pkt, NULL,
-						  &r_pkt) < 0)
-				break;
+		if (avcodec_encode_video2(enc->context, enc->packet, NULL,
+					  &r_pkt) < 0)
+			break;
 #endif
 #endif
 
 
-			if (r_pkt)
-				av_packet_unref(&pkt);
-		}
+		if (r_pkt)
+			av_packet_unref(enc->packet);
 	}
 	}
+}
 
 
+static void nvenc_destroy(void *data)
+{
+	struct nvenc_encoder *enc = data;
+
+	if (enc->initialized)
+		flush_remaining_packets(enc);
+
+	av_packet_free(&enc->packet);
 	avcodec_close(enc->context);
 	avcodec_close(enc->context);
 	av_frame_unref(enc->vframe);
 	av_frame_unref(enc->vframe);
 	av_frame_free(&enc->vframe);
 	av_frame_free(&enc->vframe);
@@ -436,26 +444,23 @@ static bool nvenc_encode(void *data, struct encoder_frame *frame,
 			 struct encoder_packet *packet, bool *received_packet)
 			 struct encoder_packet *packet, bool *received_packet)
 {
 {
 	struct nvenc_encoder *enc = data;
 	struct nvenc_encoder *enc = data;
-	AVPacket av_pkt = {0};
 	int got_packet;
 	int got_packet;
 	int ret;
 	int ret;
 
 
-	av_init_packet(&av_pkt);
-
 	copy_data(enc->vframe, frame, enc->height, enc->context->pix_fmt);
 	copy_data(enc->vframe, frame, enc->height, enc->context->pix_fmt);
 
 
 	enc->vframe->pts = frame->pts;
 	enc->vframe->pts = frame->pts;
 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
 	ret = avcodec_send_frame(enc->context, enc->vframe);
 	ret = avcodec_send_frame(enc->context, enc->vframe);
 	if (ret == 0)
 	if (ret == 0)
-		ret = avcodec_receive_packet(enc->context, &av_pkt);
+		ret = avcodec_receive_packet(enc->context, enc->packet);
 
 
 	got_packet = (ret == 0);
 	got_packet = (ret == 0);
 
 
 	if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
 	if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
 		ret = 0;
 		ret = 0;
 #else
 #else
-	ret = avcodec_encode_video2(enc->context, &av_pkt, enc->vframe,
+	ret = avcodec_encode_video2(enc->context, enc->packet, enc->vframe,
 				    &got_packet);
 				    &got_packet);
 #endif
 #endif
 	if (ret < 0) {
 	if (ret < 0) {
@@ -463,25 +468,27 @@ static bool nvenc_encode(void *data, struct encoder_frame *frame,
 		return false;
 		return false;
 	}
 	}
 
 
-	if (got_packet && av_pkt.size) {
+	if (got_packet && enc->packet->size) {
 		if (enc->first_packet) {
 		if (enc->first_packet) {
 			uint8_t *new_packet;
 			uint8_t *new_packet;
 			size_t size;
 			size_t size;
 
 
 			enc->first_packet = false;
 			enc->first_packet = false;
-			obs_extract_avc_headers(av_pkt.data, av_pkt.size,
-						&new_packet, &size,
-						&enc->header, &enc->header_size,
-						&enc->sei, &enc->sei_size);
+			obs_extract_avc_headers(enc->packet->data,
+						enc->packet->size, &new_packet,
+						&size, &enc->header,
+						&enc->header_size, &enc->sei,
+						&enc->sei_size);
 
 
 			da_copy_array(enc->buffer, new_packet, size);
 			da_copy_array(enc->buffer, new_packet, size);
 			bfree(new_packet);
 			bfree(new_packet);
 		} else {
 		} else {
-			da_copy_array(enc->buffer, av_pkt.data, av_pkt.size);
+			da_copy_array(enc->buffer, enc->packet->data,
+				      enc->packet->size);
 		}
 		}
 
 
-		packet->pts = av_pkt.pts;
-		packet->dts = av_pkt.dts;
+		packet->pts = enc->packet->pts;
+		packet->dts = enc->packet->dts;
 		packet->data = enc->buffer.array;
 		packet->data = enc->buffer.array;
 		packet->size = enc->buffer.num;
 		packet->size = enc->buffer.num;
 		packet->type = OBS_ENCODER_VIDEO;
 		packet->type = OBS_ENCODER_VIDEO;
@@ -491,7 +498,7 @@ static bool nvenc_encode(void *data, struct encoder_frame *frame,
 		*received_packet = false;
 		*received_packet = false;
 	}
 	}
 
 
-	av_packet_unref(&av_pkt);
+	av_packet_unref(enc->packet);
 	return true;
 	return true;
 }
 }
 
 

+ 48 - 37
plugins/obs-ffmpeg/obs-ffmpeg-output.c

@@ -48,7 +48,7 @@ struct ffmpeg_output {
 	os_sem_t *write_sem;
 	os_sem_t *write_sem;
 	os_event_t *stop_event;
 	os_event_t *stop_event;
 
 
-	DARRAY(AVPacket) packets;
+	DARRAY(AVPacket *) packets;
 };
 };
 
 
 /* ------------------------------------------------------------------------- */
 /* ------------------------------------------------------------------------- */
@@ -740,11 +740,9 @@ static void receive_video(void *param, struct video_data *frame)
 		return;
 		return;
 
 
 	AVCodecContext *context = data->video_ctx;
 	AVCodecContext *context = data->video_ctx;
-	AVPacket packet = {0};
+	AVPacket *packet = NULL;
 	int ret = 0, got_packet;
 	int ret = 0, got_packet;
 
 
-	av_init_packet(&packet);
-
 	if (!output->video_start_ts)
 	if (!output->video_start_ts)
 		output->video_start_ts = frame->timestamp;
 		output->video_start_ts = frame->timestamp;
 	if (!data->start_timestamp)
 	if (!data->start_timestamp)
@@ -766,15 +764,19 @@ static void receive_video(void *param, struct video_data *frame)
 	else
 	else
 		copy_data(data->vframe, frame, context->height,
 		copy_data(data->vframe, frame, context->height,
 			  context->pix_fmt);
 			  context->pix_fmt);
+
+	packet = av_packet_alloc();
+
 #if LIBAVFORMAT_VERSION_MAJOR < 58
 #if LIBAVFORMAT_VERSION_MAJOR < 58
 	if (data->output->flags & AVFMT_RAWPICTURE) {
 	if (data->output->flags & AVFMT_RAWPICTURE) {
-		packet.flags |= AV_PKT_FLAG_KEY;
-		packet.stream_index = data->video->index;
-		packet.data = data->vframe->data[0];
-		packet.size = sizeof(AVPicture);
+		packet->flags |= AV_PKT_FLAG_KEY;
+		packet->stream_index = data->video->index;
+		packet->data = data->vframe->data[0];
+		packet->size = sizeof(AVPicture);
 
 
 		pthread_mutex_lock(&output->write_mutex);
 		pthread_mutex_lock(&output->write_mutex);
 		da_push_back(output->packets, &packet);
 		da_push_back(output->packets, &packet);
+		packet = NULL;
 		pthread_mutex_unlock(&output->write_mutex);
 		pthread_mutex_unlock(&output->write_mutex);
 		os_sem_post(output->write_sem);
 		os_sem_post(output->write_sem);
 
 
@@ -784,15 +786,14 @@ static void receive_video(void *param, struct video_data *frame)
 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
 		ret = avcodec_send_frame(context, data->vframe);
 		ret = avcodec_send_frame(context, data->vframe);
 		if (ret == 0)
 		if (ret == 0)
-			ret = avcodec_receive_packet(context, &packet);
+			ret = avcodec_receive_packet(context, packet);
 
 
 		got_packet = (ret == 0);
 		got_packet = (ret == 0);
 
 
 		if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
 		if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
 			ret = 0;
 			ret = 0;
 #else
 #else
-	ret = avcodec_encode_video2(context, &packet, data->vframe,
-				    &got_packet);
+	ret = avcodec_encode_video2(context, packet, data->vframe, &got_packet);
 #endif
 #endif
 		if (ret < 0) {
 		if (ret < 0) {
 			blog(LOG_WARNING,
 			blog(LOG_WARNING,
@@ -800,20 +801,21 @@ static void receive_video(void *param, struct video_data *frame)
 			     "video: %s",
 			     "video: %s",
 			     av_err2str(ret));
 			     av_err2str(ret));
 			//FIXME: stop the encode with an error
 			//FIXME: stop the encode with an error
-			return;
+			goto fail;
 		}
 		}
 
 
-		if (!ret && got_packet && packet.size) {
-			packet.pts = rescale_ts(packet.pts, context,
-						data->video->time_base);
-			packet.dts = rescale_ts(packet.dts, context,
-						data->video->time_base);
-			packet.duration = (int)av_rescale_q(
-				packet.duration, context->time_base,
+		if (!ret && got_packet && packet->size) {
+			packet->pts = rescale_ts(packet->pts, context,
+						 data->video->time_base);
+			packet->dts = rescale_ts(packet->dts, context,
+						 data->video->time_base);
+			packet->duration = (int)av_rescale_q(
+				packet->duration, context->time_base,
 				data->video->time_base);
 				data->video->time_base);
 
 
 			pthread_mutex_lock(&output->write_mutex);
 			pthread_mutex_lock(&output->write_mutex);
 			da_push_back(output->packets, &packet);
 			da_push_back(output->packets, &packet);
+			packet = NULL;
 			pthread_mutex_unlock(&output->write_mutex);
 			pthread_mutex_unlock(&output->write_mutex);
 			os_sem_post(output->write_sem);
 			os_sem_post(output->write_sem);
 		} else {
 		} else {
@@ -829,6 +831,9 @@ static void receive_video(void *param, struct video_data *frame)
 	}
 	}
 
 
 	data->total_frames++;
 	data->total_frames++;
+
+fail:
+	av_packet_free(&packet);
 }
 }
 
 
 static void encode_audio(struct ffmpeg_output *output, int idx,
 static void encode_audio(struct ffmpeg_output *output, int idx,
@@ -836,7 +841,7 @@ static void encode_audio(struct ffmpeg_output *output, int idx,
 {
 {
 	struct ffmpeg_data *data = &output->ff_data;
 	struct ffmpeg_data *data = &output->ff_data;
 
 
-	AVPacket packet = {0};
+	AVPacket *packet = NULL;
 	int ret, got_packet;
 	int ret, got_packet;
 	size_t total_size = data->frame_size * block_size * context->channels;
 	size_t total_size = data->frame_size * block_size * context->channels;
 
 
@@ -860,42 +865,48 @@ static void encode_audio(struct ffmpeg_output *output, int idx,
 
 
 	data->total_samples[idx] += data->frame_size;
 	data->total_samples[idx] += data->frame_size;
 
 
+	packet = av_packet_alloc();
+
 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
 	ret = avcodec_send_frame(context, data->aframe[idx]);
 	ret = avcodec_send_frame(context, data->aframe[idx]);
 	if (ret == 0)
 	if (ret == 0)
-		ret = avcodec_receive_packet(context, &packet);
+		ret = avcodec_receive_packet(context, packet);
 
 
 	got_packet = (ret == 0);
 	got_packet = (ret == 0);
 
 
 	if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
 	if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
 		ret = 0;
 		ret = 0;
 #else
 #else
-	ret = avcodec_encode_audio2(context, &packet, data->aframe[idx],
+	ret = avcodec_encode_audio2(context, packet, data->aframe[idx],
 				    &got_packet);
 				    &got_packet);
 #endif
 #endif
 	if (ret < 0) {
 	if (ret < 0) {
 		blog(LOG_WARNING, "encode_audio: Error encoding audio: %s",
 		blog(LOG_WARNING, "encode_audio: Error encoding audio: %s",
 		     av_err2str(ret));
 		     av_err2str(ret));
 		//FIXME: stop the encode with an error
 		//FIXME: stop the encode with an error
-		return;
+		goto fail;
 	}
 	}
 
 
 	if (!got_packet)
 	if (!got_packet)
-		return;
+		goto fail;
 
 
-	packet.pts = rescale_ts(packet.pts, context,
-				data->audio_infos[idx].stream->time_base);
-	packet.dts = rescale_ts(packet.dts, context,
-				data->audio_infos[idx].stream->time_base);
-	packet.duration =
-		(int)av_rescale_q(packet.duration, context->time_base,
+	packet->pts = rescale_ts(packet->pts, context,
+				 data->audio_infos[idx].stream->time_base);
+	packet->dts = rescale_ts(packet->dts, context,
+				 data->audio_infos[idx].stream->time_base);
+	packet->duration =
+		(int)av_rescale_q(packet->duration, context->time_base,
 				  data->audio_infos[idx].stream->time_base);
 				  data->audio_infos[idx].stream->time_base);
-	packet.stream_index = data->audio_infos[idx].stream->index;
+	packet->stream_index = data->audio_infos[idx].stream->index;
 
 
 	pthread_mutex_lock(&output->write_mutex);
 	pthread_mutex_lock(&output->write_mutex);
 	da_push_back(output->packets, &packet);
 	da_push_back(output->packets, &packet);
 	pthread_mutex_unlock(&output->write_mutex);
 	pthread_mutex_unlock(&output->write_mutex);
 	os_sem_post(output->write_sem);
 	os_sem_post(output->write_sem);
+
+	return;
+fail:
+	av_packet_free(&packet);
 }
 }
 
 
 /* Given a bitmask for the selected tracks and the mix index,
 /* Given a bitmask for the selected tracks and the mix index,
@@ -978,7 +989,7 @@ static uint64_t get_packet_sys_dts(struct ffmpeg_output *output,
 
 
 static int process_packet(struct ffmpeg_output *output)
 static int process_packet(struct ffmpeg_output *output)
 {
 {
-	AVPacket packet;
+	AVPacket *packet;
 	bool new_packet = false;
 	bool new_packet = false;
 	int ret;
 	int ret;
 
 
@@ -999,16 +1010,16 @@ static int process_packet(struct ffmpeg_output *output)
 			packet.stream_index, output->packets.num);*/
 			packet.stream_index, output->packets.num);*/
 
 
 	if (stopping(output)) {
 	if (stopping(output)) {
-		uint64_t sys_ts = get_packet_sys_dts(output, &packet);
+		uint64_t sys_ts = get_packet_sys_dts(output, packet);
 		if (sys_ts >= output->stop_ts)
 		if (sys_ts >= output->stop_ts)
 			return 0;
 			return 0;
 	}
 	}
 
 
-	output->total_bytes += packet.size;
+	output->total_bytes += packet->size;
 
 
-	ret = av_interleaved_write_frame(output->ff_data.output, &packet);
+	ret = av_interleaved_write_frame(output->ff_data.output, packet);
 	if (ret < 0) {
 	if (ret < 0) {
-		av_free_packet(&packet);
+		av_packet_free(&packet);
 		ffmpeg_log_error(LOG_WARNING, &output->ff_data,
 		ffmpeg_log_error(LOG_WARNING, &output->ff_data,
 				 "process_packet: Error writing packet: %s",
 				 "process_packet: Error writing packet: %s",
 				 av_err2str(ret));
 				 av_err2str(ret));
@@ -1243,7 +1254,7 @@ static void ffmpeg_deactivate(struct ffmpeg_output *output)
 	pthread_mutex_lock(&output->write_mutex);
 	pthread_mutex_lock(&output->write_mutex);
 
 
 	for (size_t i = 0; i < output->packets.num; i++)
 	for (size_t i = 0; i < output->packets.num; i++)
-		av_free_packet(output->packets.array + i);
+		av_packet_free(output->packets.array + i);
 	da_free(output->packets);
 	da_free(output->packets);
 
 
 	pthread_mutex_unlock(&output->write_mutex);
 	pthread_mutex_unlock(&output->write_mutex);

+ 36 - 29
plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c

@@ -57,6 +57,8 @@ struct vaapi_encoder {
 	AVCodec *vaapi;
 	AVCodec *vaapi;
 	AVCodecContext *context;
 	AVCodecContext *context;
 
 
+	AVPacket *packet;
+
 	AVFrame *vframe;
 	AVFrame *vframe;
 
 
 	DARRAY(uint8_t) buffer;
 	DARRAY(uint8_t) buffer;
@@ -159,6 +161,8 @@ static bool vaapi_init_codec(struct vaapi_encoder *enc, const char *path)
 		return false;
 		return false;
 	}
 	}
 
 
+	enc->packet = av_packet_alloc();
+
 	enc->initialized = true;
 	enc->initialized = true;
 	return true;
 	return true;
 }
 }
@@ -298,29 +302,33 @@ static bool vaapi_update(void *data, obs_data_t *settings)
 	return vaapi_init_codec(enc, device);
 	return vaapi_init_codec(enc, device);
 }
 }
 
 
-static void vaapi_destroy(void *data)
+static inline void flush_remaining_packets(struct vaapi_encoder *enc)
 {
 {
-	struct vaapi_encoder *enc = data;
+	int r_pkt = 1;
 
 
-	if (enc->initialized) {
-		AVPacket pkt = {0};
-		int r_pkt = 1;
-
-		while (r_pkt) {
+	while (r_pkt) {
 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
-			if (avcodec_receive_packet(enc->context, &pkt) < 0)
-				break;
+		if (avcodec_receive_packet(enc->context, enc->packet) < 0)
+			break;
 #else
 #else
-			if (avcodec_encode_video2(enc->context, &pkt, NULL,
-						  &r_pkt) < 0)
-				break;
+		if (avcodec_encode_video2(enc->context, enc->packet, NULL,
+					  &r_pkt) < 0)
+			break;
 #endif
 #endif
 
 
-			if (r_pkt)
-				av_packet_unref(&pkt);
-		}
+		if (r_pkt)
+			av_packet_unref(enc->packet);
 	}
 	}
+}
 
 
+static void vaapi_destroy(void *data)
+{
+	struct vaapi_encoder *enc = data;
+
+	if (enc->initialized)
+		flush_remaining_packets(enc);
+
+	av_packet_free(&enc->packet);
 	avcodec_close(enc->context);
 	avcodec_close(enc->context);
 	av_frame_unref(enc->vframe);
 	av_frame_unref(enc->vframe);
 	av_frame_free(&enc->vframe);
 	av_frame_free(&enc->vframe);
@@ -405,7 +413,6 @@ static bool vaapi_encode(void *data, struct encoder_frame *frame,
 {
 {
 	struct vaapi_encoder *enc = data;
 	struct vaapi_encoder *enc = data;
 	AVFrame *hwframe = NULL;
 	AVFrame *hwframe = NULL;
-	AVPacket av_pkt;
 	int got_packet;
 	int got_packet;
 	int ret;
 	int ret;
 
 
@@ -443,19 +450,17 @@ static bool vaapi_encode(void *data, struct encoder_frame *frame,
 		goto fail;
 		goto fail;
 	}
 	}
 
 
-	av_init_packet(&av_pkt);
-
 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
 	ret = avcodec_send_frame(enc->context, hwframe);
 	ret = avcodec_send_frame(enc->context, hwframe);
 	if (ret == 0)
 	if (ret == 0)
-		ret = avcodec_receive_packet(enc->context, &av_pkt);
+		ret = avcodec_receive_packet(enc->context, enc->packet);
 
 
 	got_packet = (ret == 0);
 	got_packet = (ret == 0);
 
 
 	if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
 	if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
 		ret = 0;
 		ret = 0;
 #else
 #else
-	ret = avcodec_encode_video2(enc->context, &av_pkt, hwframe,
+	ret = avcodec_encode_video2(enc->context, enc->packet, hwframe,
 				    &got_packet);
 				    &got_packet);
 #endif
 #endif
 	if (ret < 0) {
 	if (ret < 0) {
@@ -463,25 +468,27 @@ static bool vaapi_encode(void *data, struct encoder_frame *frame,
 		goto fail;
 		goto fail;
 	}
 	}
 
 
-	if (got_packet && av_pkt.size) {
+	if (got_packet && enc->packet->size) {
 		if (enc->first_packet) {
 		if (enc->first_packet) {
 			uint8_t *new_packet;
 			uint8_t *new_packet;
 			size_t size;
 			size_t size;
 
 
 			enc->first_packet = false;
 			enc->first_packet = false;
-			obs_extract_avc_headers(av_pkt.data, av_pkt.size,
-						&new_packet, &size,
-						&enc->header, &enc->header_size,
-						&enc->sei, &enc->sei_size);
+			obs_extract_avc_headers(enc->packet->data,
+						enc->packet->size, &new_packet,
+						&size, &enc->header,
+						&enc->header_size, &enc->sei,
+						&enc->sei_size);
 
 
 			da_copy_array(enc->buffer, new_packet, size);
 			da_copy_array(enc->buffer, new_packet, size);
 			bfree(new_packet);
 			bfree(new_packet);
 		} else {
 		} else {
-			da_copy_array(enc->buffer, av_pkt.data, av_pkt.size);
+			da_copy_array(enc->buffer, enc->packet->data,
+				      enc->packet->size);
 		}
 		}
 
 
-		packet->pts = av_pkt.pts;
-		packet->dts = av_pkt.dts;
+		packet->pts = enc->packet->pts;
+		packet->dts = enc->packet->dts;
 		packet->data = enc->buffer.array;
 		packet->data = enc->buffer.array;
 		packet->size = enc->buffer.num;
 		packet->size = enc->buffer.num;
 		packet->type = OBS_ENCODER_VIDEO;
 		packet->type = OBS_ENCODER_VIDEO;
@@ -491,7 +498,7 @@ static bool vaapi_encode(void *data, struct encoder_frame *frame,
 		*received_packet = false;
 		*received_packet = false;
 	}
 	}
 
 
-	av_packet_unref(&av_pkt);
+	av_packet_unref(enc->packet);
 	av_frame_free(&hwframe);
 	av_frame_free(&hwframe);
 	return true;
 	return true;
 
 

+ 21 - 18
plugins/win-dshow/ffmpeg-decode.c

@@ -225,7 +225,6 @@ bool ffmpeg_decode_audio(struct ffmpeg_decode *decode, uint8_t *data,
 			 size_t size, struct obs_source_audio *audio,
 			 size_t size, struct obs_source_audio *audio,
 			 bool *got_output)
 			 bool *got_output)
 {
 {
-	AVPacket packet = {0};
 	int got_frame = false;
 	int got_frame = false;
 	int ret = 0;
 	int ret = 0;
 
 
@@ -233,18 +232,21 @@ bool ffmpeg_decode_audio(struct ffmpeg_decode *decode, uint8_t *data,
 
 
 	copy_data(decode, data, size);
 	copy_data(decode, data, size);
 
 
-	av_init_packet(&packet);
-	packet.data = decode->packet_buffer;
-	packet.size = (int)size;
-
 	if (!decode->frame) {
 	if (!decode->frame) {
 		decode->frame = av_frame_alloc();
 		decode->frame = av_frame_alloc();
 		if (!decode->frame)
 		if (!decode->frame)
 			return false;
 			return false;
 	}
 	}
 
 
-	if (data && size)
-		ret = avcodec_send_packet(decode->decoder, &packet);
+	if (data && size) {
+		AVPacket *packet = av_packet_alloc();
+		packet->data = decode->packet_buffer;
+		packet->size = (int)size;
+
+		ret = avcodec_send_packet(decode->decoder, packet);
+
+		av_packet_free(&packet);
+	}
 	if (ret == 0)
 	if (ret == 0)
 		ret = avcodec_receive_frame(decode->decoder, decode->frame);
 		ret = avcodec_receive_frame(decode->decoder, decode->frame);
 
 
@@ -297,7 +299,6 @@ bool ffmpeg_decode_video(struct ffmpeg_decode *decode, uint8_t *data,
 			 enum video_range_type range,
 			 enum video_range_type range,
 			 struct obs_source_frame2 *frame, bool *got_output)
 			 struct obs_source_frame2 *frame, bool *got_output)
 {
 {
-	AVPacket packet = {0};
 	int got_frame = false;
 	int got_frame = false;
 	AVFrame *out_frame;
 	AVFrame *out_frame;
 	int ret;
 	int ret;
@@ -306,15 +307,6 @@ bool ffmpeg_decode_video(struct ffmpeg_decode *decode, uint8_t *data,
 
 
 	copy_data(decode, data, size);
 	copy_data(decode, data, size);
 
 
-	av_init_packet(&packet);
-	packet.data = decode->packet_buffer;
-	packet.size = (int)size;
-	packet.pts = *ts;
-
-	if (decode->codec->id == AV_CODEC_ID_H264 &&
-	    obs_avc_keyframe(data, size))
-		packet.flags |= AV_PKT_FLAG_KEY;
-
 	if (!decode->frame) {
 	if (!decode->frame) {
 		decode->frame = av_frame_alloc();
 		decode->frame = av_frame_alloc();
 		if (!decode->frame)
 		if (!decode->frame)
@@ -329,11 +321,22 @@ bool ffmpeg_decode_video(struct ffmpeg_decode *decode, uint8_t *data,
 
 
 	out_frame = decode->hw ? decode->hw_frame : decode->frame;
 	out_frame = decode->hw ? decode->hw_frame : decode->frame;
 
 
-	ret = avcodec_send_packet(decode->decoder, &packet);
+	AVPacket *packet = av_packet_alloc();
+	packet->data = decode->packet_buffer;
+	packet->size = (int)size;
+	packet->pts = *ts;
+
+	if (decode->codec->id == AV_CODEC_ID_H264 &&
+	    obs_avc_keyframe(data, size))
+		packet->flags |= AV_PKT_FLAG_KEY;
+
+	ret = avcodec_send_packet(decode->decoder, packet);
 	if (ret == 0) {
 	if (ret == 0) {
 		ret = avcodec_receive_frame(decode->decoder, out_frame);
 		ret = avcodec_receive_frame(decode->decoder, out_frame);
 	}
 	}
 
 
+	av_packet_free(&packet);
+
 	got_frame = (ret == 0);
 	got_frame = (ret == 0);
 
 
 	if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
 	if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))