1
0
Эх сурвалжийг харах

deps/media-playback: New AVPacket pattern

FFmpeg has deprecated stack-allocated AVPacket objects, so make a pool
and use the new pattern instead.
jpark37 3 жил өмнө
parent
commit
d528f6cafa

+ 27 - 43
deps/media-playback/media-playback/decode.c

@@ -195,17 +195,19 @@ bool mp_decode_init(mp_media_t *m, enum AVMediaType type, bool hw)
 	return true;
 }
 
+extern void mp_media_free_packet(mp_media_t *m, AVPacket *pkt);
+
 void mp_decode_clear_packets(struct mp_decode *d)
 {
-	if (d->packet_pending) {
-		av_packet_unref(&d->orig_pkt);
-		d->packet_pending = false;
+	if (d->pkt) {
+		mp_media_free_packet(d->m, d->pkt);
+		d->pkt = NULL;
 	}
 
 	while (d->packets.size) {
-		AVPacket pkt;
+		AVPacket *pkt;
 		circlebuf_pop_front(&d->packets, &pkt, sizeof(pkt));
-		av_packet_unref(&pkt);
+		mp_media_free_packet(d->m, pkt);
 	}
 }
 
@@ -241,7 +243,7 @@ void mp_decode_free(struct mp_decode *d)
 
 void mp_decode_push_packet(struct mp_decode *decode, AVPacket *packet)
 {
-	circlebuf_push_back(&decode->packets, packet, sizeof(*packet));
+	circlebuf_push_back(&decode->packets, &packet, sizeof(packet));
 }
 
 static inline int64_t get_estimated_duration(struct mp_decode *d,
@@ -269,7 +271,6 @@ static int decode_packet(struct mp_decode *d, int *got_frame)
 	int ret;
 	*got_frame = 0;
 
-#ifdef USE_NEW_FFMPEG_DECODE_API
 	ret = avcodec_receive_frame(d->decoder, d->in_frame);
 	if (ret != 0 && ret != AVERROR(EAGAIN)) {
 		if (ret == AVERROR_EOF)
@@ -278,7 +279,10 @@ static int decode_packet(struct mp_decode *d, int *got_frame)
 	}
 
 	if (ret != 0) {
-		ret = avcodec_send_packet(d->decoder, &d->pkt);
+		if (!d->pkt)
+			return 0;
+
+		ret = avcodec_send_packet(d->decoder, d->pkt);
 		if (ret != 0 && ret != AVERROR(EAGAIN)) {
 			if (ret == AVERROR_EOF)
 				ret = 0;
@@ -293,22 +297,12 @@ static int decode_packet(struct mp_decode *d, int *got_frame)
 		}
 
 		*got_frame = (ret == 0);
-		ret = d->pkt.size;
+		ret = d->pkt->size;
 	} else {
 		ret = 0;
 		*got_frame = 1;
 	}
 
-#else
-	if (d->audio) {
-		ret = avcodec_decode_audio4(d->decoder, d->in_frame, got_frame,
-					    &d->pkt);
-	} else {
-		ret = avcodec_decode_video2(d->decoder, d->in_frame, got_frame,
-					    &d->pkt);
-	}
-#endif
-
 #ifdef USE_NEW_HARDWARE_CODEC_METHOD
 	if (*got_frame && d->hw) {
 		if (d->hw_frame->format != d->hw_format) {
@@ -340,19 +334,13 @@ bool mp_decode_next(struct mp_decode *d)
 		return true;
 
 	while (!d->frame_ready) {
-		if (!d->packet_pending) {
+		if (!d->pkt) {
 			if (!d->packets.size) {
-				if (eof) {
-					d->pkt.data = NULL;
-					d->pkt.size = 0;
-				} else {
+				if (!eof)
 					return true;
-				}
 			} else {
-				circlebuf_pop_front(&d->packets, &d->orig_pkt,
-						    sizeof(d->orig_pkt));
-				d->pkt = d->orig_pkt;
-				d->packet_pending = true;
+				circlebuf_pop_front(&d->packets, &d->pkt,
+						    sizeof(d->pkt));
 			}
 		}
 
@@ -368,28 +356,24 @@ bool mp_decode_next(struct mp_decode *d)
 			     av_err2str(ret));
 #endif
 
-			if (d->packet_pending) {
-				av_packet_unref(&d->orig_pkt);
-				av_init_packet(&d->orig_pkt);
-				av_init_packet(&d->pkt);
-				d->packet_pending = false;
+			if (d->pkt) {
+				mp_media_free_packet(d->m, d->pkt);
+				d->pkt = NULL;
 			}
 			return true;
 		}
 
 		d->frame_ready = !!got_frame;
 
-		if (d->packet_pending) {
-			if (d->pkt.size) {
-				d->pkt.data += ret;
-				d->pkt.size -= ret;
+		if (d->pkt) {
+			if (d->pkt->size) {
+				d->pkt->data += ret;
+				d->pkt->size -= ret;
 			}
 
-			if (d->pkt.size <= 0) {
-				av_packet_unref(&d->orig_pkt);
-				av_init_packet(&d->orig_pkt);
-				av_init_packet(&d->pkt);
-				d->packet_pending = false;
+			if (d->pkt->size <= 0) {
+				mp_media_free_packet(d->m, d->pkt);
+				d->pkt = NULL;
 			}
 		}
 	}

+ 1 - 3
deps/media-playback/media-playback/decode.h

@@ -68,9 +68,7 @@ struct mp_decode {
 	bool eof;
 	bool hw;
 
-	AVPacket orig_pkt;
-	AVPacket pkt;
-	bool packet_pending;
+	AVPacket *pkt;
 	struct circlebuf packets;
 };
 

+ 26 - 12
deps/media-playback/media-playback/media.c

@@ -132,7 +132,7 @@ static inline enum video_range_type convert_color_range(enum AVColorRange r)
 }
 
 static inline struct mp_decode *get_packet_decoder(mp_media_t *media,
-						   AVPacket *pkt)
+						   const AVPacket *pkt)
 {
 	if (media->has_audio && pkt->stream_index == media->a.stream->index)
 		return &media->a;
@@ -142,14 +142,24 @@ static inline struct mp_decode *get_packet_decoder(mp_media_t *media,
 	return NULL;
 }
 
+void mp_media_free_packet(struct mp_media *media, AVPacket *pkt)
+{
+	av_packet_unref(pkt);
+	da_push_back(media->packet_pool, &pkt);
+}
+
 static int mp_media_next_packet(mp_media_t *media)
 {
-	AVPacket new_pkt;
-	AVPacket pkt;
-	av_init_packet(&pkt);
-	new_pkt = pkt;
+	AVPacket *pkt;
+	AVPacket **const cached = da_end(media->packet_pool);
+	if (cached) {
+		pkt = *cached;
+		da_pop_back(media->packet_pool);
+	} else {
+		pkt = av_packet_alloc();
+	}
 
-	int ret = av_read_frame(media->fmt, &pkt);
+	int ret = av_read_frame(media->fmt, pkt);
 	if (ret < 0) {
 		if (ret != AVERROR_EOF && ret != AVERROR_EXIT)
 			blog(LOG_WARNING, "MP: av_read_frame failed: %s (%d)",
@@ -157,13 +167,13 @@ static int mp_media_next_packet(mp_media_t *media)
 		return ret;
 	}
 
-	struct mp_decode *d = get_packet_decoder(media, &pkt);
-	if (d && pkt.size) {
-		av_packet_ref(&new_pkt, &pkt);
-		mp_decode_push_packet(d, &new_pkt);
+	struct mp_decode *d = get_packet_decoder(media, pkt);
+	if (d && pkt->size) {
+		mp_decode_push_packet(d, pkt);
+	} else {
+		mp_media_free_packet(media, pkt);
 	}
 
-	av_packet_unref(&pkt);
 	return ret;
 }
 
@@ -385,7 +395,7 @@ static void mp_media_next_video(mp_media_t *m, bool preload)
 	}
 
 	if (flip)
-		frame->data[0] -= frame->linesize[0] * (f->height - 1);
+		frame->data[0] -= frame->linesize[0] * ((size_t)f->height - 1);
 
 	new_format = convert_pixel_format(m->scale_format);
 	new_space = convert_color_space(f->colorspace, f->color_trc);
@@ -820,6 +830,7 @@ bool mp_media_init(mp_media_t *media, const struct mp_media_info *info)
 	media->buffering = info->buffering;
 	media->speed = info->speed;
 	media->is_local_file = info->is_local_file;
+	da_init(media->packet_pool);
 
 	if (!info->is_local_file || media->speed < 1 || media->speed > 200)
 		media->speed = 100;
@@ -867,6 +878,9 @@ void mp_media_free(mp_media_t *media)
 	mp_kill_thread(media);
 	mp_decode_free(&media->v);
 	mp_decode_free(&media->a);
+	for (size_t i = 0; i < media->packet_pool.num; i++)
+		av_packet_free(&media->packet_pool.array[i]);
+	da_free(media->packet_pool);
 	avformat_close_input(&media->fmt);
 	pthread_mutex_destroy(&media->mutex);
 	os_sem_destroy(media->sem);

+ 1 - 4
deps/media-playback/media-playback/media.h

@@ -62,6 +62,7 @@ struct mp_media {
 	int scale_linesizes[4];
 	uint8_t *scale_pic[4];
 
+	DARRAY(AVPacket *) packet_pool;
 	struct mp_decode v;
 	struct mp_decode a;
 	bool is_local_file;
@@ -137,10 +138,6 @@ extern void mp_media_seek_to(mp_media_t *m, int64_t pos);
 
 /* #define DETAILED_DEBUG_INFO */
 
-#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
-#define USE_NEW_FFMPEG_DECODE_API
-#endif
-
 #ifdef __cplusplus
 }
 #endif