//#define DATA_DEBUG
+extern void aml_recycle_dma_buffers(struct aml_vcodec_ctx *ctx, u32 handle);
static int def_4k_vstreambuf_sizeM =
(DEFAULT_VIDEO_BUFFER_SIZE_4K >> 20);
static int def_vstreambuf_sizeM =
return ret;
}
+void vdec_vframe_input_free(void *priv, u32 handle)
+{
+ struct aml_vcodec_ctx *ctx = priv;
+
+ aml_recycle_dma_buffers(ctx, handle);
+}
+
int vdec_vframe_write_with_dma(struct aml_vdec_adapt *ada_ctx,
- ulong addr, u32 count, u64 timestamp, u32 handle)
+ ulong addr, u32 count, u64 timestamp, u32 handle,
+ chunk_free free, void* priv)
{
int ret = -1;
struct vdec_s *vdec = ada_ctx->vdec;
/* set timestamp */
vdec_set_timestamp(vdec, timestamp);
- ret = vdec_write_vframe_with_dma(vdec, addr, count, handle);
+ ret = vdec_write_vframe_with_dma(vdec, addr, count,
+ handle, free, priv);
if (slow_input) {
v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO,
vdec->config_len = len > PAGE_SIZE ? PAGE_SIZE : len;
memcpy(vdec->config, data, vdec->config_len);
}
-
-u32 aml_recycle_buffer(struct aml_vdec_adapt *adaptor)
-{
- return vdec_input_get_freed_handle(adaptor->vdec);
-}
-
#include <linux/amlogic/media/utils/vformat.h>
#include <linux/amlogic/media/utils/amstream.h>
#include "../stream_input/amports/streambuf.h"
+#include "../frame_provider/decoder/utils/vdec_input.h"
#include "aml_vcodec_drv.h"
struct aml_vdec_adapt {
int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx,
const char *buf, unsigned int count, u64 timestamp);
+void vdec_vframe_input_free(void *priv, u32 handle);
+
int vdec_vframe_write_with_dma(struct aml_vdec_adapt *ada_ctx,
- ulong addr, u32 count, u64 timestamp, u32 handle);
+ ulong addr, u32 count, u64 timestamp, u32 handle,
+ chunk_free free, void *priv);
bool vdec_input_full(struct aml_vdec_adapt *ada_ctx);
int vdec_frame_number(struct aml_vdec_adapt *ada_ctx);
-u32 aml_recycle_buffer(struct aml_vdec_adapt *adaptor);
-
#endif /* VDEC_ADAPT_H */
extern int dmabuf_fd_install_data(int fd, void* data, u32 size);
extern bool is_v4l2_buf_file(struct file *file);
-static void aml_recycle_dma_buffers(struct aml_vcodec_ctx *ctx);
static ulong aml_vcodec_ctx_lock(struct aml_vcodec_ctx *ctx)
{
dstbuf = container_of(fb, struct aml_video_dec_buf, frame_buffer);
vb2_buf = &dstbuf->vb.vb2_buf;
- if (ctx->is_drm_mode && vb2_buf->memory == VB2_MEMORY_DMABUF)
- aml_recycle_dma_buffers(ctx);
-
if (dstbuf->frame_buffer.num_planes == 1) {
vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, fb->m.mem[0].bytes_used);
} else if (dstbuf->frame_buffer.num_planes == 2) {
}
}
-static void aml_recycle_dma_buffers(struct aml_vcodec_ctx *ctx)
+void aml_recycle_dma_buffers(struct aml_vcodec_ctx *ctx, u32 handle)
{
struct vb2_v4l2_buffer *vb;
struct aml_video_dec_buf *buf;
struct vb2_queue *q;
- u32 handle;
+ int index = handle & 0xf;
+ if (ctx->is_out_stream_off) {
+ v4l_dbg(ctx, V4L_DEBUG_CODEC_INPUT,
+ "ignore buff idx: %d streamoff\n", index);
+ return;
+ }
q = v4l2_m2m_get_vq(ctx->m2m_ctx,
V4L2_BUF_TYPE_VIDEO_OUTPUT);
- while ((handle = aml_recycle_buffer(ctx->ada_ctx))) {
- int index = handle & 0xf;
+ vb = to_vb2_v4l2_buffer(q->bufs[index]);
+ buf = container_of(vb, struct aml_video_dec_buf, vb);
+ v4l2_m2m_buf_done(vb, buf->error ? VB2_BUF_STATE_ERROR :
+ VB2_BUF_STATE_DONE);
- vb = to_vb2_v4l2_buffer(q->bufs[index]);
- buf = container_of(vb, struct aml_video_dec_buf, vb);
- v4l2_m2m_buf_done(vb, buf->error ? VB2_BUF_STATE_ERROR :
- VB2_BUF_STATE_DONE);
-
- v4l_dbg(ctx, V4L_DEBUG_CODEC_INPUT,
- "recycle buff idx: %d, vbuf: %lx\n", index,
- (ulong)vb2_dma_contig_plane_dma_addr(q->bufs[index], 0));
- }
+ v4l_dbg(ctx, V4L_DEBUG_CODEC_INPUT,
+ "recycle buff idx: %d, vbuf: %lx\n", index,
+ (ulong)vb2_dma_contig_plane_dma_addr(q->bufs[index], 0));
}
static void aml_vdec_worker(struct work_struct *work)
* when decode success without resolution change.
*/
v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
-
- if (ctx->is_drm_mode && buf.model == VB2_MEMORY_DMABUF)
- aml_recycle_dma_buffers(ctx);
- else
+ if (!(ctx->is_drm_mode && buf.model == VB2_MEMORY_DMABUF))
v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_DONE);
} else if (ret && ret != -EAGAIN) {
src_buf_info->error = (ret == -EIO ? true : false);
v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
- if (ctx->is_drm_mode && buf.model == VB2_MEMORY_DMABUF)
- aml_recycle_dma_buffers(ctx);
- else
+ if (!(ctx->is_drm_mode && buf.model == VB2_MEMORY_DMABUF))
v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_ERROR);
v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
ctx->is_stream_off = false;
}
- }
+ } else
+ ctx->is_out_stream_off = false;
v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
"%s, type: %d\n", __func__, q->type);
struct vb2_queue *q;
q = v4l2_m2m_get_vq(fh->m2m_ctx, i);
- if (!V4L2_TYPE_IS_OUTPUT(q->type)) {
+ if (!V4L2_TYPE_IS_OUTPUT(q->type))
ctx->is_stream_off = true;
- }
+ else
+ ctx->is_out_stream_off = true;
v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
"%s, type: %d\n", __func__, q->type);
if (vdec_if_probe(ctx, &src_mem, NULL)) {
v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
- if (ctx->is_drm_mode && src_mem.model == VB2_MEMORY_DMABUF)
- aml_recycle_dma_buffers(ctx);
- else
+ if (!(ctx->is_drm_mode && src_mem.model == VB2_MEMORY_DMABUF))
v4l2_m2m_buf_done(to_vb2_v4l2_buffer(vb), VB2_BUF_STATE_DONE);
return;
}
*/
if (ctx->is_drm_mode && src_mem.model == VB2_MEMORY_DMABUF) {
v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
- aml_recycle_dma_buffers(ctx);
} else if (ctx->param_sets_from_ucode) {
v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
v4l2_m2m_buf_done(to_vb2_v4l2_buffer(vb),
codec_mm_bufs_cnt_clean(q);
if (V4L2_TYPE_IS_OUTPUT(q->type)) {
- if (ctx->is_drm_mode && q->memory == VB2_MEMORY_DMABUF)
- aml_recycle_dma_buffers(ctx);
-
while ((vb2_v4l2 = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)))
v4l2_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
* @is_drm_mode: decoding work on drm mode if that set.
* @is_stream_mode: vdec input used to stream mode, default frame mode.
* @is_stream_off: the value used to handle reset active.
+ * @is_out_stream_off: streamoff called for output port.
* @receive_cmd_stop: if receive the cmd flush decoder.
* @reset_flag: reset mode includes lightly and normal mode.
* @decoded_frame_cnt: the capture buffer deque number to be count.
bool is_drm_mode;
bool output_dma_mode;
bool is_stream_off;
+ bool is_out_stream_off;
bool receive_cmd_stop;
int reset_flag;
int decoded_frame_cnt;
int ret = 0;
struct aml_vdec_adapt *vdec = &inst->vdec;
- ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle);
+ ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle,
+ vdec_vframe_input_free, inst->ctx);
if (ret < 0) {
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
"write frame data failed. err: %d\n", ret);
bs->model == VB2_MEMORY_USERPTR) {
ret = vdec_vframe_write_with_dma(vdec,
bs->addr, size, bs->timestamp,
- BUFF_IDX(bs, bs->index));
+ BUFF_IDX(bs, bs->index),
+ vdec_vframe_input_free, inst->ctx);
}
} else {
/*checked whether the resolution changes.*/
int ret = 0;
struct aml_vdec_adapt *vdec = &inst->vdec;
- ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle);
+ ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle,
+ vdec_vframe_input_free, inst->ctx);
if (ret < 0) {
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
"write frame data failed. err: %d\n", ret);
bs->model == VB2_MEMORY_USERPTR) {
ret = vdec_vframe_write_with_dma(vdec,
bs->addr, size, bs->timestamp,
- BUFF_IDX(bs, bs->index));
+ BUFF_IDX(bs, bs->index),
+ vdec_vframe_input_free, inst->ctx);
}
} else {
if (inst->ctx->param_sets_from_ucode) {
int ret = 0;
struct aml_vdec_adapt *vdec = &inst->vdec;
- ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle);
+ ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle,
+ vdec_vframe_input_free, inst->ctx);
if (ret < 0) {
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
"write frame data failed. err: %d\n", ret);
bs->model == VB2_MEMORY_USERPTR) {
ret = vdec_vframe_write_with_dma(vdec,
bs->addr, size, bs->timestamp,
- BUFF_IDX(bs, bs->index));
+ BUFF_IDX(bs, bs->index),
+ vdec_vframe_input_free, inst->ctx);
}
} else {
if (!inst->ctx->param_sets_from_ucode) {
int ret = 0;
struct aml_vdec_adapt *vdec = &inst->vdec;
- ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle);
+ ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle,
+ vdec_vframe_input_free, inst->ctx);
if (ret < 0) {
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
"write frame data failed. err: %d\n", ret);
bs->model == VB2_MEMORY_USERPTR) {
ret = vdec_vframe_write_with_dma(vdec,
bs->addr, size, bs->timestamp,
- BUFF_IDX(bs, bs->index));
+ BUFF_IDX(bs, bs->index),
+ vdec_vframe_input_free, inst->ctx);
}
} else {
ret = vdec_write_nalu(inst, buf, size, bs->timestamp);
int ret = 0;
struct aml_vdec_adapt *vdec = &inst->vdec;
- ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle);
+ ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle,
+ vdec_vframe_input_free, inst->ctx);
if (ret < 0) {
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
"write frame data failed. err: %d\n", ret);
bs->model == VB2_MEMORY_USERPTR) {
ret = vdec_vframe_write_with_dma(vdec,
bs->addr, size, bs->timestamp,
- BUFF_IDX(bs, bs->index));
+ BUFF_IDX(bs, bs->index),
+ vdec_vframe_input_free, inst->ctx);
}
} else {
ret = vdec_write_nalu(inst, buf, size, bs->timestamp);
int ret = 0;
struct aml_vdec_adapt *vdec = &inst->vdec;
- ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle);
+ ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle,
+ vdec_vframe_input_free, inst->ctx);
if (ret < 0) {
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
"write frame data failed. err: %d\n", ret);
bs->model == VB2_MEMORY_USERPTR) {
ret = vdec_vframe_write_with_dma(vdec,
bs->addr, size, bs->timestamp,
- BUFF_IDX(bs, bs->index));
+ BUFF_IDX(bs, bs->index),
+ vdec_vframe_input_free, inst->ctx);
}
} else {
ret = vdec_write_nalu(inst, buf, size, bs->timestamp);
int ret = 0;
struct aml_vdec_adapt *vdec = &inst->vdec;
- ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle);
+ ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle,
+ vdec_vframe_input_free, inst->ctx);
if (ret < 0) {
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
"write frame data failed. err: %d\n", ret);
bs->model == VB2_MEMORY_USERPTR) {
ret = vdec_vframe_write_with_dma(vdec,
bs->addr, size, bs->timestamp,
- BUFF_IDX(bs, bs->index));
+ BUFF_IDX(bs, bs->index),
+ vdec_vframe_input_free, inst->ctx);
}
} else {
/*checked whether the resolution changes.*/
EXPORT_SYMBOL(vdec_write_vframe);
int vdec_write_vframe_with_dma(struct vdec_s *vdec,
- ulong addr, size_t count, u32 handle)
+ ulong addr, size_t count, u32 handle, chunk_free free, void* priv)
{
- return vdec_input_add_frame_with_dma(&vdec->input, addr, count, handle);
+ return vdec_input_add_frame_with_dma(&vdec->input,
+ addr, count, handle, free, priv);
}
EXPORT_SYMBOL(vdec_write_vframe_with_dma);
size_t count);
extern int vdec_write_vframe_with_dma(struct vdec_s *vdec,
- ulong addr, size_t count, u32 handle);
+ ulong addr, size_t count, u32 handle, chunk_free free, void* priv);
/* mark the vframe_chunk as consumed */
extern void vdec_vframe_dirty(struct vdec_s *vdec,
static struct vframe_block_list_s *
vdec_input_alloc_new_block(struct vdec_input_s *input,
ulong phy_addr,
- int size);
+ int size,
+ chunk_free free,
+ void* priv);
static int aml_copy_from_user(void *to, const void *from, ulong n)
{
static int vframe_block_init_alloc_storage(struct vdec_input_s *input,
struct vframe_block_list_s *block,
ulong phy_addr,
- int size)
+ int size,
+ chunk_free free,
+ void *priv)
{
int alloc_size = input->default_block_size;
block->magic = 0x4b434c42;
block->start_virt = NULL;
block->start = phy_addr;
block->size = size;
+ block->free = free;
+ block->priv = priv;
} else {
alloc_size = PAGE_ALIGN(alloc_size);
block->addr = codec_mm_alloc_for_dma_ex(
block->start = block->addr;
block->size = alloc_size;
block->is_out_buf = 0;
+ block->free = NULL;
}
return 0;
}
/*prepared 3 buffers for smooth start.*/
for (i = 0; i < 3; i++) {
- block = vdec_input_alloc_new_block(input, 0, 0);
+ block = vdec_input_alloc_new_block(input, 0, 0, NULL, NULL);
if (!block)
break;
flags = vdec_input_lock(input);
static struct vframe_block_list_s *
vdec_input_alloc_new_block(struct vdec_input_s *input,
ulong phy_addr,
- int size)
+ int size,
+ chunk_free free,
+ void* priv)
{
struct vframe_block_list_s *block;
block = kzalloc(sizeof(struct vframe_block_list_s),
}
if (vframe_block_init_alloc_storage(input,
- block, phy_addr, size) != 0) {
+ block, phy_addr, size, free, priv) != 0) {
kfree(block);
pr_err("vframe_block storage allocation failed\n");
return NULL;
/*128k aligned,same as codec_mm*/
input->default_block_size = def_size;
}
- block = vdec_input_alloc_new_block(input, 0, 0);
+ block = vdec_input_alloc_new_block(input, 0, 0, NULL, NULL);
if (!block) {
input->no_mem_err_cnt++;
return -EAGAIN;
}
int vdec_input_add_chunk(struct vdec_input_s *input, const char *buf,
- size_t count, u32 handle)
+ size_t count, u32 handle, chunk_free free, void* priv)
{
unsigned long flags;
struct vframe_chunk_s *chunk;
if (vdec_secure(vdec)) {
block = vdec_input_alloc_new_block(input, (ulong)buf,
- PAGE_ALIGN(count + HEVC_PADDING_SIZE + 1)); /*Add padding large than HEVC_PADDING_SIZE */
+ PAGE_ALIGN(count + HEVC_PADDING_SIZE + 1),
+ free, priv); /*Add padding large than HEVC_PADDING_SIZE */
if (!block)
return -ENOMEM;
block->handle = handle;
return -EIO; /*must drm info v2 version*/
phy_buf = (unsigned long) drm.drm_phy;
vdec_input_add_chunk(input, (char *)phy_buf,
- (size_t)drm.drm_pktsize, drm.handle);
+ (size_t)drm.drm_pktsize, drm.handle, NULL, NULL);
count -= sizeof(struct drm_info);
ret += sizeof(struct drm_info);
vdec->pts_valid = true;
}
} else {
- ret = vdec_input_add_chunk(input, buf, count, 0);
+ ret = vdec_input_add_chunk(input, buf, count, 0, NULL, NULL);
}
return ret;
EXPORT_SYMBOL(vdec_input_add_frame);
int vdec_input_add_frame_with_dma(struct vdec_input_s *input, ulong addr,
- size_t count, u32 handle)
+ size_t count, u32 handle, chunk_free free, void* priv)
{
struct vdec_s *vdec = input->vdec;
return vdec_secure(vdec) ?
- vdec_input_add_chunk(input, (char *)addr, count, handle) : -1;
+ vdec_input_add_chunk(input,
+ (char *)addr, count, handle, free, priv) : -1;
}
EXPORT_SYMBOL(vdec_input_add_frame_with_dma);
if (block->is_out_buf) {
list_move_tail(&block->list,
&input->vframe_block_free_list);
+ if (block->free) {
+ vdec_input_del_block_locked(input, block);
+ block->free(block->priv, block->handle);
+ }
+ kfree(block);
} else if (block->chunk_count == 0 &&
input->wr_block != block ) {/*don't free used block*/
if (block->size < input->default_block_size) {
handle = block->handle;
vdec_input_del_block_locked(input, block);
+ if (block->free)
+ block->free(block->priv, handle);
kfree(block);
} while(!handle);
struct vdec_s;
struct vdec_input_s;
+typedef void (*chunk_free)(void *priv, u32 handle);
+
struct vframe_block_list_s {
u32 magic;
int id;
int chunk_count;
int is_out_buf;
u32 handle;
+
+ /* free callback */
+ chunk_free free;
+ void* priv;
+
struct vdec_input_s *input;
};
size_t count);
extern int vdec_input_add_frame_with_dma(struct vdec_input_s *input, ulong addr,
- size_t count, u32 handle);
+ size_t count, u32 handle, chunk_free free, void* priv);
/* Peek next frame data from decoder's input */
extern struct vframe_chunk_s *vdec_input_next_chunk(