[FFmpeg-devel] [RFC/PATCH 8/8] tidsp: process buffers

Felipe Contreras felipe.contreras
Mon Sep 6 00:15:35 CEST 2010


Now it's fully functional. Could be organized a bit better though.

Signed-off-by: Felipe Contreras <felipe.contreras at gmail.com>
---
 libavcodec/tidsp_mpeg4.c |   89 +++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 84 insertions(+), 5 deletions(-)

diff --git a/libavcodec/tidsp_mpeg4.c b/libavcodec/tidsp_mpeg4.c
index 4c72dfb..935a376 100644
--- a/libavcodec/tidsp_mpeg4.c
+++ b/libavcodec/tidsp_mpeg4.c
@@ -9,13 +9,28 @@
  */
 
 #include "tidsp/tidsp.h"
+#include "tidsp/dmm_buffer.h"
 
 #include "avcodec.h"
+#include "mpegvideo.h"
 
 struct td_av_context {
 	struct td_context *td_ctx;
+	struct td_buffer *output_buffer;
 };
 
+static void handle_buffer(struct td_context *td_ctx, struct td_buffer *b)
+{
+	AVCodecContext *avctx = td_ctx->client;
+	struct td_av_context *ctx = avctx->hwaccel_private;
+
+	if (b->port->id == 0)
+		return;
+	if (ctx->output_buffer)
+		av_log(avctx, AV_LOG_ERROR, "overriding buffer\n");
+	ctx->output_buffer = b;
+}
+
 static av_cold int init(AVCodecContext *avctx)
 {
 	struct td_av_context *ctx;
@@ -27,6 +42,7 @@ static av_cold int init(AVCodecContext *avctx)
 	td_ctx->codec = &td_mp4v_codec;
 	td_ctx->width = avctx->width;
 	td_ctx->height = avctx->height;
+	td_ctx->handle_buffer = handle_buffer;
 
 	if (!td_init(ctx->td_ctx)) {
 		av_freep(&avctx->hwaccel_private);
@@ -46,16 +62,79 @@ static av_cold int close(AVCodecContext *avctx)
 	return 0;
 }
 
-static int start_frame(av_unused AVCodecContext *avctx,
-		av_unused const uint8_t *buffer,
-		av_unused uint32_t size)
+static int start_frame(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
 {
+	struct td_av_context *ctx = avctx->hwaccel_private;
+	struct td_port *p;
+	struct td_buffer *b;
+
+	p = ctx->td_ctx->ports[0];
+
+	b = &p->buffers[0];
+	if (b->used)
+		b = &p->buffers[1];
+	if (b->used)
+		return -1;
+
+	memcpy(b->data->data, buffer, size);
+	b->data->size = size;
+	td_send_buffer(ctx->td_ctx, b);
+
 	return 0;
 }
 
-static int end_frame(av_unused AVCodecContext *avctx)
+static int end_frame(AVCodecContext *avctx)
 {
-	return 0;
+	struct td_av_context *ctx = avctx->hwaccel_private;
+	MpegEncContext *s = avctx->priv_data;
+	AVFrame *f;
+	uint8_t *p1, *p2, *p3;
+	unsigned i;
+	int ret = -1;
+	struct td_port *p;
+	struct td_buffer *b;
+	bool ready;
+
+again:
+	if (!td_get_event(ctx->td_ctx))
+		goto leave;
+
+	b = ctx->output_buffer;
+	if (!b)
+		goto leave;
+
+	ctx->output_buffer = NULL;
+	f = (AVFrame*) &s->current_picture;
+
+	p1 = b->data->data;
+	p2 = p1 + avctx->width * avctx->height;
+	p3 = p2 + (avctx->width * avctx->height / 4);
+
+	for (i = 0; i < avctx->height; i++)
+		memcpy(f->data[0] + i * f->linesize[0], p1 + i * avctx->width, avctx->width);
+	for (i = 0; i < avctx->height / 2; i++)
+		memcpy(f->data[1] + i * f->linesize[1], p2 + i * avctx->width / 2, avctx->width / 2);
+	for (i = 0; i < avctx->height / 2; i++)
+		memcpy(f->data[2] + i * f->linesize[2], p3 + i * avctx->width / 2, avctx->width / 2);
+
+	td_send_buffer(ctx->td_ctx, b);
+
+	ret = 0;
+
+leave:
+
+	p = ctx->td_ctx->ports[0];
+	ready = false;
+	for (i = 0; i < p->nr_buffers; i++) {
+		if (!p->buffers[i].used) {
+			ready = true;
+			break;
+		}
+	}
+	if (!ready)
+		goto again;
+
+	return ret;
 }
 
 static int decode_slice(av_unused AVCodecContext *avctx,
-- 
1.7.2.2




More information about the ffmpeg-devel mailing list