#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
#include "libavformat/avformat.h"
+#include "libavutil/pixdesc.h"
#include "debug_ch.h"
qemu_mutex_lock(&s->context_mutex);
if (ioparam->api_index != CODEC_INIT) {
- if (!CONTEXT(s, ioparam->ctx_index).opened_context) {
+ if (!CONTEXT(s, ioparam->ctx_index)->opened_context) {
INFO("abandon api %d for context %d\n",
ioparam->api_index, ioparam->ctx_index);
qemu_mutex_unlock(&s->context_mutex);
TRACE("api_id: %d ctx_id: %d\n", api_id, ctx_id);
qemu_mutex_lock(&s->context_mutex);
- CONTEXT(s, ctx_id).occupied_thread = true;
+ CONTEXT(s, ctx_id)->occupied_thread = true;
qemu_mutex_unlock(&s->context_mutex);
ret = codec_func_handler[api_id](s, ctx_id, indata_buf);
g_free(elem);
qemu_mutex_lock(&s->context_mutex);
- if (CONTEXT(s, ctx_id).requested_close) {
+ if (CONTEXT(s, ctx_id)->requested_close) {
INFO("make worker thread to handle deinit\n");
// codec_deinit(s, ctx_id, NULL);
maru_brill_codec_release_context(s, ctx_id);
- CONTEXT(s, ctx_id).requested_close = false;
+ CONTEXT(s, ctx_id)->requested_close = false;
}
qemu_mutex_unlock(&s->context_mutex);
qemu_bh_schedule(s->codec_bh);
qemu_mutex_lock(&s->context_mutex);
- CONTEXT(s, ctx_id).occupied_thread = false;
+ CONTEXT(s, ctx_id)->occupied_thread = false;
qemu_mutex_unlock(&s->context_mutex);
}
TRACE("release %d of context\n", ctx_id);
qemu_mutex_lock(&s->threadpool.mutex);
- if (CONTEXT(s, ctx_id).opened_context) {
+ if (CONTEXT(s, ctx_id)->opened_context) {
// qemu_mutex_unlock(&s->threadpool.mutex);
codec_deinit(s, ctx_id, NULL);
// qemu_mutex_lock(&s->threadpool.mutex);
}
- CONTEXT(s, ctx_id).occupied_context = false;
+ CONTEXT(s, ctx_id)->occupied_context = false;
qemu_mutex_unlock(&s->threadpool.mutex);
// TODO: check if foreach statment needs lock or not.
// requires mutex_lock? its function is protected by critical section.
qemu_mutex_lock(&s->threadpool.mutex);
for (ctx_id = 1; ctx_id < CODEC_CONTEXT_MAX; ctx_id++) {
- if (CONTEXT(s, ctx_id).occupied_context == false) {
+ if (CONTEXT(s, ctx_id)->occupied_context == false) {
TRACE("get %d of codec context successfully.\n", ctx_id);
- CONTEXT(s, ctx_id).occupied_context = true;
+ CONTEXT(s, ctx_id)->occupied_context = true;
break;
}
}
return ctx_id;
}
+static enum PixelFormat get_format(AVCodecContext *avctx,
+ const enum PixelFormat *pi_fmt) {
+ bool can_hwaccel = false;
+ int i;
+
+ CodecContext *context = (CodecContext *)avctx->opaque;
+ MaruBrillCodecState *s = context->state;
+
+ if (s->hwaccel_plugin) {
+ goto end;
+ }
+
+ for (i = 0; pi_fmt[i] != PIX_FMT_NONE; ++i) {
+ const AVPixFmtDescriptor *dsc = av_pix_fmt_desc_get(pi_fmt[i]);
+ if (dsc == NULL) {
+ continue;
+ }
+ bool hwaccel = (dsc->flags & PIX_FMT_HWACCEL) != 0;
+
+ if (hwaccel) {
+ can_hwaccel = true;
+ }
+ }
+
+ if (!can_hwaccel) {
+ goto end;
+ }
+
+
+ if (s->hwaccel_plugin->setup(avctx, avctx->width, avctx->height)) {
+ goto end;
+ }
+
+ for (i = 0; pi_fmt[i] != PIX_FMT_NONE; ++i) {
+ if (pi_fmt[i] == s->hwaccel_plugin->pix_fmt) {
+ break;
+ }
+ }
+
+ if (pi_fmt[i] == PIX_FMT_NONE) {
+ goto end;
+ }
+
+ context->is_hwaccel = true;
+ return pi_fmt[i];
+
+end:
+ context->is_hwaccel = false;
+ return avcodec_default_get_format(avctx, pi_fmt);
+}
+
+static int get_buffer(struct AVCodecContext *avctx, AVFrame *frame) {
+ CodecContext *context = (CodecContext *)avctx->opaque;
+
+ if (context->is_hwaccel) {
+ return context->state->hwaccel_plugin->get_buffer(avctx, frame);
+ }
+
+ return avcodec_default_get_buffer(avctx, frame);
+}
+
+static void release_buffer(struct AVCodecContext *avctx, AVFrame *frame) {
+ CodecContext *context = (CodecContext *)avctx->opaque;
+
+ if (context->is_hwaccel) {
+ return context->state->hwaccel_plugin->release_buffer(avctx, frame);
+ }
+
+ return avcodec_default_release_buffer(avctx, frame);
+}
// allocate avcontext and avframe struct.
static AVCodecContext *maru_brill_codec_alloc_context(MaruBrillCodecState *s, int ctx_id)
TRACE("enter: %s\n", __func__);
TRACE("allocate %d of context and frame.\n", ctx_id);
- CONTEXT(s, ctx_id).avctx = avcodec_alloc_context3(NULL);
- CONTEXT(s, ctx_id).frame = avcodec_alloc_frame();
- CONTEXT(s, ctx_id).opened_context = false;
+
+ AVCodecContext *avctx = CONTEXT(s, ctx_id)->avctx;
+ avctx = avcodec_alloc_context3(NULL);
+ avctx->get_format = get_format;
+ avctx->get_buffer = get_buffer;
+ avctx->reget_buffer = avcodec_default_reget_buffer;
+ avctx->release_buffer = release_buffer;
+ avctx->opaque = CONTEXT(s, ctx_id);
+
+ CONTEXT(s, ctx_id)->frame = avcodec_alloc_frame();
+ CONTEXT(s, ctx_id)->opened_context = false;
+ CONTEXT(s, ctx_id)->state = s;
TRACE("leave: %s\n", __func__);
- return CONTEXT(s, ctx_id).avctx;
+ return CONTEXT(s, ctx_id)->avctx;
}
static AVCodec *maru_brill_codec_find_avcodec(uint8_t *mem_buf)
+ sizeof(avctx->extradata_size) + avctx->extradata_size)
+ sizeof(int);
- CONTEXT(s, ctx_id).opened_context = true;
- CONTEXT(s, ctx_id).parser_ctx =
+ CONTEXT(s, ctx_id)->opened_context = true;
+ CONTEXT(s, ctx_id)->parser_ctx =
maru_brill_codec_parser_init(avctx);
} else {
ERR("failed to find codec. ctx_id: %d\n", ctx_id);
TRACE("enter: %s\n", __func__);
- avctx = CONTEXT(s, ctx_id).avctx;
- frame = CONTEXT(s, ctx_id).frame;
- parserctx = CONTEXT(s, ctx_id).parser_ctx;
+ avctx = CONTEXT(s, ctx_id)->avctx;
+ frame = CONTEXT(s, ctx_id)->frame;
+ parserctx = CONTEXT(s, ctx_id)->parser_ctx;
if (!avctx || !frame) {
TRACE("%d of AVCodecContext or AVFrame is NULL. "
" Those resources have been released before.\n", ctx_id);
INFO("close avcontext of %d\n", ctx_id);
// qemu_mutex_lock(&s->threadpool.mutex);
avcodec_close(avctx);
- CONTEXT(s, ctx_id).opened_context = false;
+ CONTEXT(s, ctx_id)->opened_context = false;
// qemu_mutex_unlock(&s->threadpool.mutex);
if (avctx->extradata) {
TRACE("free context extradata\n");
av_free(avctx->extradata);
- CONTEXT(s, ctx_id).avctx->extradata = NULL;
+ CONTEXT(s, ctx_id)->avctx->extradata = NULL;
}
if (frame) {
TRACE("free frame\n");
// av_free(frame);
avcodec_free_frame(&frame);
- CONTEXT(s, ctx_id).frame = NULL;
+ CONTEXT(s, ctx_id)->frame = NULL;
}
if (avctx) {
TRACE("free codec context\n");
av_free(avctx);
- CONTEXT(s, ctx_id).avctx = NULL;
+ CONTEXT(s, ctx_id)->avctx = NULL;
}
if (parserctx) {
av_parser_close(parserctx);
- CONTEXT(s, ctx_id).parser_ctx = NULL;
+ CONTEXT(s, ctx_id)->parser_ctx = NULL;
}
maru_brill_codec_push_writequeue(s, NULL, 0, ctx_id, NULL);
TRACE("enter: %s\n", __func__);
- avctx = CONTEXT(s, ctx_id).avctx;
+ avctx = CONTEXT(s, ctx_id)->avctx;
if (!avctx) {
ERR("%d of AVCodecContext is NULL.\n", ctx_id);
ret = false;
avpkt.data = inbuf;
avpkt.size = inbuf_size;
- avctx = CONTEXT(s, ctx_id).avctx;
- picture = CONTEXT(s, ctx_id).frame;
+ avctx = CONTEXT(s, ctx_id)->avctx;
+ picture = CONTEXT(s, ctx_id)->frame;
if (!avctx) {
ERR("decode_video. %d of AVCodecContext is NULL.\n", ctx_id);
} else if (!avctx->codec) {
return true;
}
+
static bool codec_picture_copy (MaruBrillCodecState *s, int ctx_id, void *elem)
{
AVCodecContext *avctx = NULL;
TRACE("copy decoded image of %d context.\n", ctx_id);
- avctx = CONTEXT(s, ctx_id).avctx;
- src = (AVPicture *)CONTEXT(s, ctx_id).frame;
+ avctx = CONTEXT(s, ctx_id)->avctx;
+ src = (AVPicture *)CONTEXT(s, ctx_id)->frame;
if (!avctx) {
ERR("picture_copy. %d of AVCodecContext is NULL.\n", ctx_id);
ret = false;
ret = false;
} else {
TRACE("picture size: %d\n", pict_size);
- maru_brill_codec_push_writequeue(s, src, pict_size, ctx_id, &default_video_decode_data_handler);
+ if (CONTEXT(s, ctx_id)->is_hwaccel) {
+ maru_brill_codec_push_writequeue(s, src, pict_size, ctx_id, s->hwaccel_plugin->video_decode_data_handler);
+ } else {
+ maru_brill_codec_push_writequeue(s, src, pict_size, ctx_id, &default_video_decode_data_handler);
+ }
}
}
avpkt.data = inbuf;
avpkt.size = inbuf_size;
- avctx = CONTEXT(s, ctx_id).avctx;
- // audio_out = CONTEXT(s, ctx_id).frame;
+ avctx = CONTEXT(s, ctx_id)->avctx;
+ // audio_out = CONTEXT(s, ctx_id)->frame;
audio_out = avcodec_alloc_frame();
if (!avctx) {
ERR("decode_audio. %d of AVCodecContext is NULL\n", ctx_id);
avpkt.data = NULL;
avpkt.size = 0;
- avctx = CONTEXT(s, ctx_id).avctx;
- pict = CONTEXT(s, ctx_id).frame;
+ avctx = CONTEXT(s, ctx_id)->avctx;
+ pict = CONTEXT(s, ctx_id)->frame;
if (!avctx || !pict) {
ERR("%d of context or frame is NULL\n", ctx_id);
} else if (!avctx->codec) {
// return false;
}
- avctx = CONTEXT(s, ctx_id).avctx;
+ avctx = CONTEXT(s, ctx_id)->avctx;
if (!avctx) {
ERR("[%s] %d of Context is NULL!\n", __func__, ctx_id);
} else if (!avctx->codec) {