summaryrefslogtreecommitdiff
authorHui Zhang <hui.zhang@amlogic.com>2020-02-27 08:10:45 (GMT)
committer Zhi Zhou <zhi.zhou@amlogic.com>2020-05-15 11:31:05 (GMT)
commitd631e9c223ed4d7402cad987dd9c0d9c0b804ecc (patch)
tree9ae033197370d7743d47525314961d7b3b03f947
parent5f8edcbfe885c02518a1d87f70d0b9314710982a (diff)
downloadmedia_modules-d631e9c223ed4d7402cad987dd9c0d9c0b804ecc.zip
media_modules-d631e9c223ed4d7402cad987dd9c0d9c0b804ecc.tar.gz
media_modules-d631e9c223ed4d7402cad987dd9c0d9c0b804ecc.tar.bz2
decode: support multi-instance on stream mode. [1/1]
PD#SWPL-21360 Problem: can not support multi-instance on stream mode. Solution: 1. parser's wp and rp operations have been separated from decode. 2. remove register rw of parser from the stream input pipeline. 3. opitimize stbuf involves the struct and adds series of ops fun. 4. defualt used ops with esparser of stbuf, we can force switch non-parser mode used by the flag "enable_stream_mode_multi_dec" on stream_input. echo 1 > /sys/module/decoder_common/parameters/enable_stream_mode_multi_dec Verify: u212, ab301 1. pass the base playeback that be tested by dailiang. 2. pass the dvb playback that be tested by chenyuanyuan. 3. pass cts testing for media that be tested by zhanggan. Change-Id: I20abb42f894bee92bd11870b5e293b0f0a941930 Signed-off-by: Hui Zhang <hui.zhang@amlogic.com>
Diffstat
-rw-r--r--drivers/amvdec_ports/aml_vcodec_adapt.c27
-rw-r--r--drivers/amvdec_ports/aml_vcodec_adapt.h2
-rw-r--r--drivers/amvdec_ports/vdec_drv_if.h2
-rw-r--r--drivers/frame_provider/decoder/avs/avs.c2
-rw-r--r--drivers/frame_provider/decoder/avs/avsp_trans.c2
-rw-r--r--drivers/frame_provider/decoder/avs2/vavs2.c17
-rw-r--r--drivers/frame_provider/decoder/avs_multi/avs_multi.c23
-rw-r--r--drivers/frame_provider/decoder/h264/vh264.c2
-rw-r--r--drivers/frame_provider/decoder/h264_multi/vmh264.c25
-rw-r--r--drivers/frame_provider/decoder/h265/vh265.c33
-rw-r--r--drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c12
-rw-r--r--drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c19
-rw-r--r--drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c13
-rw-r--r--drivers/frame_provider/decoder/real/vreal.c4
-rw-r--r--drivers/frame_provider/decoder/utils/vdec.c155
-rw-r--r--drivers/frame_provider/decoder/utils/vdec.h6
-rw-r--r--drivers/frame_provider/decoder/vav1/vav1.c4
-rw-r--r--drivers/frame_provider/decoder/vp9/vvp9.c4
-rw-r--r--drivers/stream_input/Makefile7
-rw-r--r--drivers/stream_input/amports/adec.c2
-rw-r--r--drivers/stream_input/amports/adec.h2
-rw-r--r--drivers/stream_input/amports/amports_priv.h2
-rw-r--r--drivers/stream_input/amports/amstream.c445
-rw-r--r--drivers/stream_input/amports/stream_buffer_base.c169
-rw-r--r--drivers/stream_input/amports/stream_buffer_base.h62
-rw-r--r--drivers/stream_input/amports/stream_buffer_interface.c334
-rw-r--r--drivers/stream_input/amports/streambuf.c (renamed from drivers/stream_input/parser/streambuf.c)84
-rw-r--r--drivers/stream_input/amports/streambuf.h (renamed from drivers/stream_input/parser/streambuf.h)39
-rw-r--r--drivers/stream_input/amports/streambuf_reg.h (renamed from drivers/stream_input/parser/streambuf_reg.h)0
-rw-r--r--drivers/stream_input/amports/thread_rw.c (renamed from drivers/stream_input/parser/thread_rw.c)4
-rw-r--r--drivers/stream_input/amports/thread_rw.h (renamed from drivers/stream_input/parser/thread_rw.h)4
-rw-r--r--drivers/stream_input/parser/demux/hw_demux/hwdemux_inject.c28
-rw-r--r--drivers/stream_input/parser/esparser.c75
-rw-r--r--drivers/stream_input/parser/hw_demux/aml_dmx.c2
-rw-r--r--drivers/stream_input/parser/psparser.c48
-rw-r--r--drivers/stream_input/parser/rmparser.c4
-rw-r--r--drivers/stream_input/parser/tsdemux.c55
37 files changed, 1280 insertions, 438 deletions
diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.c b/drivers/amvdec_ports/aml_vcodec_adapt.c
index b87d0c8..67a29bb 100644
--- a/drivers/amvdec_ports/aml_vcodec_adapt.c
+++ b/drivers/amvdec_ports/aml_vcodec_adapt.c
@@ -32,8 +32,8 @@
#include <linux/amlogic/media/utils/aformat.h>
#include <linux/amlogic/media/registers/register.h>
#include "../stream_input/amports/adec.h"
-#include "../stream_input/parser/streambuf.h"
-#include "../stream_input/parser/streambuf_reg.h"
+#include "../stream_input/amports/streambuf.h"
+#include "../stream_input/amports/streambuf_reg.h"
#include "../stream_input/parser/tsdemux.h"
#include "../stream_input/parser/psparser.h"
#include "../stream_input/parser/esparser.h"
@@ -202,7 +202,7 @@ static void change_vbufsize(struct vdec_s *vdec,
return;
}
- if (pvbuf->for_4k) {
+ if (vdec->port->is_4k) {
pvbuf->buf_size = def_4k_vstreambuf_sizeM * SZ_1M;
if (vdec->port_flag & PORT_FLAG_DRM)
@@ -246,7 +246,7 @@ static void audio_component_release(struct stream_port_s *port,
case 3:
adec_release(port->vformat);
case 2:
- stbuf_release(pbuf, false);
+ stbuf_release(pbuf);
case 1:
;
}
@@ -262,7 +262,7 @@ static int audio_component_init(struct stream_port_s *port,
return 0;
}
- r = stbuf_init(pbuf, NULL, false);
+ r = stbuf_init(pbuf, NULL);
if (r < 0)
return r;
@@ -293,7 +293,6 @@ struct stream_buf_s *pbuf, int release_num)
struct vdec_s *vdec = ada_ctx->vdec;
struct vdec_s *slave = NULL;
- bool is_multidec = !vdec_single(vdec);
switch (release_num) {
default:
@@ -315,7 +314,7 @@ struct stream_buf_s *pbuf, int release_num)
case 2: {
if ((port->type & PORT_TYPE_FRAME) == 0)
- stbuf_release(pbuf, is_multidec);
+ stbuf_release(pbuf);
}
case 1:
@@ -338,15 +337,15 @@ static int video_component_init(struct stream_port_s *port,
if ((vdec->sys_info->height * vdec->sys_info->width) > 1920 * 1088
|| port->vformat == VFORMAT_H264_4K2K) {
- pbuf->for_4k = 1;
+ port->is_4k = true;
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX
&& port->vformat == VFORMAT_H264)
vdec_poweron(VDEC_HEVC);
} else
- pbuf->for_4k = 0;
+ port->is_4k = false;
if (port->type & PORT_TYPE_FRAME) {
- ret = vdec_init(vdec, pbuf->for_4k);
+ ret = vdec_init(vdec, port->is_4k);
if (ret < 0) {
v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "failed\n");
video_component_release(port, pbuf, 2);
@@ -367,14 +366,14 @@ static int video_component_init(struct stream_port_s *port,
}
}
- ret = stbuf_init(pbuf, vdec, false);
+ ret = stbuf_init(pbuf, vdec);
if (ret < 0) {
v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "stbuf_init failed\n");
return ret;
}
/* todo: set path based on port flag */
- ret = vdec_init(vdec, pbuf->for_4k);
+ ret = vdec_init(vdec, port->is_4k);
if (ret < 0) {
v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "vdec_init failed\n");
video_component_release(port, pbuf, 2);
@@ -382,7 +381,7 @@ static int video_component_init(struct stream_port_s *port,
}
if (vdec_dual(vdec)) {
- ret = vdec_init(vdec->slave, pbuf->for_4k);
+ ret = vdec_init(vdec->slave, port->is_4k);
if (ret < 0) {
v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "vdec_init failed\n");
video_component_release(port, pbuf, 2);
@@ -543,7 +542,7 @@ static int vdec_ports_init(struct aml_vdec_adapt *ada_ctx)
if ((vdec->port->type & PORT_TYPE_VIDEO)
&& (vdec->port_flag & PORT_FLAG_VFORMAT)) {
- pvbuf->for_4k = 0;
+ vdec->port->is_4k = false;
if (has_hevc_vdec()) {
if (vdec->port->vformat == VFORMAT_HEVC
|| vdec->port->vformat == VFORMAT_VP9)
diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.h b/drivers/amvdec_ports/aml_vcodec_adapt.h
index b73b9ff..d09f5f0 100644
--- a/drivers/amvdec_ports/aml_vcodec_adapt.h
+++ b/drivers/amvdec_ports/aml_vcodec_adapt.h
@@ -22,7 +22,7 @@
#include <linux/amlogic/media/utils/vformat.h>
#include <linux/amlogic/media/utils/amstream.h>
-#include "../stream_input/parser/streambuf.h"
+#include "../stream_input/amports/streambuf.h"
#include "aml_vcodec_drv.h"
struct aml_vdec_adapt {
diff --git a/drivers/amvdec_ports/vdec_drv_if.h b/drivers/amvdec_ports/vdec_drv_if.h
index a5ab735..579e499 100644
--- a/drivers/amvdec_ports/vdec_drv_if.h
+++ b/drivers/amvdec_ports/vdec_drv_if.h
@@ -23,7 +23,7 @@
#include "aml_vcodec_drv.h"
#include "aml_vcodec_dec.h"
#include "aml_vcodec_util.h"
-#include "../stream_input/parser/streambuf.h"
+#include "../stream_input/amports/streambuf.h"
#define AML_VIDEO_MAGIC CODEC_MODE('A', 'M', 'L', 'V')
diff --git a/drivers/frame_provider/decoder/avs/avs.c b/drivers/frame_provider/decoder/avs/avs.c
index b97cb33..b6e500f 100644
--- a/drivers/frame_provider/decoder/avs/avs.c
+++ b/drivers/frame_provider/decoder/avs/avs.c
@@ -30,7 +30,7 @@
#include <linux/amlogic/media/vfm/vframe_receiver.h>
#include <linux/amlogic/media/vfm/vframe.h>
#include <linux/amlogic/media/utils/vdec_reg.h>
-#include "../../../stream_input/parser/streambuf_reg.h"
+#include "../../../stream_input/amports/streambuf_reg.h"
#include "../utils/amvdec.h"
#include <linux/amlogic/media/registers/register.h>
#include "../../../stream_input/amports/amports_priv.h"
diff --git a/drivers/frame_provider/decoder/avs/avsp_trans.c b/drivers/frame_provider/decoder/avs/avsp_trans.c
index b5dc444..a92dbb9 100644
--- a/drivers/frame_provider/decoder/avs/avsp_trans.c
+++ b/drivers/frame_provider/decoder/avs/avsp_trans.c
@@ -36,7 +36,7 @@
/* #include <mach/am_regs.h> */
#include <linux/module.h>
#include <linux/amlogic/media/utils/vdec_reg.h>
-#include "../../../stream_input/parser/streambuf_reg.h"
+#include "../../../stream_input/amports/streambuf_reg.h"
#include "../utils/amvdec.h"
#include <linux/amlogic/media/registers/register.h>
#include "../../../stream_input/amports/amports_priv.h"
diff --git a/drivers/frame_provider/decoder/avs2/vavs2.c b/drivers/frame_provider/decoder/avs2/vavs2.c
index 4c2cb54..2de21c1 100644
--- a/drivers/frame_provider/decoder/avs2/vavs2.c
+++ b/drivers/frame_provider/decoder/avs2/vavs2.c
@@ -6925,7 +6925,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
if (dec->next_again_flag &&
(!vdec_frame_based(vdec))) {
u32 parser_wr_ptr =
- READ_PARSER_REG(PARSER_VIDEO_WP);
+ STBUF_READ(&vdec->vbuf, get_wp);
if (parser_wr_ptr >= dec->pre_parser_wr_ptr &&
(parser_wr_ptr - dec->pre_parser_wr_ptr) <
again_threshold) {
@@ -6940,8 +6940,8 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
&& pre_decode_buf_level != 0) {
u32 rp, wp, level;
- rp = READ_PARSER_REG(PARSER_VIDEO_RP);
- wp = READ_PARSER_REG(PARSER_VIDEO_WP);
+ rp = STBUF_READ(&vdec->vbuf, get_rp);
+ wp = STBUF_READ(&vdec->vbuf, get_wp);
if (wp < rp)
level = vdec->input.size + wp - rp;
else
@@ -7001,9 +7001,12 @@ static void run(struct vdec_s *vdec, unsigned long mask,
dec->vdec_cb = callback;
/* dec->chunk = vdec_prepare_input(vdec); */
hevc_reset_core(vdec);
- dec->pre_parser_wr_ptr =
- READ_PARSER_REG(PARSER_VIDEO_WP);
+
+ if (vdec_stream_based(vdec)) {
+ dec->pre_parser_wr_ptr =
+ STBUF_READ(&vdec->vbuf, get_wp);
dec->next_again_flag = 0;
+ }
r = vdec_prepare_input(vdec, &dec->chunk);
if (r < 0) {
@@ -7242,10 +7245,10 @@ static void avs2_dump_state(struct vdec_s *vdec)
READ_VREG(HEVC_STREAM_RD_PTR));
avs2_print(dec, 0,
"PARSER_VIDEO_RP=0x%x\n",
- READ_PARSER_REG(PARSER_VIDEO_RP));
+ STBUF_READ(&vdec->vbuf, get_rp));
avs2_print(dec, 0,
"PARSER_VIDEO_WP=0x%x\n",
- READ_PARSER_REG(PARSER_VIDEO_WP));
+ STBUF_READ(&vdec->vbuf, get_wp));
if (input_frame_based(vdec) &&
(debug & PRINT_FLAG_VDEC_DATA)
diff --git a/drivers/frame_provider/decoder/avs_multi/avs_multi.c b/drivers/frame_provider/decoder/avs_multi/avs_multi.c
index f041bf7..dd5a7b6 100644
--- a/drivers/frame_provider/decoder/avs_multi/avs_multi.c
+++ b/drivers/frame_provider/decoder/avs_multi/avs_multi.c
@@ -30,7 +30,7 @@
#include <linux/amlogic/media/vfm/vframe_receiver.h>
#include <linux/amlogic/media/vfm/vframe.h>
#include <linux/amlogic/media/utils/vdec_reg.h>
-#include "../../../stream_input/parser/streambuf_reg.h"
+#include "../../../stream_input/amports/streambuf_reg.h"
#include "../utils/amvdec.h"
#include <linux/amlogic/media/registers/register.h>
#include "../../../stream_input/amports/amports_priv.h"
@@ -3042,7 +3042,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
hw->again_flag &&
(!vdec_frame_based(vdec))) {
u32 parser_wr_ptr =
- READ_PARSER_REG(PARSER_VIDEO_WP);
+ STBUF_READ(&vdec->vbuf, get_rp);
if (parser_wr_ptr >= hw->pre_parser_wr_ptr &&
(parser_wr_ptr - hw->pre_parser_wr_ptr) <
again_threshold) {
@@ -3380,8 +3380,8 @@ static void check_timer_func(unsigned long arg)
READ_VREG(VLD_MEM_VIFIFO_LEVEL),
READ_VREG(VLD_MEM_VIFIFO_WP),
READ_VREG(VLD_MEM_VIFIFO_RP),
- READ_PARSER_REG(PARSER_VIDEO_RP),
- READ_PARSER_REG(PARSER_VIDEO_WP));
+ STBUF_READ(&vdec->vbuf, get_rp),
+ STBUF_READ(&vdec->vbuf, get_wp));
}
}
@@ -3478,9 +3478,10 @@ void (*callback)(struct vdec_s *, void *),
int size, ret;
/* reset everything except DOS_TOP[1] and APB_CBUS[0]*/
- hw->pre_parser_wr_ptr =
- READ_PARSER_REG(PARSER_VIDEO_WP);
-
+ if (vdec_stream_based(vdec)) {
+ hw->pre_parser_wr_ptr =
+ STBUF_READ(&vdec->vbuf, get_wp);
+ }
#if 1
#if DEBUG_MULTI_FLAG > 0
if (hw->decode_pic_count == 0) {
@@ -3574,8 +3575,8 @@ void (*callback)(struct vdec_s *, void *),
READ_VREG(VLD_MEM_VIFIFO_LEVEL),
READ_VREG(VLD_MEM_VIFIFO_WP),
READ_VREG(VLD_MEM_VIFIFO_RP),
- READ_PARSER_REG(PARSER_VIDEO_RP),
- READ_PARSER_REG(PARSER_VIDEO_WP),
+ STBUF_READ(&vdec->vbuf, get_rp),
+ STBUF_READ(&vdec->vbuf, get_wp),
size);
@@ -3785,10 +3786,10 @@ static void vmavs_dump_state(struct vdec_s *vdec)
READ_VREG(VLD_MEM_VIFIFO_RP));
debug_print(hw, 0,
"PARSER_VIDEO_RP=0x%x\n",
- READ_PARSER_REG(PARSER_VIDEO_RP));
+ STBUF_READ(&vdec->vbuf, get_rp));
debug_print(hw, 0,
"PARSER_VIDEO_WP=0x%x\n",
- READ_PARSER_REG(PARSER_VIDEO_WP));
+ STBUF_READ(&vdec->vbuf, get_wp));
if (vdec_frame_based(vdec) &&
(debug & PRINT_FRAMEBASE_DATA)
diff --git a/drivers/frame_provider/decoder/h264/vh264.c b/drivers/frame_provider/decoder/h264/vh264.c
index 3470147..03a1dba 100644
--- a/drivers/frame_provider/decoder/h264/vh264.c
+++ b/drivers/frame_provider/decoder/h264/vh264.c
@@ -43,7 +43,7 @@
#include <linux/amlogic/media/utils/vdec_reg.h>
#include "../utils/amvdec.h"
#include "vh264.h"
-#include "../../../stream_input/parser/streambuf.h"
+#include "../../../stream_input/amports/streambuf.h"
#include <linux/delay.h>
#include <linux/amlogic/media/video_sink/video.h>
#include <linux/amlogic/tee.h>
diff --git a/drivers/frame_provider/decoder/h264_multi/vmh264.c b/drivers/frame_provider/decoder/h264_multi/vmh264.c
index 22eab2b..7e07874 100644
--- a/drivers/frame_provider/decoder/h264_multi/vmh264.c
+++ b/drivers/frame_provider/decoder/h264_multi/vmh264.c
@@ -49,7 +49,7 @@
#include "../utils/vdec.h"
#include "../utils/amvdec.h"
#include "../h264/vh264.h"
-#include "../../../stream_input/parser/streambuf.h"
+#include "../../../stream_input/amports/streambuf.h"
#include <linux/delay.h>
#include <linux/amlogic/media/codec_mm/configs.h>
#include "../utils/decoder_mmu_box.h"
@@ -6771,10 +6771,10 @@ static void vmh264_dump_state(struct vdec_s *vdec)
READ_VREG(VLD_MEM_VIFIFO_RP));
dpb_print(DECODE_ID(hw), 0,
"PARSER_VIDEO_RP=0x%x\n",
- READ_PARSER_REG(PARSER_VIDEO_RP));
+ STBUF_READ(&vdec->vbuf, get_rp));
dpb_print(DECODE_ID(hw), 0,
"PARSER_VIDEO_WP=0x%x\n",
- READ_PARSER_REG(PARSER_VIDEO_WP));
+ STBUF_READ(&vdec->vbuf, get_wp));
if (input_frame_based(vdec) &&
dpb_is_debug(DECODE_ID(hw),
@@ -8633,8 +8633,8 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
&& pre_decode_buf_level != 0) {
u32 rp, wp, level;
- rp = READ_PARSER_REG(PARSER_VIDEO_RP);
- wp = READ_PARSER_REG(PARSER_VIDEO_WP);
+ rp = STBUF_READ(&vdec->vbuf, get_rp);
+ wp = STBUF_READ(&vdec->vbuf, get_wp);
if (wp < rp)
level = vdec->input.size + wp - rp;
else
@@ -8665,8 +8665,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
}
if (hw->next_again_flag &&
(!vdec_frame_based(vdec))) {
- u32 parser_wr_ptr =
- READ_PARSER_REG(PARSER_VIDEO_WP);
+ u32 parser_wr_ptr = STBUF_READ(&vdec->vbuf, get_wp);
if (parser_wr_ptr >= hw->pre_parser_wr_ptr &&
(parser_wr_ptr - hw->pre_parser_wr_ptr) <
again_threshold) {
@@ -8791,9 +8790,11 @@ static void run(struct vdec_s *vdec, unsigned long mask,
kfifo_len(&hw->display_q));
}
- hw->pre_parser_wr_ptr =
- READ_PARSER_REG(PARSER_VIDEO_WP);
- hw->next_again_flag = 0;
+ if (vdec_stream_based(vdec)) {
+ hw->pre_parser_wr_ptr =
+ STBUF_READ(&vdec->vbuf, get_wp);
+ hw->next_again_flag = 0;
+ }
if (hw->reset_bufmgr_flag ||
((error_proc_policy & 0x40) &&
@@ -8887,8 +8888,8 @@ static void run(struct vdec_s *vdec, unsigned long mask,
READ_VREG(VLD_MEM_VIFIFO_LEVEL),
READ_VREG(VLD_MEM_VIFIFO_WP),
READ_VREG(VLD_MEM_VIFIFO_RP),
- READ_PARSER_REG(PARSER_VIDEO_RP),
- READ_PARSER_REG(PARSER_VIDEO_WP),
+ STBUF_READ(&vdec->vbuf, get_rp),
+ STBUF_READ(&vdec->vbuf, get_wp),
size);
start_process_time(hw);
diff --git a/drivers/frame_provider/decoder/h265/vh265.c b/drivers/frame_provider/decoder/h265/vh265.c
index 5accb87..d99b770 100644
--- a/drivers/frame_provider/decoder/h265/vh265.c
+++ b/drivers/frame_provider/decoder/h265/vh265.c
@@ -9390,6 +9390,7 @@ static int hevc_recover(struct hevc_state_s *hevc)
unsigned int hevc_stream_control;
unsigned int hevc_stream_fifo_ctl;
unsigned int hevc_stream_buf_size;
+ struct vdec_s *vdec = hw_to_vdec(hevc);
mutex_lock(&vh265_mutex);
#if 0
@@ -9413,8 +9414,14 @@ static int hevc_recover(struct hevc_state_s *hevc)
msleep(20);
ret = 0;
/* reset */
- WRITE_PARSER_REG(PARSER_VIDEO_RP, READ_VREG(HEVC_STREAM_RD_PTR));
- SET_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR);
+ if (vdec_stream_based(vdec)) {
+ STBUF_WRITE(&vdec->vbuf, set_rp,
+ READ_VREG(HEVC_STREAM_RD_PTR));
+
+ if (!vdec->vbuf.no_parser)
+ SET_PARSER_REG_MASK(PARSER_ES_CONTROL,
+ ES_VID_MAN_RD_PTR);
+ }
hevc_stream_start_addr = READ_VREG(HEVC_STREAM_START_ADDR);
hevc_stream_end_addr = READ_VREG(HEVC_STREAM_END_ADDR);
@@ -12478,8 +12485,8 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
&& pre_decode_buf_level != 0) {
u32 rp, wp, level;
- rp = READ_PARSER_REG(PARSER_VIDEO_RP);
- wp = READ_PARSER_REG(PARSER_VIDEO_WP);
+ rp = STBUF_READ(&vdec->vbuf, get_rp);
+ wp = STBUF_READ(&vdec->vbuf, get_wp);
if (wp < rp)
level = vdec->input.size + wp - rp;
else
@@ -12493,7 +12500,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
if (hevc->next_again_flag &&
(!vdec_frame_based(vdec))) {
u32 parser_wr_ptr =
- READ_PARSER_REG(PARSER_VIDEO_WP);
+ STBUF_READ(&vdec->vbuf, get_wp);
if (parser_wr_ptr >= hevc->pre_parser_wr_ptr &&
(parser_wr_ptr - hevc->pre_parser_wr_ptr) <
again_threshold) {
@@ -12595,9 +12602,11 @@ static void run(struct vdec_s *vdec, unsigned long mask,
hevc_reset_core(vdec);
#ifdef AGAIN_HAS_THRESHOLD
- hevc->pre_parser_wr_ptr =
- READ_PARSER_REG(PARSER_VIDEO_WP);
- hevc->next_again_flag = 0;
+ if (vdec_stream_based(vdec)) {
+ hevc->pre_parser_wr_ptr =
+ STBUF_READ(&vdec->vbuf, get_wp);
+ hevc->next_again_flag = 0;
+ }
#endif
r = vdec_prepare_input(vdec, &hevc->chunk);
if (r < 0) {
@@ -12631,8 +12640,8 @@ static void run(struct vdec_s *vdec, unsigned long mask,
READ_VREG(HEVC_STREAM_LEVEL),
READ_VREG(HEVC_STREAM_WR_PTR),
READ_VREG(HEVC_STREAM_RD_PTR),
- READ_PARSER_REG(PARSER_VIDEO_RP),
- READ_PARSER_REG(PARSER_VIDEO_WP),
+ STBUF_READ(&vdec->vbuf, get_rp),
+ STBUF_READ(&vdec->vbuf, get_wp),
hevc->start_shift_bytes
);
if ((get_dbg_flag(hevc) & PRINT_FRAMEBASE_DATA) &&
@@ -13153,10 +13162,10 @@ static void vh265_dump_state(struct vdec_s *vdec)
READ_VREG(HEVC_STREAM_RD_PTR));
hevc_print(hevc, 0,
"PARSER_VIDEO_RP=0x%x\n",
- READ_PARSER_REG(PARSER_VIDEO_RP));
+ STBUF_READ(&vdec->vbuf, get_rp));
hevc_print(hevc, 0,
"PARSER_VIDEO_WP=0x%x\n",
- READ_PARSER_REG(PARSER_VIDEO_WP));
+ STBUF_READ(&vdec->vbuf, get_wp));
if (input_frame_based(vdec) &&
(get_dbg_flag(hevc) & PRINT_FRAMEBASE_DATA)
diff --git a/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c b/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
index 33b787a..413ce81 100644
--- a/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
+++ b/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
@@ -721,10 +721,10 @@ static void vmjpeg_dump_state(struct vdec_s *vdec)
READ_VREG(VLD_MEM_VIFIFO_RP));
mmjpeg_debug_print(DECODE_ID(hw), 0,
"PARSER_VIDEO_RP=0x%x\n",
- READ_PARSER_REG(PARSER_VIDEO_RP));
+ STBUF_READ(&vdec->vbuf, get_rp));
mmjpeg_debug_print(DECODE_ID(hw), 0,
"PARSER_VIDEO_WP=0x%x\n",
- READ_PARSER_REG(PARSER_VIDEO_WP));
+ STBUF_READ(&vdec->vbuf, get_wp));
if (input_frame_based(vdec) &&
debug_enable & PRINT_FRAMEBASE_DATA
) {
@@ -802,7 +802,7 @@ static void check_timer_func(unsigned long arg)
"%s: %d,buftl=%x:%x:%x:%x\n",
__func__, __LINE__,
READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL),
- READ_PARSER_REG(PARSER_VIDEO_WP),
+ STBUF_READ(&vdec->vbuf, get_wp),
READ_VREG(VLD_MEM_VIFIFO_LEVEL),
READ_VREG(VLD_MEM_VIFIFO_WP));
@@ -1151,8 +1151,8 @@ static unsigned long run_ready(struct vdec_s *vdec,
&& pre_decode_buf_level != 0) {
u32 rp, wp, level;
- rp = READ_PARSER_REG(PARSER_VIDEO_RP);
- wp = READ_PARSER_REG(PARSER_VIDEO_WP);
+ rp = STBUF_READ(&vdec->vbuf, get_rp);
+ wp = STBUF_READ(&vdec->vbuf, get_wp);
if (wp < rp)
level = vdec->input.size + wp - rp;
else
@@ -1205,7 +1205,7 @@ static void run(struct vdec_s *vdec, unsigned long mask,
"%s: %d,r=%d,buftl=%x:%x:%x\n",
__func__, __LINE__, ret,
READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL),
- READ_PARSER_REG(PARSER_VIDEO_WP),
+ STBUF_READ(&vdec->vbuf, get_rp),
READ_VREG(VLD_MEM_VIFIFO_WP));
hw->dec_result = DEC_RESULT_AGAIN;
diff --git a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
index 27d62a9..4116688 100644
--- a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
+++ b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
@@ -2572,10 +2572,11 @@ static void vmpeg2_dump_state(struct vdec_s *vdec)
READ_VREG(VLD_MEM_VIFIFO_RP));
debug_print(DECODE_ID(hw), 0,
"PARSER_VIDEO_RP=0x%x\n",
- READ_PARSER_REG(PARSER_VIDEO_RP));
+ STBUF_READ(&vdec->vbuf, get_rp));
debug_print(DECODE_ID(hw), 0,
"PARSER_VIDEO_WP=0x%x\n",
- READ_PARSER_REG(PARSER_VIDEO_WP));
+ STBUF_READ(&vdec->vbuf, get_wp));
+
if (vdec_frame_based(vdec) &&
debug_enable & PRINT_FRAMEBASE_DATA
) {
@@ -2950,8 +2951,8 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
&& pre_decode_buf_level != 0) {
u32 rp, wp, level;
- rp = READ_PARSER_REG(PARSER_VIDEO_RP);
- wp = READ_PARSER_REG(PARSER_VIDEO_WP);
+ rp = STBUF_READ(&vdec->vbuf, get_rp);
+ wp = STBUF_READ(&vdec->vbuf, get_wp);
if (wp < rp)
level = vdec->input.size + wp - rp;
else
@@ -2967,7 +2968,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
if (hw->next_again_flag&&
(!vdec_frame_based(vdec))) {
u32 parser_wr_ptr =
- READ_PARSER_REG(PARSER_VIDEO_WP);
+ STBUF_READ(&vdec->vbuf, get_wp);
if (parser_wr_ptr >= hw->pre_parser_wr_ptr &&
(parser_wr_ptr - hw->pre_parser_wr_ptr) <
again_threshold) {
@@ -3056,9 +3057,11 @@ void (*callback)(struct vdec_s *, void *),
hw->vdec_cb = callback;
#ifdef AGAIN_HAS_THRESHOLD
+ if (vdec_stream_based(vdec)) {
hw->pre_parser_wr_ptr =
- READ_PARSER_REG(PARSER_VIDEO_WP);
+ STBUF_READ(&vdec->vbuf, get_wp);
hw->next_again_flag = 0;
+ }
#endif
size = vdec_prepare_input(vdec, &hw->chunk);
@@ -3136,8 +3139,8 @@ void (*callback)(struct vdec_s *, void *),
READ_VREG(VLD_MEM_VIFIFO_LEVEL),
READ_VREG(VLD_MEM_VIFIFO_WP),
READ_VREG(VLD_MEM_VIFIFO_RP),
- READ_PARSER_REG(PARSER_VIDEO_RP),
- READ_PARSER_REG(PARSER_VIDEO_WP),
+ STBUF_READ(&vdec->vbuf, get_rp),
+ STBUF_READ(&vdec->vbuf, get_wp),
size);
if (vdec->mvfrm && hw->chunk)
diff --git a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
index c6bea5b..9cf5629 100644
--- a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
+++ b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
@@ -1800,10 +1800,11 @@ static void vmpeg4_dump_state(struct vdec_s *vdec)
READ_VREG(VLD_MEM_VIFIFO_RP));
mmpeg4_debug_print(DECODE_ID(hw), 0,
"PARSER_VIDEO_RP=0x%x\n",
- READ_PARSER_REG(PARSER_VIDEO_RP));
+ STBUF_READ(&vdec->vbuf, get_rp));
mmpeg4_debug_print(DECODE_ID(hw), 0,
"PARSER_VIDEO_WP=0x%x\n",
- READ_PARSER_REG(PARSER_VIDEO_WP));
+ STBUF_READ(&vdec->vbuf, get_wp));
+
if (vdec_frame_based(vdec) &&
debug_enable & PRINT_FRAMEBASE_DATA) {
int jj;
@@ -2182,8 +2183,8 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
&& pre_decode_buf_level != 0) {
u32 rp, wp, level;
- rp = READ_PARSER_REG(PARSER_VIDEO_RP);
- wp = READ_PARSER_REG(PARSER_VIDEO_WP);
+ rp = STBUF_READ(&vdec->vbuf, get_rp);
+ wp = STBUF_READ(&vdec->vbuf, get_wp);
if (wp < rp)
level = vdec->input.size + wp - rp;
else
@@ -2329,8 +2330,8 @@ static void run(struct vdec_s *vdec, unsigned long mask,
READ_VREG(VLD_MEM_VIFIFO_LEVEL),
READ_VREG(VLD_MEM_VIFIFO_WP),
READ_VREG(VLD_MEM_VIFIFO_RP),
- READ_PARSER_REG(PARSER_VIDEO_RP),
- READ_PARSER_REG(PARSER_VIDEO_WP));
+ STBUF_READ(&vdec->vbuf, get_rp),
+ STBUF_READ(&vdec->vbuf, get_wp));
hw->dec_result = DEC_RESULT_NONE;
if (vdec->mc_loaded) {
diff --git a/drivers/frame_provider/decoder/real/vreal.c b/drivers/frame_provider/decoder/real/vreal.c
index a752f78..49bd408 100644
--- a/drivers/frame_provider/decoder/real/vreal.c
+++ b/drivers/frame_provider/decoder/real/vreal.c
@@ -41,8 +41,8 @@
#include <linux/amlogic/media/utils/vdec_reg.h>
#include "../utils/amvdec.h"
-#include "../../../stream_input/parser/streambuf.h"
-#include "../../../stream_input/parser/streambuf_reg.h"
+#include "../../../stream_input/amports/streambuf.h"
+#include "../../../stream_input/amports/streambuf_reg.h"
#include "../../../stream_input/parser/rmparser.h"
#include "vreal.h"
diff --git a/drivers/frame_provider/decoder/utils/vdec.c b/drivers/frame_provider/decoder/utils/vdec.c
index e2993a6..dfcd1c8 100644
--- a/drivers/frame_provider/decoder/utils/vdec.c
+++ b/drivers/frame_provider/decoder/utils/vdec.c
@@ -41,6 +41,7 @@
#include <linux/time.h>
#include <linux/amlogic/media/utils/vdec_reg.h>
+#include "../../../stream_input/amports/streambuf.h"
#include "vdec.h"
#include "vdec_trace.h"
#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
@@ -126,6 +127,8 @@ static int enable_mvdec_info = 1;
int decode_underflow = 0;
+int enable_stream_mode_multi_dec;
+
#define CANVAS_MAX_SIZE (AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1)
struct am_reg {
@@ -771,8 +774,8 @@ void vdec_update_streambuff_status(void)
(vdec->need_more_data & VDEC_NEED_MORE_DATA)) {
u32 rp, wp, level;
- rp = READ_PARSER_REG(PARSER_VIDEO_RP);
- wp = READ_PARSER_REG(PARSER_VIDEO_WP);
+ rp = STBUF_READ(&vdec->vbuf, get_rp);
+ wp = STBUF_READ(&vdec->vbuf, get_wp);
if (wp < rp)
level = input->size + wp - rp;
else
@@ -1258,13 +1261,13 @@ static void vdec_sync_input_read(struct vdec_s *vdec)
other =
vdec_get_associate(vdec)->input.swap_rp;
if (me > other) {
- WRITE_PARSER_REG(PARSER_VIDEO_RP,
- vdec_get_associate(vdec)->
- input.swap_rp);
+ STBUF_WRITE(&vdec->vbuf, set_rp,
+ vdec_get_associate(vdec)->input.swap_rp);
return;
}
}
- WRITE_PARSER_REG(PARSER_VIDEO_RP,
+
+ STBUF_WRITE(&vdec->vbuf, set_rp,
READ_VREG(VLD_MEM_VIFIFO_RP));
} else if (vdec->input.target == VDEC_INPUT_TARGET_HEVC) {
me = READ_VREG(HEVC_SHIFT_BYTE_COUNT);
@@ -1273,20 +1276,19 @@ static void vdec_sync_input_read(struct vdec_s *vdec)
me += 1ULL << 32;
other = vdec_get_associate(vdec)->input.streaming_rp;
if (me > other) {
- WRITE_PARSER_REG(PARSER_VIDEO_RP,
- vdec_get_associate(vdec)->
- input.swap_rp);
+ STBUF_WRITE(&vdec->vbuf, set_rp,
+ vdec_get_associate(vdec)->input.swap_rp);
return;
}
- WRITE_PARSER_REG(PARSER_VIDEO_RP,
+ STBUF_WRITE(&vdec->vbuf, set_rp,
READ_VREG(HEVC_STREAM_RD_PTR));
}
} else if (vdec->input.target == VDEC_INPUT_TARGET_VLD) {
- WRITE_PARSER_REG(PARSER_VIDEO_RP,
+ STBUF_WRITE(&vdec->vbuf, set_rp,
READ_VREG(VLD_MEM_VIFIFO_RP));
} else if (vdec->input.target == VDEC_INPUT_TARGET_HEVC) {
- WRITE_PARSER_REG(PARSER_VIDEO_RP,
+ STBUF_WRITE(&vdec->vbuf, set_rp,
READ_VREG(HEVC_STREAM_RD_PTR));
}
}
@@ -1298,10 +1300,10 @@ static void vdec_sync_input_write(struct vdec_s *vdec)
if (vdec->input.target == VDEC_INPUT_TARGET_VLD) {
WRITE_VREG(VLD_MEM_VIFIFO_WP,
- READ_PARSER_REG(PARSER_VIDEO_WP));
+ STBUF_READ(&vdec->vbuf, get_wp));
} else if (vdec->input.target == VDEC_INPUT_TARGET_HEVC) {
WRITE_VREG(HEVC_STREAM_WR_PTR,
- READ_PARSER_REG(PARSER_VIDEO_WP));
+ STBUF_READ(&vdec->vbuf, get_wp));
}
}
@@ -1474,6 +1476,10 @@ int vdec_prepare_input(struct vdec_s *vdec, struct vframe_chunk_s **p)
WRITE_VREG(VLD_MEM_VIFIFO_CONTROL,
(0x11 << 16) | (1<<10));
+ if (vdec->vbuf.no_parser)
+ SET_VREG_MASK(VLD_MEM_VIFIFO_CONTROL,
+ 7 << 3);
+
/* sync with front end */
vdec_sync_input_read(vdec);
vdec_sync_input_write(vdec);
@@ -1509,6 +1515,9 @@ int vdec_prepare_input(struct vdec_s *vdec, struct vframe_chunk_s **p)
wp = READ_VREG(HEVC_STREAM_WR_PTR);
+ if (vdec->vbuf.no_parser)
+ SET_VREG_MASK(HEVC_STREAM_CONTROL,
+ 7 << 4);
/*pr_info("vdec: restore context\r\n");*/
}
@@ -1528,13 +1537,15 @@ int vdec_prepare_input(struct vdec_s *vdec, struct vframe_chunk_s **p)
WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2);
WRITE_VREG(VLD_MEM_VIFIFO_RP, input->start);
WRITE_VREG(VLD_MEM_VIFIFO_WP,
- READ_PARSER_REG(PARSER_VIDEO_WP));
-
+ STBUF_READ(&vdec->vbuf, get_wp));
rp = READ_VREG(VLD_MEM_VIFIFO_RP);
/* enable */
WRITE_VREG(VLD_MEM_VIFIFO_CONTROL,
(0x11 << 16) | (1<<10));
+ if (vdec->vbuf.no_parser)
+ SET_VREG_MASK(VLD_MEM_VIFIFO_CONTROL,
+ 7 << 3);
wp = READ_VREG(VLD_MEM_VIFIFO_WP);
@@ -1546,13 +1557,14 @@ int vdec_prepare_input(struct vdec_s *vdec, struct vframe_chunk_s **p)
WRITE_VREG(HEVC_STREAM_RD_PTR,
input->start);
WRITE_VREG(HEVC_STREAM_WR_PTR,
- READ_PARSER_REG(PARSER_VIDEO_WP));
-
+ STBUF_READ(&vdec->vbuf, get_wp));
rp = READ_VREG(HEVC_STREAM_RD_PTR);
wp = READ_VREG(HEVC_STREAM_WR_PTR);
fifo_len = (READ_VREG(HEVC_STREAM_FIFO_CTL)
>> 16) & 0x7f;
-
+ if (vdec->vbuf.no_parser)
+ SET_VREG_MASK(HEVC_STREAM_CONTROL,
+ 7 << 4);
/* enable */
}
}
@@ -1582,10 +1594,15 @@ void vdec_enable_input(struct vdec_s *vdec)
SET_VREG_MASK(VLD_MEM_VIFIFO_CONTROL, (1<<2) | (1<<1));
else if (input->target == VDEC_INPUT_TARGET_HEVC) {
SET_VREG_MASK(HEVC_STREAM_CONTROL, 1);
- if (vdec_stream_based(vdec))
- CLEAR_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4);
- else
+ if (vdec_stream_based(vdec)) {
+ if (vdec->vbuf.no_parser)
+ /*set endian for non-parser mode. */
+ SET_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4);
+ else
+ CLEAR_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4);
+ } else
SET_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4);
+
SET_VREG_MASK(HEVC_STREAM_FIFO_CTL, (1<<29));
}
}
@@ -1624,10 +1641,10 @@ bool vdec_has_more_input(struct vdec_s *vdec)
else {
if (input->target == VDEC_INPUT_TARGET_VLD)
return READ_VREG(VLD_MEM_VIFIFO_WP) !=
- READ_PARSER_REG(PARSER_VIDEO_WP);
+ STBUF_READ(&vdec->vbuf, get_wp);
else {
return (READ_VREG(HEVC_STREAM_WR_PTR) & ~0x3) !=
- (READ_PARSER_REG(PARSER_VIDEO_WP) & ~0x3);
+ (STBUF_READ(&vdec->vbuf, get_wp) & ~0x3);
}
}
}
@@ -2153,13 +2170,15 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k)
*todo: VFM patch control should be configurable,
* for now all stream based input uses default VFM path.
*/
- if (vdec_stream_based(vdec) && !vdec_dual(vdec)) {
- if (vdec_core->vfm_vdec == NULL) {
- pr_debug("vdec_init set vfm decoder %p\n", vdec);
- vdec_core->vfm_vdec = vdec;
- } else {
- pr_info("vdec_init vfm path busy.\n");
- return -EBUSY;
+ if (!enable_stream_mode_multi_dec) {
+ if (vdec_stream_based(vdec) && !vdec_dual(vdec)) {
+ if (vdec_core->vfm_vdec == NULL) {
+ pr_debug("vdec_init set vfm decoder %p\n", vdec);
+ vdec_core->vfm_vdec = vdec;
+ } else {
+ pr_info("vdec_init vfm path busy.\n");
+ return -EBUSY;
+ }
}
}
@@ -2186,8 +2205,13 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k)
atomic_set(&p->inirq_flag, 0);
atomic_set(&p->inirq_thread_flag, 0);
/* todo */
- if (!vdec_dual(vdec))
- p->use_vfm_path = vdec_stream_based(vdec);
+ if (!vdec_dual(vdec)) {
+ p->use_vfm_path =
+ enable_stream_mode_multi_dec ?
+ vdec_single(vdec) :
+ vdec_stream_based(vdec);
+ }
+
if (debugflags & 0x4)
p->use_vfm_path = 1;
/* vdec_dev_reg.flag = 0; */
@@ -2199,6 +2223,20 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k)
#ifdef FRAME_CHECK
vdec_frame_check_init(vdec);
#endif
+ /* stream buffer init. */
+ if (vdec->vbuf.ops) {
+ r = vdec->vbuf.ops->init(&vdec->vbuf, vdec);
+ if (r) {
+ pr_err("%s stream buffer init err (%d)\n", dev_name, r);
+
+ mutex_lock(&vdec_mutex);
+ inited_vcodec_num--;
+ mutex_unlock(&vdec_mutex);
+
+ goto error;
+ }
+ }
+
p->dev = platform_device_register_data(
&vdec_core->vdec_core_platform_device->dev,
dev_name,
@@ -2241,15 +2279,17 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k)
/* create IONVIDEO instance and connect decoder's
* vf_provider interface to it
*/
- if (p->type != VDEC_TYPE_FRAME_BLOCK) {
- r = -ENODEV;
- pr_err("vdec: Incorrect decoder type\n");
+ if (!enable_stream_mode_multi_dec) {
+ if (p->type != VDEC_TYPE_FRAME_BLOCK) {
+ r = -ENODEV;
+ pr_err("vdec: Incorrect decoder type\n");
- mutex_lock(&vdec_mutex);
- inited_vcodec_num--;
- mutex_unlock(&vdec_mutex);
+ mutex_lock(&vdec_mutex);
+ inited_vcodec_num--;
+ mutex_unlock(&vdec_mutex);
- goto error;
+ goto error;
+ }
}
if (strncmp("disable", vfm_path, strlen("disable"))) {
@@ -2557,6 +2597,10 @@ void vdec_release(struct vdec_s *vdec)
platform_device_unregister(vdec->dev);
/*Check if the vdec still in connected list, if yes, delete it*/
vdec_connect_list_force_clear(vdec_core, vdec);
+
+ if (vdec->vbuf.ops)
+ vdec->vbuf.ops->release(&vdec->vbuf);
+
pr_debug("vdec_release instance %p, total %d\n", vdec,
atomic_read(&vdec_core->vdec_nr));
vdec_destroy(vdec);
@@ -2903,8 +2947,8 @@ unsigned long vdec_ready_to_run(struct vdec_s *vdec, unsigned long mask)
if (input && input_stream_based(input) && !input->eos) {
u32 rp, wp, level;
- rp = READ_PARSER_REG(PARSER_VIDEO_RP);
- wp = READ_PARSER_REG(PARSER_VIDEO_WP);
+ rp = STBUF_READ(&vdec->vbuf, get_rp);
+ wp = STBUF_READ(&vdec->vbuf, get_wp);
if (wp < rp)
level = input->size + wp - rp;
else
@@ -4523,6 +4567,29 @@ static ssize_t show_debug(struct class *class,
}
#endif
+int show_stream_buffer_status(char *buf,
+ int (*callback) (struct stream_buf_s *, char *))
+{
+ char *pbuf = buf;
+ struct vdec_s *vdec;
+ struct vdec_core_s *core = vdec_core;
+ u64 flags = vdec_core_lock(vdec_core);
+
+ list_for_each_entry(vdec,
+ &core->connected_vdec_list, list) {
+ if ((vdec->status == VDEC_STATUS_CONNECTED
+ || vdec->status == VDEC_STATUS_ACTIVE)) {
+ if (vdec_frame_based(vdec))
+ continue;
+ pbuf += callback(&vdec->vbuf, pbuf);
+ }
+ }
+ vdec_core_unlock(vdec_core, flags);
+
+ return pbuf - buf;
+}
+EXPORT_SYMBOL(show_stream_buffer_status);
+
static ssize_t store_vdec_vfm_path(struct class *class,
struct class_attribute *attr,
const char *buf, size_t count)
@@ -5447,6 +5514,10 @@ MODULE_PARM_DESC(max_di_instance,
module_param(debug_vdetect, int, 0664);
MODULE_PARM_DESC(debug_vdetect, "\n debug_vdetect\n");
+module_param(enable_stream_mode_multi_dec, int, 0664);
+EXPORT_SYMBOL(enable_stream_mode_multi_dec);
+MODULE_PARM_DESC(enable_stream_mode_multi_dec,
+ "\n enable multi-decoding on stream mode. \n");
/*
*module_init(vdec_module_init);
*module_exit(vdec_module_exit);
diff --git a/drivers/frame_provider/decoder/utils/vdec.h b/drivers/frame_provider/decoder/utils/vdec.h
index 12fa840..f991850 100644
--- a/drivers/frame_provider/decoder/utils/vdec.h
+++ b/drivers/frame_provider/decoder/utils/vdec.h
@@ -31,6 +31,8 @@
#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_VDEC
#include <trace/events/meson_atrace.h>
/*#define CONFIG_AM_VDEC_DV*/
+#include "../../../stream_input/amports/streambuf.h"
+#include "../../../stream_input/amports/stream_buffer_base.h"
#include "vdec_input.h"
#include "frame_check.h"
@@ -178,6 +180,7 @@ struct vdec_s {
struct vdec_s *master;
struct vdec_s *slave;
struct stream_port_s *port;
+ struct stream_buf_s vbuf;
int status;
int next_status;
int type;
@@ -460,4 +463,7 @@ extern u32 vdec_get_frame_vdec(struct vdec_s *vdec, struct vframe_counter_s *t
int vdec_get_frame_num(struct vdec_s *vdec);
+int show_stream_buffer_status(char *buf,
+ int (*callback) (struct stream_buf_s *, char *));
+
#endif /* VDEC_H */
diff --git a/drivers/frame_provider/decoder/vav1/vav1.c b/drivers/frame_provider/decoder/vav1/vav1.c
index e84ee3e..93578b5 100644
--- a/drivers/frame_provider/decoder/vav1/vav1.c
+++ b/drivers/frame_provider/decoder/vav1/vav1.c
@@ -9284,10 +9284,10 @@ static void av1_dump_state(struct vdec_s *vdec)
READ_VREG(HEVC_STREAM_RD_PTR));
av1_print(hw, 0,
"PARSER_VIDEO_RP=0x%x\n",
- READ_PARSER_REG(PARSER_VIDEO_RP));
+ STBUF_READ(&vdec->vbuf, get_rp));
av1_print(hw, 0,
"PARSER_VIDEO_WP=0x%x\n",
- READ_PARSER_REG(PARSER_VIDEO_WP));
+ STBUF_READ(&vdec->vbuf, get_wp));
if (input_frame_based(vdec) &&
(debug & PRINT_FLAG_VDEC_DATA)
diff --git a/drivers/frame_provider/decoder/vp9/vvp9.c b/drivers/frame_provider/decoder/vp9/vvp9.c
index c9aee91..acf2db8 100644
--- a/drivers/frame_provider/decoder/vp9/vvp9.c
+++ b/drivers/frame_provider/decoder/vp9/vvp9.c
@@ -10463,10 +10463,10 @@ static void vp9_dump_state(struct vdec_s *vdec)
READ_VREG(HEVC_STREAM_RD_PTR));
vp9_print(pbi, 0,
"PARSER_VIDEO_RP=0x%x\n",
- READ_PARSER_REG(PARSER_VIDEO_RP));
+ STBUF_READ(&vdec->vbuf, get_rp));
vp9_print(pbi, 0,
"PARSER_VIDEO_WP=0x%x\n",
- READ_PARSER_REG(PARSER_VIDEO_WP));
+ STBUF_READ(&vdec->vbuf, get_wp));
if (input_frame_based(vdec) &&
(debug & PRINT_FLAG_VDEC_DATA)
diff --git a/drivers/stream_input/Makefile b/drivers/stream_input/Makefile
index a6cedab..36efa14 100644
--- a/drivers/stream_input/Makefile
+++ b/drivers/stream_input/Makefile
@@ -2,8 +2,11 @@ obj-m += stream_input.o
stream_input-objs += amports/amstream.o
stream_input-objs += amports/adec.o
-stream_input-objs += parser/thread_rw.o
-stream_input-objs += parser/streambuf.o
+stream_input-objs += amports/thread_rw.o
+stream_input-objs += amports/streambuf.o
+stream_input-objs += amports/stream_buffer_base.o
+stream_input-objs += amports/stream_buffer_interface.o
+
stream_input-objs += parser/esparser.o
stream_input-objs += parser/tsdemux.o
stream_input-objs += parser/psparser.o
diff --git a/drivers/stream_input/amports/adec.c b/drivers/stream_input/amports/adec.c
index 5bca205..0828388 100644
--- a/drivers/stream_input/amports/adec.c
+++ b/drivers/stream_input/amports/adec.c
@@ -25,7 +25,7 @@
#include <linux/amlogic/media/frame_sync/ptsserv.h>
#include <linux/amlogic/media/registers/register.h>
#include <linux/amlogic/media/codec_mm/configs.h>
-#include "../parser/streambuf.h"
+#include "../amports/streambuf.h"
#include <linux/module.h>
#include <linux/of.h>
#include "amports_priv.h"
diff --git a/drivers/stream_input/amports/adec.h b/drivers/stream_input/amports/adec.h
index f06f73a..1ad276f 100644
--- a/drivers/stream_input/amports/adec.h
+++ b/drivers/stream_input/amports/adec.h
@@ -18,7 +18,7 @@
#ifndef ADEC_H
#define ADEC_H
-#include "../parser/streambuf.h"
+#include "../amports/streambuf.h"
#include <linux/amlogic/media/utils/aformat.h>
extern s32 adec_init(struct stream_port_s *port);
diff --git a/drivers/stream_input/amports/amports_priv.h b/drivers/stream_input/amports/amports_priv.h
index b09118d..ffead01 100644
--- a/drivers/stream_input/amports/amports_priv.h
+++ b/drivers/stream_input/amports/amports_priv.h
@@ -17,7 +17,7 @@
#ifndef AMPORTS_PRIV_HEAD_HH
#define AMPORTS_PRIV_HEAD_HH
-#include "../parser/streambuf.h"
+#include "../amports/streambuf.h"
#include "../../common/media_clock/switch/amports_gate.h"
#include <linux/amlogic/media/vfm/vframe.h>
#include <linux/amlogic/media/registers/register.h>
diff --git a/drivers/stream_input/amports/amstream.c b/drivers/stream_input/amports/amstream.c
index 9f747e4..916a656 100644
--- a/drivers/stream_input/amports/amstream.c
+++ b/drivers/stream_input/amports/amstream.c
@@ -56,8 +56,8 @@
/* #include <mach/mod_gate.h> */
/* #include <mach/power_gate.h> */
#endif
-#include "../parser/streambuf.h"
-#include "../parser/streambuf_reg.h"
+#include "../amports/streambuf.h"
+#include "../amports/streambuf_reg.h"
#include "../parser/tsdemux.h"
#include "../parser/psparser.h"
#include "../parser/esparser.h"
@@ -67,7 +67,7 @@
#include "amports_priv.h"
#include <linux/amlogic/media/utils/amports_config.h>
#include <linux/amlogic/media/frame_sync/tsync_pcr.h>
-#include "../parser/thread_rw.h"
+#include "../amports/thread_rw.h"
#include <linux/firmware.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
@@ -83,6 +83,7 @@
#include "../../common/chips/chips.h"
#include "../../common/chips/decoder_cpu_ver_info.h"
#include "../subtitle/subtitle.h"
+#include "stream_buffer_base.h"
//#define G12A_BRINGUP_DEBUG
@@ -122,6 +123,8 @@ static int def_vstreambuf_sizeM =
(DEFAULT_VIDEO_BUFFER_SIZE >> 20);
static int slow_input;
+extern int enable_stream_mode_multi_dec;
+
/* #define DATA_DEBUG */
static int use_bufferlevelx10000 = 10000;
static int reset_canuse_buferlevel(int level);
@@ -520,7 +523,7 @@ static void amstream_change_vbufsize(struct port_priv_s *priv,
pr_info("streambuf is alloced before\n");
return;
}
- if (pvbuf->for_4k) {
+ if (priv->port->is_4k) {
pvbuf->buf_size = def_4k_vstreambuf_sizeM * SZ_1M;
if (priv->vdec->port_flag & PORT_FLAG_DRM)
pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP;
@@ -547,7 +550,7 @@ static bool port_get_inited(struct port_priv_s *priv)
if (port->type & PORT_TYPE_VIDEO) {
struct vdec_s *vdec = priv->vdec;
- return vdec->port_flag & PORT_FLAG_INITED;
+ return vdec ? vdec->port_flag & PORT_FLAG_INITED : 0;
}
return port->flag & PORT_FLAG_INITED;
@@ -571,20 +574,16 @@ static void port_set_inited(struct port_priv_s *priv)
static void video_port_release(struct port_priv_s *priv,
struct stream_buf_s *pbuf, int release_num)
{
- struct stream_port_s *port = priv->port;
struct vdec_s *vdec = priv->vdec;
struct vdec_s *slave = NULL;
- bool is_multidec = !vdec_single(vdec);
+
+ if (!vdec)
+ return;
switch (release_num) {
default:
/*fallthrough*/
case 0: /*release all */
- /*fallthrough*/
- case 4:
- if ((port->type & PORT_TYPE_FRAME) == 0)
- esparser_release(pbuf);
- /*fallthrough*/
case 3:
if (vdec->slave)
slave = vdec->slave;
@@ -593,10 +592,6 @@ static void video_port_release(struct port_priv_s *priv,
vdec_release(slave);
priv->vdec = NULL;
/*fallthrough*/
- case 2:
- if ((port->type & PORT_TYPE_FRAME) == 0)
- stbuf_release(pbuf, is_multidec);
- /*fallthrough*/
case 1:
;
}
@@ -620,13 +615,13 @@ static int video_port_init(struct port_priv_s *priv,
if (port->vformat == VFORMAT_H264_4K2K ||
(priv->vdec->sys_info->height *
priv->vdec->sys_info->width) > 1920*1088) {
- pbuf->for_4k = 1;
+ port->is_4k = true;
if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX
&& port->vformat == VFORMAT_H264) {
vdec_poweron(VDEC_HEVC);
}
} else {
- pbuf->for_4k = 0;
+ port->is_4k = false;
}
if (port->type & PORT_TYPE_FRAME) {
@@ -636,7 +631,6 @@ static int video_port_init(struct port_priv_s *priv,
if (r < 0) {
pr_err("video_port_init %d, vdec_init failed\n",
__LINE__);
- video_port_release(priv, pbuf, 2);
return r;
}
@@ -647,9 +641,9 @@ static int video_port_init(struct port_priv_s *priv,
(priv->vdec->sys_info->height *
priv->vdec->sys_info->width) > 1920*1088);
if (r < 0) {
+ vdec_release(vdec);
pr_err("video_port_init %d, vdec_init failed\n",
__LINE__);
- video_port_release(priv, pbuf, 2);
return r;
}
}
@@ -667,12 +661,6 @@ static int video_port_init(struct port_priv_s *priv,
}
}
- r = stbuf_init(pbuf, vdec, false);
- if (r < 0) {
- pr_err("video_port_init %d, stbuf_init failed\n", __LINE__);
- return r;
- }
-
/* todo: set path based on port flag */
r = vdec_init(vdec,
(priv->vdec->sys_info->height *
@@ -680,8 +668,7 @@ static int video_port_init(struct port_priv_s *priv,
if (r < 0) {
pr_err("video_port_init %d, vdec_init failed\n", __LINE__);
- video_port_release(priv, pbuf, 2);
- return r;
+ goto err;
}
if (vdec_dual(vdec)) {
@@ -689,25 +676,20 @@ static int video_port_init(struct port_priv_s *priv,
(priv->vdec->sys_info->height *
priv->vdec->sys_info->width) > 1920*1088);
if (r < 0) {
- pr_err("video_port_init %d, vdec_init failed\n",
- __LINE__);
- video_port_release(priv, pbuf, 2);
- return r;
- }
- }
-
- if (port->type & PORT_TYPE_ES) {
- r = esparser_init(pbuf, vdec);
- if (r < 0) {
- video_port_release(priv, pbuf, 3);
- pr_err("esparser_init() failed\n");
- return r;
+ pr_err("video_port_init %d, vdec_init failed\n", __LINE__);
+ goto err;
}
}
- pbuf->flag |= BUF_FLAG_IN_USE;
-
return 0;
+err:
+ if (vdec->slave)
+ vdec_release(vdec->slave);
+ if (vdec)
+ vdec_release(vdec);
+ priv->vdec = NULL;
+
+ return r;
}
static void audio_port_release(struct stream_port_s *port,
@@ -725,7 +707,7 @@ static void audio_port_release(struct stream_port_s *port,
adec_release(port->vformat);
/*fallthrough*/
case 2:
- stbuf_release(pbuf, false);
+ stbuf_release(pbuf);
/*fallthrough*/
case 1:
;
@@ -755,9 +737,9 @@ static int audio_port_reset(struct stream_port_s *port,
pr_info("audio_port_reset begin\n");
pts_stop(PTS_TYPE_AUDIO);
- stbuf_release(pbuf, false);
+ stbuf_release(pbuf);
- r = stbuf_init(pbuf, NULL, false);
+ r = stbuf_init(pbuf, NULL);
if (r < 0) {
mutex_unlock(&amstream_mutex);
return r;
@@ -804,9 +786,9 @@ static int sub_port_reset(struct stream_port_s *port,
port->flag &= (~PORT_FLAG_INITED);
- stbuf_release(pbuf, false);
+ stbuf_release(pbuf);
- r = stbuf_init(pbuf, NULL, false);
+ r = stbuf_init(pbuf, NULL);
if (r < 0)
return r;
@@ -838,7 +820,7 @@ static int audio_port_init(struct stream_port_s *port,
return 0;
}
- r = stbuf_init(pbuf, NULL, false);
+ r = stbuf_init(pbuf, NULL);
if (r < 0)
return r;
r = adec_init(port);
@@ -865,14 +847,14 @@ static void sub_port_release(struct stream_port_s *port,
/* this is es sub */
esparser_release(pbuf);
}
- stbuf_release(pbuf, false);
+ stbuf_release(pbuf);
sub_port_inited = 0;
}
static int sub_port_init(struct stream_port_s *port, struct stream_buf_s *pbuf)
{
int r;
- r = stbuf_init(pbuf, NULL, false);
+ r = stbuf_init(pbuf, NULL);
if (r < 0)
return r;
if ((port->flag & PORT_FLAG_SID) == 0) {
@@ -958,72 +940,70 @@ static int amstream_port_init(struct port_priv_s *priv)
}
if ((port->type & PORT_TYPE_VIDEO) &&
- (vdec->port_flag & PORT_FLAG_VFORMAT)) {
- pvbuf->for_4k = 0;
- if (has_hevc_vdec()) {
- if (port->vformat == VFORMAT_HEVC ||
- port->vformat == VFORMAT_AVS2 ||
- port->vformat == VFORMAT_AV1 ||
- port->vformat == VFORMAT_VP9)
- pvbuf = &bufs[BUF_TYPE_HEVC];
+ (port->flag & PORT_FLAG_VFORMAT)) {
+ if (vdec_stream_based(vdec)) {
+ struct stream_buf_ops *ops = NULL;
+ struct parser_args pars = {
+ .vid = (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff,
+ .aid = (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff,
+ .sid = (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff,
+ .pcrid = (port->pcr_inited == 1) ? port->pcrid : 0xffff,
+ };
+
+ if (port->type & PORT_TYPE_MPTS) {
+ ops = get_tsparser_stbuf_ops();
+ } else if (port->type & PORT_TYPE_MPPS) {
+ ops = get_psparser_stbuf_ops();
+ } else {
+ ops = !vdec_single(vdec) ?
+ get_stbuf_ops() :
+ get_esparser_stbuf_ops();
+
+ /* def used stbuf with parser if the feature disable. */
+ if (!enable_stream_mode_multi_dec)
+ ops = get_esparser_stbuf_ops();
+ }
+
+ r = stream_buffer_base_init(&vdec->vbuf, ops, &pars);
+ if (r) {
+ mutex_unlock(&priv->mutex);
+ pr_err("stream buffer base init failed\n");
+ goto error2;
+ }
}
+
mutex_lock(&priv->mutex);
- r = video_port_init(priv, pvbuf);
+ r = video_port_init(priv, &vdec->vbuf);
if (r < 0) {
mutex_unlock(&priv->mutex);
- pr_err("video_port_init failed\n");
+ pr_err("video_port_init failed\n");
goto error2;
}
mutex_unlock(&priv->mutex);
}
- if ((port->type & PORT_TYPE_SUB) && (port->flag & PORT_FLAG_SID)) {
- r = sub_port_init(port, psbuf);
- if (r < 0) {
- pr_err("sub_port_init failed\n");
- goto error3;
- }
- }
-
- if (port->type & PORT_TYPE_MPTS) {
- if (has_hevc_vdec()) {
- r = tsdemux_init(
- (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff,
+ if ((port->type & PORT_TYPE_MPTS) &&
+ !(port->flag & PORT_FLAG_VFORMAT)) {
+ r = tsdemux_init(0xffff,
(port->flag & PORT_FLAG_AID) ? port->aid : 0xffff,
(port->flag & PORT_FLAG_SID) ? port->sid : 0xffff,
(port->pcr_inited == 1) ? port->pcrid : 0xffff,
- (port->vformat == VFORMAT_HEVC) ||
- (port->vformat == VFORMAT_AVS2) ||
- (port->vformat == VFORMAT_AV1) ||
- (port->vformat == VFORMAT_VP9),
- vdec);
- } else {
- r = tsdemux_init(
- (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff,
- (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff,
- (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff,
- (port->pcr_inited == 1) ? port->pcrid : 0xffff,
- 0,
- vdec);
- }
-
+ 0, vdec);
if (r < 0) {
pr_err("tsdemux_init failed\n");
goto error4;
}
tsync_pcr_start();
}
- if (port->type & PORT_TYPE_MPPS) {
- r = psparser_init(
- (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff,
- (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff,
- (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff,
- priv->vdec);
+
+ if ((port->type & PORT_TYPE_SUB) && (port->flag & PORT_FLAG_SID)) {
+ r = sub_port_init(port, psbuf);
if (r < 0) {
- pr_err("psparser_init failed\n");
- goto error5;
+ pr_err("sub_port_init failed\n");
+ goto error3;
}
}
+
#ifdef CONFIG_AM_VDEC_REAL
if (port->type & PORT_TYPE_RM) {
rm_set_vasid(
@@ -1052,12 +1032,11 @@ static int amstream_port_init(struct port_priv_s *priv)
mutex_unlock(&amstream_mutex);
return 0;
/*errors follow here */
-error5:
- tsdemux_release();
+
error4:
sub_port_release(port, psbuf);
error3:
- video_port_release(priv, pvbuf, 0);
+ video_port_release(priv, &priv->vdec->vbuf, 0);
error2:
audio_port_release(port, pabuf, 0);
error1:
@@ -1068,20 +1047,12 @@ error1:
static int amstream_port_release(struct port_priv_s *priv)
{
struct stream_port_s *port = priv->port;
- struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO];
+ struct stream_buf_s *pvbuf = &priv->vdec->vbuf;
struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO];
struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE];
- if (has_hevc_vdec()) {
- if (port->vformat == VFORMAT_HEVC
- || port->vformat == VFORMAT_AVS2
- || port->vformat == VFORMAT_AV1
- || port->vformat == VFORMAT_VP9)
- pvbuf = &bufs[BUF_TYPE_HEVC];
- }
-
- if (port->type & PORT_TYPE_MPTS) {
- vdec_disconnect(priv->vdec);
+ if ((port->type & PORT_TYPE_MPTS) &&
+ !(port->flag & PORT_FLAG_VFORMAT)) {
tsync_pcr_stop();
tsdemux_release();
}
@@ -1144,14 +1115,8 @@ static ssize_t amstream_vbuf_write(struct file *file, const char *buf,
size_t count, loff_t *ppos)
{
struct port_priv_s *priv = (struct port_priv_s *)file->private_data;
- struct stream_port_s *port = priv->port;
- struct stream_buf_s *pbuf = NULL;
+ struct stream_buf_s *pbuf = &priv->vdec->vbuf;
int r;
- if (has_hevc_vdec()) {
- pbuf = (port->type & PORT_TYPE_HEVC) ? &bufs[BUF_TYPE_HEVC] :
- &bufs[BUF_TYPE_VIDEO];
- } else
- pbuf = &bufs[BUF_TYPE_VIDEO];
if (!(port_get_inited(priv))) {
r = amstream_port_init(priv);
@@ -1162,7 +1127,7 @@ static ssize_t amstream_vbuf_write(struct file *file, const char *buf,
if (priv->vdec->port_flag & PORT_FLAG_DRM)
r = drm_write(file, pbuf, buf, count);
else
- r = esparser_write(file, pbuf, buf, count);
+ r = stream_buffer_write(file, pbuf, buf, count);
if (slow_input) {
pr_info("slow_input: es codec write size %x\n", r);
msleep(3000);
@@ -1226,18 +1191,9 @@ static ssize_t amstream_mpts_write(struct file *file, const char *buf,
struct port_priv_s *priv = (struct port_priv_s *)file->private_data;
struct stream_port_s *port = priv->port;
struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO];
- struct stream_buf_s *pvbuf = NULL;
+ struct stream_buf_s *pvbuf = &priv->vdec->vbuf;
int r = 0;
- if (has_hevc_vdec()) {
- pvbuf = (port->vformat == VFORMAT_HEVC ||
- port->vformat == VFORMAT_AVS2 ||
- port->vformat == VFORMAT_AV1 ||
- port->vformat == VFORMAT_VP9) ?
- &bufs[BUF_TYPE_HEVC] : &bufs[BUF_TYPE_VIDEO];
- } else
- pvbuf = &bufs[BUF_TYPE_VIDEO];
-
if (!(port_get_inited(priv))) {
r = amstream_port_init(priv);
if (r < 0)
@@ -1656,10 +1612,12 @@ static int amstream_open(struct inode *inode, struct file *file)
}
}
- if ((port->flag & PORT_FLAG_IN_USE) &&
- ((port->type & PORT_TYPE_FRAME) == 0)) {
- mutex_unlock(&amstream_mutex);
- return -EBUSY;
+ if (!enable_stream_mode_multi_dec) {
+ if ((port->flag & PORT_FLAG_IN_USE) &&
+ ((port->type & PORT_TYPE_FRAME) == 0)) {
+ mutex_unlock(&amstream_mutex);
+ return -EBUSY;
+ }
}
/* check other ports conflicts for audio */
@@ -1824,9 +1782,8 @@ static int amstream_release(struct inode *inode, struct file *file)
#else
if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX
&& port->vformat == VFORMAT_H264
- && bufs[BUF_TYPE_VIDEO].for_4k) {
+ && port->is_4k) {
vdec_poweroff(VDEC_HEVC);
- bufs[BUF_TYPE_VIDEO].for_4k = 0;
}
if ((port->vformat == VFORMAT_HEVC
@@ -2046,25 +2003,17 @@ static long amstream_ioctl_set(struct port_priv_s *priv, ulong arg)
switch (parm.cmd) {
case AMSTREAM_SET_VB_START:
if ((this->type & PORT_TYPE_VIDEO) &&
- ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) {
- if (has_hevc_vdec())
- bufs[BUF_TYPE_HEVC].buf_start = parm.data_32;
- bufs[BUF_TYPE_VIDEO].buf_start = parm.data_32;
+ ((priv->vdec->vbuf.flag & BUF_FLAG_IN_USE) == 0)) {
+ priv->vdec->vbuf.buf_start = parm.data_32;
} else
r = -EINVAL;
break;
case AMSTREAM_SET_VB_SIZE:
if ((this->type & PORT_TYPE_VIDEO) &&
- ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) {
- if (bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_ALLOC) {
- if (has_hevc_vdec()) {
- r = stbuf_change_size(
- &bufs[BUF_TYPE_HEVC],
- parm.data_32,
- false);
- }
+ ((priv->vdec->vbuf.flag & BUF_FLAG_IN_USE) == 0)) {
+ if (priv->vdec->vbuf.flag & BUF_FLAG_ALLOC) {
r += stbuf_change_size(
- &bufs[BUF_TYPE_VIDEO],
+ &priv->vdec->vbuf,
parm.data_32,
false);
}
@@ -2176,11 +2125,9 @@ static long amstream_ioctl_set(struct port_priv_s *priv, ulong arg)
r = -EINVAL;
else if (this->type & PORT_TYPE_FRAME)
r = vdec_set_pts(priv->vdec, parm.data_32);
- else if (has_hevc_vdec() && this->type & PORT_TYPE_HEVC)
- r = es_vpts_checkin(&bufs[BUF_TYPE_HEVC],
- parm.data_32);
- else if (this->type & PORT_TYPE_VIDEO)
- r = es_vpts_checkin(&bufs[BUF_TYPE_VIDEO],
+ else if ((this->type & PORT_TYPE_VIDEO) ||
+ (this->type & PORT_TYPE_HEVC))
+ r = es_vpts_checkin(&priv->vdec->vbuf,
parm.data_32);
else if (this->type & PORT_TYPE_AUDIO)
r = es_apts_checkin(&bufs[BUF_TYPE_AUDIO],
@@ -2199,25 +2146,13 @@ static long amstream_ioctl_set(struct port_priv_s *priv, ulong arg)
* life sequence or multi-tasking management
*/
r = vdec_set_pts64(priv->vdec, pts);
- } else if (has_hevc_vdec()) {
- if (this->type & PORT_TYPE_HEVC) {
- r = es_vpts_checkin_us64(
- &bufs[BUF_TYPE_HEVC], pts);
- } else if (this->type & PORT_TYPE_VIDEO) {
+ } else if ((this->type & PORT_TYPE_HEVC) ||
+ (this->type & PORT_TYPE_VIDEO)) {
r = es_vpts_checkin_us64(
- &bufs[BUF_TYPE_VIDEO], pts);
- } else if (this->type & PORT_TYPE_AUDIO) {
+ &priv->vdec->vbuf, pts);
+ } else if (this->type & PORT_TYPE_AUDIO) {
r = es_vpts_checkin_us64(
&bufs[BUF_TYPE_AUDIO], pts);
- }
- } else {
- if (this->type & PORT_TYPE_VIDEO) {
- r = es_vpts_checkin_us64(
- &bufs[BUF_TYPE_VIDEO], pts);
- } else if (this->type & PORT_TYPE_AUDIO) {
- r = es_vpts_checkin_us64(
- &bufs[BUF_TYPE_AUDIO], pts);
- }
}
}
break;
@@ -2265,9 +2200,7 @@ static long amstream_ioctl_set(struct port_priv_s *priv, ulong arg)
tsdemux_set_demux(parm.data_32);
break;
case AMSTREAM_SET_VIDEO_DELAY_LIMIT_MS:
- if (has_hevc_vdec())
- bufs[BUF_TYPE_HEVC].max_buffer_delay_ms = parm.data_32;
- bufs[BUF_TYPE_VIDEO].max_buffer_delay_ms = parm.data_32;
+ priv->vdec->vbuf.max_buffer_delay_ms = parm.data_32;
break;
case AMSTREAM_SET_AUDIO_DELAY_LIMIT_MS:
bufs[BUF_TYPE_AUDIO].max_buffer_delay_ms = parm.data_32;
@@ -2377,25 +2310,21 @@ static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg)
struct am_ioctl_parm_ex *p = &parm;
struct stream_buf_s *buf = NULL;
- buf = (this->vformat == VFORMAT_HEVC ||
- this->vformat == VFORMAT_AVS2 ||
- this->vformat == VFORMAT_AV1 ||
- this->vformat == VFORMAT_VP9) ?
- &bufs[BUF_TYPE_HEVC] :
- &bufs[BUF_TYPE_VIDEO];
+ mutex_unlock(&amstream_mutex);
+
+ /*
+ *todo: check upper layer for decoder
+ * handler lifecycle
+ */
+ if (priv->vdec == NULL) {
+ r = -EINVAL;
+ mutex_unlock(&amstream_mutex);
+ break;
+ }
if (this->type & PORT_TYPE_FRAME) {
struct vdec_input_status_s status;
- /*
- *todo: check upper layer for decoder
- * handler lifecycle
- */
- if (priv->vdec == NULL) {
- r = -EINVAL;
- break;
- }
-
r = vdec_input_get_status(&priv->vdec->input,
&status);
if (r == 0) {
@@ -2405,13 +2334,16 @@ static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg)
p->status.read_pointer =
status.read_pointer;
}
+ mutex_unlock(&amstream_mutex);
break;
}
+ buf = &priv->vdec->vbuf;
p->status.size = stbuf_canusesize(buf);
p->status.data_len = stbuf_level(buf);
p->status.free_len = stbuf_space(buf);
p->status.read_pointer = stbuf_rp(buf);
+ mutex_unlock(&amstream_mutex);
} else
r = -EINVAL;
break;
@@ -2753,25 +2685,18 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv,
case AMSTREAM_IOC_VB_START:
if ((this->type & PORT_TYPE_VIDEO) &&
- ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) {
- if (has_hevc_vdec())
- bufs[BUF_TYPE_HEVC].buf_start = arg;
- bufs[BUF_TYPE_VIDEO].buf_start = arg;
+ ((priv->vdec->vbuf.flag & BUF_FLAG_IN_USE) == 0)) {
+ priv->vdec->vbuf.buf_start = arg;
} else
r = -EINVAL;
break;
case AMSTREAM_IOC_VB_SIZE:
if ((this->type & PORT_TYPE_VIDEO) &&
- ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) {
- if (bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_ALLOC) {
- if (has_hevc_vdec()) {
- r = stbuf_change_size(
- &bufs[BUF_TYPE_HEVC],
- arg, false);
- }
+ ((priv->vdec->vbuf.flag & BUF_FLAG_IN_USE) == 0)) {
+ if (priv->vdec->vbuf.flag & BUF_FLAG_ALLOC) {
r += stbuf_change_size(
- &bufs[BUF_TYPE_VIDEO],
+ &priv->vdec->vbuf,
arg, false);
}
} else
@@ -2864,25 +2789,21 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv,
struct am_io_param *p = &para;
struct stream_buf_s *buf = NULL;
- buf = (this->vformat == VFORMAT_HEVC ||
- this->vformat == VFORMAT_AVS2 ||
- this->vformat == VFORMAT_AV1 ||
- this->vformat == VFORMAT_VP9) ?
- &bufs[BUF_TYPE_HEVC] :
- &bufs[BUF_TYPE_VIDEO];
+ mutex_lock(&amstream_mutex);
+
+ /*
+ *todo: check upper layer for decoder
+ * handler lifecycle
+ */
+ if (priv->vdec == NULL) {
+ r = -EINVAL;
+ mutex_unlock(&amstream_mutex);
+ break;
+ }
if (this->type & PORT_TYPE_FRAME) {
struct vdec_input_status_s status;
- /*
- *todo: check upper layer for decoder
- * handler lifecycle
- */
- if (priv->vdec == NULL) {
- r = -EINVAL;
- break;
- }
-
r = vdec_input_get_status(&priv->vdec->input,
&status);
if (r == 0) {
@@ -2895,15 +2816,19 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv,
sizeof(para)))
r = -EFAULT;
}
+ mutex_unlock(&amstream_mutex);
break;
}
+ buf = &priv->vdec->vbuf;
p->status.size = stbuf_canusesize(buf);
p->status.data_len = stbuf_level(buf);
p->status.free_len = stbuf_space(buf);
p->status.read_pointer = stbuf_rp(buf);
if (copy_to_user((void *)arg, p, sizeof(para)))
r = -EFAULT;
+
+ mutex_unlock(&amstream_mutex);
return r;
}
r = -EINVAL;
@@ -2962,10 +2887,9 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv,
r = -EINVAL;
else if (this->type & PORT_TYPE_FRAME)
r = vdec_set_pts(priv->vdec, arg);
- else if (has_hevc_vdec() && this->type & PORT_TYPE_HEVC)
- r = es_vpts_checkin(&bufs[BUF_TYPE_HEVC], arg);
- else if (this->type & PORT_TYPE_VIDEO)
- r = es_vpts_checkin(&bufs[BUF_TYPE_VIDEO], arg);
+ else if ((this->type & PORT_TYPE_VIDEO) ||
+ (this->type & PORT_TYPE_HEVC))
+ r = es_vpts_checkin(&priv->vdec->vbuf, arg);
else if (this->type & PORT_TYPE_AUDIO)
r = es_apts_checkin(&bufs[BUF_TYPE_AUDIO], arg);
break;
@@ -2987,25 +2911,13 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv,
*/
if (priv->vdec)
r = vdec_set_pts64(priv->vdec, pts);
- } else if (has_hevc_vdec()) {
- if (this->type & PORT_TYPE_HEVC) {
- r = es_vpts_checkin_us64(
- &bufs[BUF_TYPE_HEVC], pts);
- } else if (this->type & PORT_TYPE_VIDEO) {
+ } else if ((this->type & PORT_TYPE_HEVC) ||
+ (this->type & PORT_TYPE_VIDEO)) {
r = es_vpts_checkin_us64(
- &bufs[BUF_TYPE_VIDEO], pts);
- } else if (this->type & PORT_TYPE_AUDIO) {
+ &priv->vdec->vbuf, pts);
+ } else if (this->type & PORT_TYPE_AUDIO) {
r = es_vpts_checkin_us64(
&bufs[BUF_TYPE_AUDIO], pts);
- }
- } else {
- if (this->type & PORT_TYPE_VIDEO) {
- r = es_vpts_checkin_us64(
- &bufs[BUF_TYPE_VIDEO], pts);
- } else if (this->type & PORT_TYPE_AUDIO) {
- r = es_vpts_checkin_us64(
- &bufs[BUF_TYPE_AUDIO], pts);
- }
}
}
break;
@@ -3368,15 +3280,13 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv,
tsdemux_set_demux((int)arg);
break;
case AMSTREAM_IOC_SET_VIDEO_DELAY_LIMIT_MS:
- if (has_hevc_vdec())
- bufs[BUF_TYPE_HEVC].max_buffer_delay_ms = (int)arg;
- bufs[BUF_TYPE_VIDEO].max_buffer_delay_ms = (int)arg;
+ priv->vdec->vbuf.max_buffer_delay_ms = (int)arg;
break;
case AMSTREAM_IOC_SET_AUDIO_DELAY_LIMIT_MS:
bufs[BUF_TYPE_AUDIO].max_buffer_delay_ms = (int)arg;
break;
case AMSTREAM_IOC_GET_VIDEO_DELAY_LIMIT_MS:
- put_user(bufs[BUF_TYPE_VIDEO].max_buffer_delay_ms, (int *)arg);
+ put_user(priv->vdec->vbuf.max_buffer_delay_ms, (int *)arg);
break;
case AMSTREAM_IOC_GET_AUDIO_DELAY_LIMIT_MS:
put_user(bufs[BUF_TYPE_AUDIO].max_buffer_delay_ms, (int *)arg);
@@ -3805,6 +3715,53 @@ static ssize_t ports_show(struct class *class, struct class_attribute *attr,
return pbuf - buf;
}
+static int show_vbuf_status_cb(struct stream_buf_s *p, char *buf)
+{
+ char *pbuf = buf;
+
+ if (!p->buf_start)
+ return 0;
+ /*type */
+ pbuf += sprintf(pbuf, "Video-%d buffer:", p->id);
+ /*flag */
+ pbuf += sprintf(pbuf, "\tflag:%d( ", p->flag);
+ if (p->flag & BUF_FLAG_ALLOC)
+ pbuf += sprintf(pbuf, "%s ", "Alloc");
+ else
+ pbuf += sprintf(pbuf, "%s ", "Unalloc");
+ if (p->flag & BUF_FLAG_IN_USE)
+ pbuf += sprintf(pbuf, "%s ", "Used");
+ else
+ pbuf += sprintf(pbuf, "%s ", "Noused");
+ if (p->flag & BUF_FLAG_PARSER)
+ pbuf += sprintf(pbuf, "%s ", "Parser");
+ else
+ pbuf += sprintf(pbuf, "%s ", "noParser");
+ if (p->flag & BUF_FLAG_FIRST_TSTAMP)
+ pbuf += sprintf(pbuf, "%s ", "firststamp");
+ else
+ pbuf += sprintf(pbuf, "%s ", "nofirststamp");
+ pbuf += sprintf(pbuf, ")\n");
+
+ /*buf stats */
+ pbuf += sprintf(pbuf, "\tbuf addr:%p\n", (void *)p->buf_start);
+ pbuf += sprintf(pbuf, "\tbuf size:%#x\n", p->buf_size);
+ pbuf += sprintf(pbuf, "\tbuf canusesize:%#x\n", p->canusebuf_size);
+ pbuf += sprintf(pbuf, "\tbuf regbase:%#lx\n", p->reg_base);
+
+ if (p->reg_base && p->flag & BUF_FLAG_IN_USE) {
+ pbuf += sprintf(pbuf, "\tbuf level:%#x\n",
+ stbuf_level(p));
+ pbuf += sprintf(pbuf, "\tbuf space:%#x\n",
+ stbuf_space(p));
+ pbuf += sprintf(pbuf, "\tbuf read pointer:%#x\n",
+ stbuf_rp(p));
+ } else
+ pbuf += sprintf(pbuf, "\tbuf no used.\n");
+
+ return pbuf - buf;
+}
+
static ssize_t bufs_show(struct class *class, struct class_attribute *attr,
char *buf)
{
@@ -3816,6 +3773,10 @@ static ssize_t bufs_show(struct class *class, struct class_attribute *attr,
for (i = 0; i < amstream_buf_num; i++) {
p = &bufs[i];
+
+ if (!p->buf_start)
+ continue;
+
/*type */
pbuf += sprintf(pbuf, "%s buffer:", buf_type[p->type]);
/*flag */
@@ -3948,6 +3909,8 @@ static ssize_t bufs_show(struct class *class, struct class_attribute *attr,
}
}
+ pbuf += show_stream_buffer_status(pbuf, show_vbuf_status_cb);
+
return pbuf - buf;
}
@@ -3956,16 +3919,11 @@ static ssize_t videobufused_show(struct class *class,
{
char *pbuf = buf;
struct stream_buf_s *p = NULL;
- struct stream_buf_s *p_hevc = NULL;
p = &bufs[0];
- if (has_hevc_vdec())
- p_hevc = &bufs[BUF_TYPE_HEVC];
if (p->flag & BUF_FLAG_IN_USE)
pbuf += sprintf(pbuf, "%d ", 1);
- else if (has_hevc_vdec() && (p_hevc->flag & BUF_FLAG_IN_USE))
- pbuf += sprintf(pbuf, "%d ", 1);
else
pbuf += sprintf(pbuf, "%d ", 0);
return 1;
@@ -4376,8 +4334,6 @@ static int amstream_remove(struct platform_device *pdev)
int i;
struct stream_port_s *st;
- if (bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_ALLOC)
- stbuf_change_size(&bufs[BUF_TYPE_VIDEO], 0, false);
if (bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_ALLOC)
stbuf_change_size(&bufs[BUF_TYPE_AUDIO], 0, false);
stbuf_fetch_release();
@@ -4482,7 +4438,6 @@ MODULE_PARM_DESC(def_vstreambuf_sizeM,
module_param(slow_input, uint, 0664);
MODULE_PARM_DESC(slow_input, "\n amstream slow_input\n");
-
MODULE_DESCRIPTION("AMLOGIC streaming port driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Tim Yao <timyao@amlogic.com>");
diff --git a/drivers/stream_input/amports/stream_buffer_base.c b/drivers/stream_input/amports/stream_buffer_base.c
new file mode 100644
index 0000000..e6dc5f1
--- a/dev/null
+++ b/drivers/stream_input/amports/stream_buffer_base.c
@@ -0,0 +1,169 @@
+/*
+ * drivers/amlogic/media/stream_input/parser/stream_buffer_base.c
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+#define DEBUG
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/atomic.h>
+#include <linux/delay.h>
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include "../../frame_provider/decoder/utils/vdec.h"
+#include "amports_priv.h"
+#include "stream_buffer_base.h"
+#include "thread_rw.h"
+
+#define DEFAULT_VIDEO_BUFFER_SIZE (1024 * 1024 * 3)
+#define DEFAULT_VIDEO_BUFFER_SIZE_4K (1024 * 1024 * 6)
+#define DEFAULT_VIDEO_BUFFER_SIZE_TVP (1024 * 1024 * 10)
+#define DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP (1024 * 1024 * 15)
+
+static struct stream_buf_s vdec_buf_def = {
+ .reg_base = VLD_MEM_VIFIFO_REG_BASE,
+ .type = BUF_TYPE_VIDEO,
+ .buf_start = 0,
+ .buf_size = DEFAULT_VIDEO_BUFFER_SIZE,
+ .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE,
+ .first_tstamp = INVALID_PTS
+};
+
+static struct stream_buf_s hevc_buf_def = {
+ .reg_base = HEVC_STREAM_REG_BASE,
+ .type = BUF_TYPE_HEVC,
+ .buf_start = 0,
+ .buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K,
+ .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K,
+ .first_tstamp = INVALID_PTS
+};
+
+static struct stream_buf_s *get_def_parms(int f)
+{
+ switch (f) {
+ case VFORMAT_HEVC:
+ case VFORMAT_AVS2:
+ case VFORMAT_AV1:
+ case VFORMAT_VP9:
+ return &hevc_buf_def;
+ default:
+ return &vdec_buf_def;
+ }
+}
+
+int stream_buffer_base_init(struct stream_buf_s *stbuf,
+ struct stream_buf_ops *ops,
+ struct parser_args *pars)
+{
+ struct vdec_s *vdec =
+ container_of(stbuf, struct vdec_s, vbuf);
+ struct stream_port_s *port = NULL;
+ u32 format, width, height;
+
+ /* sanity check. */
+ if (WARN_ON(!stbuf) || WARN_ON(!ops))
+ return -EINVAL;
+
+ port = vdec->port;
+ format = vdec->port->vformat;
+ width = vdec->sys_info->width;
+ height = vdec->sys_info->height;
+
+ memcpy(stbuf, get_def_parms(format),
+ sizeof(*stbuf));
+
+ stbuf->id = vdec->id;
+ stbuf->is_hevc = ((format == VFORMAT_HEVC) ||
+ (format == VFORMAT_AVS2) ||
+ (format == VFORMAT_AV1) ||
+ (format == VFORMAT_VP9));
+ stbuf->for_4k = ((width * height) >
+ (1920 * 1088)) ? 1 : 0;
+ stbuf->is_multi_inst = !vdec_single(vdec);
+ memcpy(&stbuf->pars, pars, sizeof(*pars));
+
+ /* register ops func. */
+ stbuf->ops = ops;
+
+ return 0;
+}
+EXPORT_SYMBOL(stream_buffer_base_init);
+
+void stream_buffer_set_ext_buf(struct stream_buf_s *stbuf,
+ ulong addr,
+ u32 size)
+{
+ stbuf->ext_buf_addr = addr;
+ stbuf->buf_size = size;
+}
+EXPORT_SYMBOL(stream_buffer_set_ext_buf);
+
+ssize_t stream_buffer_write_ex(struct file *file,
+ struct stream_buf_s *stbuf,
+ const char __user *buf,
+ size_t count, int flags)
+{
+ int r;
+ u32 len = count;
+
+ if (buf == NULL || count == 0)
+ return -EINVAL;
+
+ if (stbuf_space(stbuf) < count) {
+ if ((flags & 2) || ((file != NULL) &&
+ (file->f_flags & O_NONBLOCK))) {
+ len = stbuf_space(stbuf);
+ if (len < 256) /* <1k.do eagain, */
+ return -EAGAIN;
+ } else {
+ len = min(stbuf_canusesize(stbuf) / 8, len);
+ if (stbuf_space(stbuf) < len) {
+ r = stbuf_wait_space(stbuf, len);
+ if (r < 0)
+ return r;
+ }
+ }
+ }
+
+ stbuf->last_write_jiffies64 = jiffies_64;
+ stbuf->is_phybuf = (flags & 1);
+
+ len = min_t(u32, len, count);
+
+ r = stbuf->ops->write(stbuf, buf, len);
+
+ return r;
+}
+EXPORT_SYMBOL(stream_buffer_write_ex);
+
+int stream_buffer_write(struct file *file,
+ struct stream_buf_s *stbuf,
+ const char *buf,
+ size_t count)
+{
+ if (stbuf->write_thread)
+ return threadrw_write(file, stbuf, buf, count);
+ else
+ return stream_buffer_write_ex(file, stbuf, buf, count, 0);
+}
+EXPORT_SYMBOL(stream_buffer_write);
+
diff --git a/drivers/stream_input/amports/stream_buffer_base.h b/drivers/stream_input/amports/stream_buffer_base.h
new file mode 100644
index 0000000..e7a107f
--- a/dev/null
+++ b/drivers/stream_input/amports/stream_buffer_base.h
@@ -0,0 +1,62 @@
+/*
+ * drivers/amlogic/media/stream_input/parser/stream_buffer_base.h
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef STREAM_BUFFER_INTERFACE_H
+#define STREAM_BUFFER_INTERFACE_H
+#include "streambuf.h"
+#include "streambuf_reg.h"
+
+#define STBUF_READ(s, func, args...) \
+({ \
+ u32 ret = 0; \
+ if ((s) && (s)->ops) \
+ ret = (s)->ops->func((s), ##args); \
+ ret; \
+})
+
+#define STBUF_WRITE(s, func, args...) \
+({ \
+ if ((s) && (s)->ops) \
+ (s)->ops->func((s), ##args); \
+})
+
+extern struct stream_buf_ops *get_stbuf_ops(void);
+extern struct stream_buf_ops *get_esparser_stbuf_ops(void);
+extern struct stream_buf_ops *get_tsparser_stbuf_ops(void);
+extern struct stream_buf_ops *get_psparser_stbuf_ops(void);
+
+int stream_buffer_base_init(struct stream_buf_s *stbuf,
+ struct stream_buf_ops *ops,
+ struct parser_args *pars);
+
+void stream_buffer_set_ext_buf(struct stream_buf_s *stbuf,
+ ulong addr,
+ u32 size);
+
+int stream_buffer_write(struct file *file,
+ struct stream_buf_s *stbuf,
+ const char *buf,
+ size_t count);
+
+ssize_t stream_buffer_write_ex(struct file *file,
+ struct stream_buf_s *stbuf,
+ const char __user *buf,
+ size_t count,
+ int flags);
+
+#endif /* STREAM_BUFFER_INTERFACE_H */
+
diff --git a/drivers/stream_input/amports/stream_buffer_interface.c b/drivers/stream_input/amports/stream_buffer_interface.c
new file mode 100644
index 0000000..71e83d0
--- a/dev/null
+++ b/drivers/stream_input/amports/stream_buffer_interface.c
@@ -0,0 +1,334 @@
+/*
+ * drivers/amlogic/media/stream_input/parser/stream_bufffer_interface.c
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+#define DEBUG
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/atomic.h>
+#include <linux/delay.h>
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include <linux/amlogic/media/frame_sync/ptsserv.h>
+#include "../../frame_provider/decoder/utils/vdec.h"
+#include "stream_buffer_base.h"
+#include "amports_priv.h"
+#include "thread_rw.h"
+
+#define MEM_NAME "stbuf"
+#define MAP_RANGE (SZ_1M)
+
+static void stream_buffer_release(struct stream_buf_s *stbuf);
+
+static const char *type_to_str(int t)
+{
+ switch (t) {
+ case BUF_TYPE_VIDEO:
+ return "VIDEO";
+ case BUF_TYPE_AUDIO:
+ return "AUDIO";
+ case BUF_TYPE_SUBTITLE:
+ return "SUB";
+ case BUF_TYPE_USERDATA:
+ return "USER";
+ case BUF_TYPE_HEVC:
+ return "HEVC";
+ default:
+ return "ERR";
+ }
+}
+
+static int type_to_pts(int t)
+{
+ switch (t) {
+ case BUF_TYPE_VIDEO:
+ return PTS_TYPE_VIDEO;
+ case BUF_TYPE_HEVC:
+ return PTS_TYPE_HEVC;
+ default:
+ return PTS_TYPE_MAX;
+ }
+}
+
+static int stream_buffer_init(struct stream_buf_s *stbuf, struct vdec_s *vdec)
+{
+ int ret = 0;
+ u32 flags = CODEC_MM_FLAGS_DMA;
+ bool is_secure = 0;
+ u32 addr = 0;
+ int pages = 0;
+ u32 size;
+
+ if (stbuf->buf_start)
+ return 0;
+
+ snprintf(stbuf->name, sizeof(stbuf->name),
+ "%s-%d", MEM_NAME, vdec->id);
+
+ if (stbuf->ext_buf_addr) {
+ addr = stbuf->ext_buf_addr;
+ size = stbuf->buf_size;
+ } else {
+ flags |= CODEC_MM_FLAGS_FOR_VDECODER;
+ if (vdec->port_flag & PORT_FLAG_DRM) {
+ flags |= CODEC_MM_FLAGS_TVP;
+ is_secure = true;
+ }
+
+ size = PAGE_ALIGN(stbuf->buf_size);
+ pages = (size >> PAGE_SHIFT);
+ addr = codec_mm_alloc_for_dma(stbuf->name,
+ pages, PAGE_SHIFT + 4, flags);
+ if (!addr) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ ret = vdec_set_input_buffer(vdec, addr, size);
+ if (ret) {
+ pr_err("[%d]: set input buffer err.\n", stbuf->id);
+ goto err;
+ }
+ }
+
+ atomic_set(&stbuf->payload, 0);
+ init_waitqueue_head(&stbuf->wq);
+
+ stbuf->buf_start = addr;
+ stbuf->buf_wp = addr;
+ stbuf->buf_rp = addr;
+ stbuf->buf_size = size;
+ stbuf->is_secure = is_secure;
+ stbuf->no_parser = true;
+ stbuf->buf_page_num = pages;
+ stbuf->canusebuf_size = size;
+
+ /* init pts server. */
+ ret = pts_start(type_to_pts(stbuf->type));
+ if (ret < 0) {
+ pr_err("[%d]: pts server failed\n", stbuf->id);
+ //goto err;//fixme
+ }
+
+ /* init thread write. */
+ if (!(vdec_get_debug_flags() & 1) &&
+ !codec_mm_video_tvp_enabled()) {
+ int block_size = PAGE_SIZE << 4;
+ int buf_num = (2 * SZ_1M) / (PAGE_SIZE << 4);
+
+ stbuf->write_thread =
+ threadrw_alloc(buf_num, block_size,
+ stream_buffer_write_ex, 0);
+ }
+
+ stbuf->flag |= BUF_FLAG_ALLOC;
+ stbuf->flag |= BUF_FLAG_IN_USE;
+
+ pr_info("[%d]: [%s-%s] addr: %lx, size: %x, thrRW: %d, extbuf: %d, secure: %d\n",
+ stbuf->id, type_to_str(stbuf->type), stbuf->name,
+ stbuf->buf_start, stbuf->buf_size,
+ !!stbuf->write_thread,
+ !!stbuf->ext_buf_addr,
+ stbuf->is_secure);
+
+ return 0;
+err:
+ stream_buffer_release(stbuf);
+
+ return ret;
+}
+
+static void stream_buffer_release(struct stream_buf_s *stbuf)
+{
+ if (stbuf->write_thread)
+ threadrw_release(stbuf);
+
+ pts_stop(type_to_pts(stbuf->type));
+
+ if (stbuf->flag & BUF_FLAG_ALLOC && stbuf->buf_start) {
+ if (!stbuf->ext_buf_addr)
+ codec_mm_free_for_dma(MEM_NAME, stbuf->buf_start);
+
+ stbuf->flag &= ~BUF_FLAG_ALLOC;
+ stbuf->ext_buf_addr = 0;
+ stbuf->buf_start = 0;
+ stbuf->is_secure = false;
+ }
+ stbuf->flag &= ~BUF_FLAG_IN_USE;
+}
+
+static int get_free_space(struct stream_buf_s *stbuf)
+{
+ u32 len = stbuf->buf_size;
+ int idle = 0;
+
+ if (!atomic_read(&stbuf->payload) && (stbuf->buf_rp == stbuf->buf_wp))
+ idle = len;
+ else if (stbuf->buf_wp > stbuf->buf_rp)
+ idle = len - (stbuf->buf_wp - stbuf->buf_rp);
+ else if (stbuf->buf_wp < stbuf->buf_rp)
+ idle = stbuf->buf_rp - stbuf->buf_wp;
+
+ /*pr_info("[%d]: wp: %x, rp: %x, payload: %d, free space: %d\n",
+ stbuf->id, stbuf->buf_wp, stbuf->buf_rp,
+ atomic_read(&stbuf->payload), idle);*/
+
+ return idle;
+}
+
+static int aml_copy_from_user(void *to, const void *from, ulong n)
+{
+ int ret =0;
+
+ if (likely(access_ok(VERIFY_READ, from, n)))
+ ret = copy_from_user(to, from, n);
+ else
+ memcpy(to, from, n);
+
+ return ret;
+}
+
+static int stream_buffer_copy(struct stream_buf_s *stbuf, const u8 *buf, u32 size)
+{
+ int ret = 0;
+ void *src = NULL, *dst = NULL;
+ int i, len;
+
+ for (i = 0; i < size; i += MAP_RANGE) {
+ len = ((size - i) > MAP_RANGE) ? MAP_RANGE : size - i;
+ src = stbuf->is_phybuf ?
+ codec_mm_vmap((ulong) buf + i, len) :
+ (void *) buf;
+ dst = codec_mm_vmap(stbuf->buf_wp + i, len);
+ if (!src || !dst) {
+ ret = -EFAULT;
+ pr_err("[%d]: %s, src or dst is invalid.\n",
+ stbuf->id, __func__);
+ goto err;
+ }
+
+ if (aml_copy_from_user(dst, src, len)) {
+ ret = -EAGAIN;
+ goto err;
+ }
+
+ codec_mm_dma_flush(dst, len, DMA_TO_DEVICE);
+ codec_mm_unmap_phyaddr(dst);
+
+ if (stbuf->is_phybuf)
+ codec_mm_unmap_phyaddr(src);
+ }
+
+ return 0;
+err:
+ if (stbuf->is_phybuf && src)
+ codec_mm_unmap_phyaddr(src);
+ if (dst)
+ codec_mm_unmap_phyaddr(dst);
+ return ret;
+}
+
+static int rb_push_data(struct stream_buf_s *stbuf, const u8 *in, u32 size)
+{
+ int ret, len;
+ u32 wp = stbuf->buf_wp;
+ u32 sp = (stbuf->buf_wp + size);
+ u32 ep = (stbuf->buf_start + stbuf->buf_size);
+
+ len = sp > ep ? ep - wp : size;
+
+ if (!stbuf->ext_buf_addr) {
+ ret = stream_buffer_copy(stbuf, in, len);
+ if (ret)
+ return ret;
+ }
+
+ stbuf->ops->set_wp(stbuf, (wp + len >= ep) ?
+ stbuf->buf_start : (wp + len));
+
+ if (stbuf->buf_wp == stbuf->buf_rp) {
+ pr_debug("[%d]: stream buffer is full, payload: %d\n",
+ stbuf->id, atomic_read(&stbuf->payload));
+ }
+
+ return len;
+}
+
+static int stream_buffer_write_inner(struct stream_buf_s *stbuf,
+ const u8 *in, u32 size)
+{
+ if (in == NULL || size > stbuf->buf_size) {
+ pr_err("[%d]: params are not valid.\n", stbuf->id);
+ return -1;
+ }
+
+ if (get_free_space(stbuf) < size)
+ return -EAGAIN;
+
+ return rb_push_data(stbuf, in, size);
+}
+
+static u32 stream_buffer_get_wp(struct stream_buf_s *stbuf)
+{
+ return stbuf->buf_wp;
+}
+
+static void stream_buffer_set_wp(struct stream_buf_s *stbuf, u32 val)
+{
+ int len = (val >= stbuf->buf_wp) ? (val - stbuf->buf_wp) :
+ ((stbuf->buf_start + stbuf->buf_size) - stbuf->buf_wp);
+
+ stbuf->buf_wp = val;
+ atomic_add(len, &stbuf->payload);
+}
+
+static u32 stream_buffer_get_rp(struct stream_buf_s *stbuf)
+{
+ return stbuf->buf_rp;
+}
+
+static void stream_buffer_set_rp(struct stream_buf_s *stbuf, u32 val)
+{
+ int len = (val >= stbuf->buf_rp) ? (val - stbuf->buf_rp) :
+ ((stbuf->buf_start + stbuf->buf_size) - stbuf->buf_rp);
+
+ stbuf->buf_rp = val;
+ atomic_sub(len, &stbuf->payload);
+}
+
+static struct stream_buf_ops stream_buffer_ops = {
+ .init = stream_buffer_init,
+ .release = stream_buffer_release,
+ .write = stream_buffer_write_inner,
+ .get_wp = stream_buffer_get_wp,
+ .set_wp = stream_buffer_set_wp,
+ .get_rp = stream_buffer_get_rp,
+ .set_rp = stream_buffer_set_rp,
+};
+
+struct stream_buf_ops *get_stbuf_ops(void)
+{
+ return &stream_buffer_ops;
+}
+EXPORT_SYMBOL(get_stbuf_ops);
+
diff --git a/drivers/stream_input/parser/streambuf.c b/drivers/stream_input/amports/streambuf.c
index 1060770..20aa640 100644
--- a/drivers/stream_input/parser/streambuf.c
+++ b/drivers/stream_input/amports/streambuf.c
@@ -114,8 +114,8 @@ static s32 _stbuf_alloc(struct stream_buf_s *buf, bool is_secure)
buf->is_secure,
buf->buf_size);
}
- if (buf->buf_size < buf->canusebuf_size)
- buf->canusebuf_size = buf->buf_size;
+
+ buf->canusebuf_size = buf->buf_size;
buf->flag |= BUF_FLAG_ALLOC;
return 0;
@@ -210,17 +210,24 @@ static void _stbuf_timer_func(unsigned long arg)
u32 stbuf_level(struct stream_buf_s *buf)
{
if ((buf->type == BUF_TYPE_HEVC) || (buf->type == BUF_TYPE_VIDEO)) {
- if (READ_PARSER_REG(PARSER_ES_CONTROL) & 1) {
- int level = READ_PARSER_REG(PARSER_VIDEO_WP) -
- READ_PARSER_REG(PARSER_VIDEO_RP);
+ if (buf->no_parser) {
+ int level = buf->buf_wp - buf->buf_rp;
if (level < 0)
- level += READ_PARSER_REG(PARSER_VIDEO_END_PTR) -
- READ_PARSER_REG(PARSER_VIDEO_START_PTR) + 8;
- return (u32)level;
- } else
- return (buf->type == BUF_TYPE_HEVC) ?
- READ_VREG(HEVC_STREAM_LEVEL) :
- _READ_ST_REG(LEVEL);
+ level += buf->buf_size;
+ return level;
+ } else {
+ if (READ_PARSER_REG(PARSER_ES_CONTROL) & 1) {
+ int level = READ_PARSER_REG(PARSER_VIDEO_WP) -
+ READ_PARSER_REG(PARSER_VIDEO_RP);
+ if (level < 0)
+ level += READ_PARSER_REG(PARSER_VIDEO_END_PTR) -
+ READ_PARSER_REG(PARSER_VIDEO_START_PTR) + 8;
+ return (u32)level;
+ } else
+ return (buf->type == BUF_TYPE_HEVC) ?
+ READ_VREG(HEVC_STREAM_LEVEL) :
+ _READ_ST_REG(LEVEL);
+ }
}
return _READ_ST_REG(LEVEL);
@@ -229,12 +236,16 @@ u32 stbuf_level(struct stream_buf_s *buf)
u32 stbuf_rp(struct stream_buf_s *buf)
{
if ((buf->type == BUF_TYPE_HEVC) || (buf->type == BUF_TYPE_VIDEO)) {
- if (READ_PARSER_REG(PARSER_ES_CONTROL) & 1)
- return READ_PARSER_REG(PARSER_VIDEO_RP);
- else
- return (buf->type == BUF_TYPE_HEVC) ?
- READ_VREG(HEVC_STREAM_RD_PTR) :
- _READ_ST_REG(RP);
+ if (buf->no_parser)
+ return buf->buf_rp;
+ else {
+ if (READ_PARSER_REG(PARSER_ES_CONTROL) & 1)
+ return READ_PARSER_REG(PARSER_VIDEO_RP);
+ else
+ return (buf->type == BUF_TYPE_HEVC) ?
+ READ_VREG(HEVC_STREAM_RD_PTR) :
+ _READ_ST_REG(RP);
+ }
}
return _READ_ST_REG(RP);
@@ -271,7 +282,7 @@ u32 stbuf_canusesize(struct stream_buf_s *buf)
return buf->canusebuf_size;
}
-s32 stbuf_init(struct stream_buf_s *buf, struct vdec_s *vdec, bool is_multi)
+s32 stbuf_init(struct stream_buf_s *buf, struct vdec_s *vdec)
{
s32 r;
u32 dummy;
@@ -304,7 +315,7 @@ s32 stbuf_init(struct stream_buf_s *buf, struct vdec_s *vdec, bool is_multi)
}
buf->write_thread = 0;
- if (((vdec && !vdec_single(vdec)) || (is_multi)) &&
+ if (((vdec && !vdec_single(vdec)) || (buf->is_multi_inst)) &&
(vdec_get_debug_flags() & 0x2) == 0)
return 0;
if (has_hevc_vdec() && buf->type == BUF_TYPE_HEVC) {
@@ -364,6 +375,10 @@ s32 stbuf_init(struct stream_buf_s *buf, struct vdec_s *vdec, bool is_multi)
_SET_ST_REG_MASK(CONTROL,
(0x11 << 16) | MEM_FILL_ON_LEVEL | MEM_CTRL_FILL_EN |
MEM_CTRL_EMPTY_EN);
+
+ if (buf->no_parser)
+ _SET_ST_REG_MASK(CONTROL, 7 << 3);
+
return 0;
}
EXPORT_SYMBOL(stbuf_init);
@@ -412,13 +427,13 @@ s32 stbuf_wait_space(struct stream_buf_s *stream_buf, size_t count)
return 0;
}
-void stbuf_release(struct stream_buf_s *buf, bool is_multi)
+void stbuf_release(struct stream_buf_s *buf)
{
int r;
buf->first_tstamp = INVALID_PTS;
- r = stbuf_init(buf, NULL, is_multi);/* reinit buffer */
+ r = stbuf_init(buf, NULL);/* reinit buffer */
if (r < 0)
pr_err("stbuf_release %d, stbuf_init failed\n", __LINE__);
@@ -452,3 +467,28 @@ u32 stbuf_sub_start_get(void)
{
return READ_PARSER_REG(PARSER_SUB_START_PTR);
}
+
+u32 parser_get_wp(struct stream_buf_s *vb)
+{
+ return READ_PARSER_REG(PARSER_VIDEO_WP);
+}
+EXPORT_SYMBOL(parser_get_wp);
+
+void parser_set_wp(struct stream_buf_s *vb, u32 val)
+{
+ WRITE_PARSER_REG(PARSER_VIDEO_WP, val);
+}
+EXPORT_SYMBOL(parser_set_wp);
+
+u32 parser_get_rp(struct stream_buf_s *vb)
+{
+ return READ_PARSER_REG(PARSER_VIDEO_RP);
+}
+EXPORT_SYMBOL(parser_get_rp);
+
+void parser_set_rp(struct stream_buf_s *vb, u32 val)
+{
+ WRITE_PARSER_REG(PARSER_VIDEO_RP, val);
+}
+EXPORT_SYMBOL(parser_set_rp);
+
diff --git a/drivers/stream_input/parser/streambuf.h b/drivers/stream_input/amports/streambuf.h
index d73865e..8e4d2e3 100644
--- a/drivers/stream_input/parser/streambuf.h
+++ b/drivers/stream_input/amports/streambuf.h
@@ -38,8 +38,28 @@
#define USER_DATA_SIZE (8*1024)
struct vdec_s;
+struct stream_buf_s;
+
+struct parser_args {
+ u32 vid;
+ u32 aid;
+ u32 sid;
+ u32 pcrid;
+};
+
+struct stream_buf_ops {
+ int (*init) (struct stream_buf_s *, struct vdec_s *);
+ void (*release) (struct stream_buf_s *);
+ int (*write) (struct stream_buf_s *, const u8 *, u32);
+ u32 (*get_wp) (struct stream_buf_s *);
+ void (*set_wp) (struct stream_buf_s *, u32);
+ u32 (*get_rp) (struct stream_buf_s *);
+ void (*set_rp) (struct stream_buf_s *, u32);
+};
struct stream_buf_s {
+ int id;
+ u8 name[16];
s32 flag;
u32 type;
unsigned long buf_start;
@@ -60,6 +80,14 @@ struct stream_buf_s {
void *write_thread;
int for_4k;
bool is_secure;
+ bool is_multi_inst;
+ bool no_parser;
+ bool is_phybuf;
+ bool is_hevc;
+ ulong ext_buf_addr;
+ atomic_t payload;
+ struct parser_args pars;
+ struct stream_buf_ops *ops;
} /*stream_buf_t */;
struct stream_port_s {
@@ -85,6 +113,7 @@ struct stream_port_s {
u32 aid;
u32 sid;
u32 pcrid;
+ bool is_4k;
} /*stream_port_t */;
enum drm_level_e {
DRM_LEVEL1 = 1,
@@ -121,10 +150,9 @@ extern u32 stbuf_rp(struct stream_buf_s *buf);
extern u32 stbuf_space(struct stream_buf_s *buf);
extern u32 stbuf_size(struct stream_buf_s *buf);
extern u32 stbuf_canusesize(struct stream_buf_s *buf);
-extern s32 stbuf_init(struct stream_buf_s *buf, struct vdec_s *vdec,
- bool is_multi);
+extern s32 stbuf_init(struct stream_buf_s *buf, struct vdec_s *vdec);
extern s32 stbuf_wait_space(struct stream_buf_s *stream_buf, size_t count);
-extern void stbuf_release(struct stream_buf_s *buf, bool is_multi);
+extern void stbuf_release(struct stream_buf_s *buf);
extern int stbuf_change_size(struct stream_buf_s *buf, int size,
bool is_secure);
extern int stbuf_fetch_init(void);
@@ -138,4 +166,9 @@ extern struct stream_buf_s *get_stream_buffer(int id);
extern void stbuf_vdec2_init(struct stream_buf_s *buf);
+u32 parser_get_wp(struct stream_buf_s *vb);
+void parser_set_wp(struct stream_buf_s *vb, u32 val);
+u32 parser_get_rp(struct stream_buf_s *vb);
+void parser_set_rp(struct stream_buf_s *vb, u32 val);
+
#endif /* STREAMBUF_H */
diff --git a/drivers/stream_input/parser/streambuf_reg.h b/drivers/stream_input/amports/streambuf_reg.h
index 5f0c8ca..5f0c8ca 100644
--- a/drivers/stream_input/parser/streambuf_reg.h
+++ b/drivers/stream_input/amports/streambuf_reg.h
diff --git a/drivers/stream_input/parser/thread_rw.c b/drivers/stream_input/amports/thread_rw.c
index 4e4864f..0d386ce 100644
--- a/drivers/stream_input/parser/thread_rw.c
+++ b/drivers/stream_input/amports/thread_rw.c
@@ -33,8 +33,8 @@
/* #include <mach/am_regs.h> */
#include <linux/delay.h>
-#include "../../stream_input/parser/streambuf.h"
-#include "../../stream_input/amports/amports_priv.h"
+#include "streambuf.h"
+#include "amports_priv.h"
#include "thread_rw.h"
#define BUF_NAME "fetchbuf"
diff --git a/drivers/stream_input/parser/thread_rw.h b/drivers/stream_input/amports/thread_rw.h
index a91b004..4a93dee 100644
--- a/drivers/stream_input/parser/thread_rw.h
+++ b/drivers/stream_input/amports/thread_rw.h
@@ -17,8 +17,8 @@
#ifndef THREAD_RW_H
#define THREAD_RW_H
-#include "../../stream_input/parser/streambuf_reg.h"
-#include "../../stream_input/parser/streambuf.h"
+#include "../../stream_input/amports/streambuf_reg.h"
+#include "../../stream_input/amports/streambuf.h"
#include "../../stream_input/parser/esparser.h"
#include "../../stream_input/amports/amports_priv.h"
diff --git a/drivers/stream_input/parser/demux/hw_demux/hwdemux_inject.c b/drivers/stream_input/parser/demux/hw_demux/hwdemux_inject.c
index 0f201a9..a92d238 100644
--- a/drivers/stream_input/parser/demux/hw_demux/hwdemux_inject.c
+++ b/drivers/stream_input/parser/demux/hw_demux/hwdemux_inject.c
@@ -65,31 +65,31 @@
static DECLARE_WAIT_QUEUE_HEAD(wq);
static u32 fetch_done = 0;
-static void *fetchbuf = NULL;
+static void *fetchbuff = NULL;
static const char tsdemux_fetch_id[] = "tsdemux-fetch-id";
-static int stbuf_fetch_init(void)
+static int stbuff_fetch_init(void)
{
- if (NULL != fetchbuf)
+ if (NULL != fetchbuff)
return 0;
pr_dbg("%s line:%d\n",__FUNCTION__,__LINE__);
- fetchbuf = (void *)__get_free_pages(GFP_KERNEL,
+ fetchbuff = (void *)__get_free_pages(GFP_KERNEL,
get_order(FETCHBUF_SIZE));
- if (!fetchbuf) {
+ if (!fetchbuff) {
pr_info("%s: Can not allocate fetch working buffer\n",
__func__);
return -ENOMEM;
}
return 0;
}
-static void stbuf_fetch_release(void)
+static void stbuff_fetch_release(void)
{
- if (0 && fetchbuf) {
+ if (0 && fetchbuff) {
/* always don't free.for safe alloc/free*/
- free_pages((unsigned long)fetchbuf, get_order(FETCHBUF_SIZE));
- fetchbuf = 0;
+ free_pages((unsigned long)fetchbuff, get_order(FETCHBUF_SIZE));
+ fetchbuff = 0;
}
}
static irqreturn_t parser_isr(int irq, void *dev_id)
@@ -126,7 +126,7 @@ static void _hwdmx_inject_init(HWDMX_Demux *pdmx) {
if (pdmx->inject_init)
return ;
- stbuf_fetch_init();
+ stbuff_fetch_init();
r = vdec_request_irq(PARSER_IRQ, parser_isr,
"tsdemux-fetch", (void *)tsdemux_fetch_id);
@@ -160,12 +160,12 @@ static int _hwdmx_inject_write(HWDMX_Demux *pdmx, const char *buf, int count) {
len = count;
else {
len = min_t(size_t, r, FETCHBUF_SIZE);
- if (copy_from_user(fetchbuf, p, len))
+ if (copy_from_user(fetchbuff, p, len))
return -EFAULT;
dma_addr =
dma_map_single(hwdemux_get_dma_device(),
- fetchbuf,
+ fetchbuff,
FETCHBUF_SIZE, DMA_TO_DEVICE);
if (dma_mapping_error(hwdemux_get_dma_device(),
dma_addr))
@@ -174,7 +174,7 @@ static int _hwdmx_inject_write(HWDMX_Demux *pdmx, const char *buf, int count) {
fetch_done = 0;
- wmb(); /* Ensure fetchbuf contents visible */
+ wmb(); /* Ensure fetchbuff contents visible */
if (isphybuf) {
u32 buf_32 = (unsigned long)buf & 0xffffffff;
@@ -212,7 +212,7 @@ void hwdmx_inject_destroy(HWDMX_Demux *pdmx) {
if (!(pdmx && pdmx->init)) {
return ;
}
- stbuf_fetch_release();
+ stbuff_fetch_release();
WRITE_PARSER_REG(PARSER_INT_ENABLE, 0);
vdec_free_irq(PARSER_IRQ, (void *)tsdemux_fetch_id);
diff --git a/drivers/stream_input/parser/esparser.c b/drivers/stream_input/parser/esparser.c
index f81ba0c..94fafd1 100644
--- a/drivers/stream_input/parser/esparser.c
+++ b/drivers/stream_input/parser/esparser.c
@@ -35,11 +35,11 @@
#include "../../frame_provider/decoder/utils/vdec.h"
#include <linux/amlogic/media/utils/vdec_reg.h>
-#include "streambuf_reg.h"
-#include "streambuf.h"
+#include "../amports/streambuf_reg.h"
+#include "../amports/streambuf.h"
#include "esparser.h"
#include "../amports/amports_priv.h"
-#include "thread_rw.h"
+#include "../amports/thread_rw.h"
#include <linux/amlogic/media/codec_mm/codec_mm.h>
@@ -153,8 +153,7 @@ static inline u32 buf_wp(u32 type)
return wp;
}
-static ssize_t _esparser_write(const char __user *buf,
- size_t count, struct stream_buf_s *stbuf, int isphybuf)
+static int esparser_stbuf_write(struct stream_buf_s *stbuf, const u8 *buf, u32 count)
{
size_t r = count;
const char __user *p = buf;
@@ -179,7 +178,7 @@ static ssize_t _esparser_write(const char __user *buf,
wp = buf_wp(type);
if (r > 0) {
- if (isphybuf)
+ if (stbuf->is_phybuf)
len = count;
else {
len = min_t(size_t, r, (size_t) FETCHBUF_SIZE);
@@ -207,7 +206,7 @@ static ssize_t _esparser_write(const char __user *buf,
PARSER_AUTOSEARCH, ES_CTRL_BIT,
ES_CTRL_WID);
- if (isphybuf) {
+ if (stbuf->is_phybuf) {
u32 buf_32 = (unsigned long)buf & 0xffffffff;
WRITE_PARSER_REG(PARSER_FETCH_ADDR, buf_32);
} else {
@@ -217,7 +216,7 @@ static ssize_t _esparser_write(const char __user *buf,
}
search_done = 0;
- if (!(isphybuf & TYPE_PATTERN)) {
+ if (!(stbuf->is_phybuf & TYPE_PATTERN)) {
WRITE_PARSER_REG(PARSER_FETCH_CMD,
(7 << FETCH_ENDIAN) | len);
WRITE_PARSER_REG(PARSER_FETCH_ADDR, search_pattern_map);
@@ -238,7 +237,7 @@ static ssize_t _esparser_write(const char __user *buf,
} else {
pr_info("W Timeout, but fetch ok,");
pr_info("type %d len=%d,wpdiff=%d, isphy %x\n",
- type, len, wp - buf_wp(type), isphybuf);
+ type, len, wp - buf_wp(type), stbuf->is_phybuf);
}
} else if (ret < 0)
return -ERESTARTSYS;
@@ -256,6 +255,13 @@ static ssize_t _esparser_write(const char __user *buf,
return len;
}
+static ssize_t _esparser_write(const char __user *buf,
+ size_t count, struct stream_buf_s *stbuf, int isphybuf)
+{
+ return esparser_stbuf_write(stbuf, buf, count);
+}
+
+
static ssize_t _esparser_write_s(const char __user *buf,
size_t count, struct stream_buf_s *stbuf)
{
@@ -509,6 +515,11 @@ s32 esparser_init(struct stream_buf_s *buf, struct vdec_s *vdec)
/* set stream_fetch_enable */
SET_VREG_MASK(HEVC_STREAM_CONTROL, 1);
+ if (buf->no_parser) {
+ /*set endian for non-parser mode */
+ SET_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4);
+ }
+
/* set stream_buffer_hole with 256 bytes */
SET_VREG_MASK(HEVC_STREAM_FIFO_CTL, (1 << 29));
} else {
@@ -523,6 +534,7 @@ s32 esparser_init(struct stream_buf_s *buf, struct vdec_s *vdec)
vdec->input.start);
WRITE_PARSER_REG(PARSER_VIDEO_END_PTR,
vdec->input.start + vdec->input.size - 8);
+
if (vdec_single(vdec) || (vdec_get_debug_flags() & 0x2)) {
if (vdec_get_debug_flags() & 0x2)
pr_info("%s %d\n", __func__, __LINE__);
@@ -611,6 +623,7 @@ s32 esparser_init(struct stream_buf_s *buf, struct vdec_s *vdec)
PARSER_INT_HOST_EN_BIT);
}
mutex_unlock(&esparser_mutex);
+
if (!(vdec_get_debug_flags() & 1) &&
!codec_mm_video_tvp_enabled()) {
int block_size = (buf->type == BUF_TYPE_AUDIO) ?
@@ -624,6 +637,7 @@ s32 esparser_init(struct stream_buf_s *buf, struct vdec_s *vdec)
(buf->type == BUF_TYPE_AUDIO) ? 1 : 0);
/*manul mode for audio*/
}
+
return 0;
Err_2:
@@ -908,6 +922,9 @@ ssize_t esparser_write_ex(struct file *file,
mutex_lock(&esparser_mutex);
+ if (flags & 1)
+ stbuf->is_phybuf = true;
+
if (stbuf->type == BUF_TYPE_AUDIO)
r = _esparser_write_s(buf, len, stbuf);
else
@@ -982,3 +999,43 @@ void esparser_sub_reset(void)
spin_unlock_irqrestore(&lock, flags);
}
+
+static int esparser_stbuf_init(struct stream_buf_s *stbuf,
+ struct vdec_s *vdec)
+{
+ int ret = -1;
+
+ ret = stbuf_init(stbuf, vdec);
+ if (ret)
+ goto out;
+
+ ret = esparser_init(stbuf, vdec);
+ if (!ret)
+ stbuf->flag |= BUF_FLAG_IN_USE;
+out:
+ return ret;
+}
+
+static void esparser_stbuf_release(struct stream_buf_s *stbuf)
+{
+ esparser_release(stbuf);
+
+ stbuf_release(stbuf);
+}
+
+static struct stream_buf_ops esparser_stbuf_ops = {
+ .init = esparser_stbuf_init,
+ .release = esparser_stbuf_release,
+ .write = esparser_stbuf_write,
+ .get_wp = parser_get_wp,
+ .set_wp = parser_set_wp,
+ .get_rp = parser_get_rp,
+ .set_rp = parser_set_rp,
+};
+
+struct stream_buf_ops *get_esparser_stbuf_ops(void)
+{
+ return &esparser_stbuf_ops;
+}
+EXPORT_SYMBOL(get_esparser_stbuf_ops);
+
diff --git a/drivers/stream_input/parser/hw_demux/aml_dmx.c b/drivers/stream_input/parser/hw_demux/aml_dmx.c
index 787111e..488f052 100644
--- a/drivers/stream_input/parser/hw_demux/aml_dmx.c
+++ b/drivers/stream_input/parser/hw_demux/aml_dmx.c
@@ -45,7 +45,7 @@
#include <linux/vmalloc.h>
#include <linux/amlogic/media/codec_mm/codec_mm.h>
#include <linux/amlogic/media/codec_mm/configs.h>
-#include "../streambuf.h"
+#include "../../amports/streambuf.h"
#include "c_stb_define.h"
#include "c_stb_regs_define.h"
#include "aml_dvb.h"
diff --git a/drivers/stream_input/parser/psparser.c b/drivers/stream_input/parser/psparser.c
index 771314a..20c1d1a 100644
--- a/drivers/stream_input/parser/psparser.c
+++ b/drivers/stream_input/parser/psparser.c
@@ -30,8 +30,8 @@
#include <linux/uaccess.h>
/* #include <mach/am_regs.h> */
#include <linux/amlogic/media/utils/vdec_reg.h>
-#include "streambuf_reg.h"
-#include "streambuf.h"
+#include "../amports/streambuf_reg.h"
+#include "../amports/streambuf.h"
#include "psparser.h"
#include "../amports/amports_priv.h"
@@ -1153,3 +1153,47 @@ u8 psparser_get_sub_info(struct subtitle_info **sub_infos)
return 0;
#endif
}
+
+static int psparser_stbuf_init(struct stream_buf_s *stbuf,
+ struct vdec_s *vdec)
+{
+ int ret = -1;
+
+ ret = stbuf_init(stbuf, vdec);
+ if (ret)
+ goto out;
+
+ ret = psparser_init(stbuf->pars.vid,
+ stbuf->pars.aid,
+ stbuf->pars.sid,
+ vdec);
+ if (ret)
+ goto out;
+
+ stbuf->flag |= BUF_FLAG_IN_USE;
+out:
+ return ret;
+}
+
+static void psparser_stbuf_release(struct stream_buf_s *stbuf)
+{
+ psparser_release();
+
+ stbuf_release(stbuf);
+}
+
+static struct stream_buf_ops psparser_stbuf_ops = {
+ .init = psparser_stbuf_init,
+ .release = psparser_stbuf_release,
+ .get_wp = parser_get_wp,
+ .set_wp = parser_set_wp,
+ .get_rp = parser_get_rp,
+ .set_rp = parser_set_rp,
+};
+
+struct stream_buf_ops *get_psparser_stbuf_ops(void)
+{
+ return &psparser_stbuf_ops;
+}
+EXPORT_SYMBOL(get_psparser_stbuf_ops);
+
diff --git a/drivers/stream_input/parser/rmparser.c b/drivers/stream_input/parser/rmparser.c
index 9f7a1b0..902dc5a 100644
--- a/drivers/stream_input/parser/rmparser.c
+++ b/drivers/stream_input/parser/rmparser.c
@@ -30,8 +30,8 @@
#include <linux/amlogic/media/utils/vdec_reg.h>
#include "../amports/amports_priv.h"
-#include "streambuf.h"
-#include "streambuf_reg.h"
+#include "../amports/streambuf.h"
+#include "../amports/streambuf_reg.h"
#include <linux/delay.h>
#include "rmparser.h"
diff --git a/drivers/stream_input/parser/tsdemux.c b/drivers/stream_input/parser/tsdemux.c
index 7aa8a06..9ba65b5 100644
--- a/drivers/stream_input/parser/tsdemux.c
+++ b/drivers/stream_input/parser/tsdemux.c
@@ -39,9 +39,10 @@
#include "../../frame_provider/decoder/utils/vdec.h"
#include <linux/amlogic/media/utils/vdec_reg.h>
-#include "streambuf_reg.h"
-#include "streambuf.h"
+#include "../amports/streambuf_reg.h"
+#include "../amports/streambuf.h"
#include <linux/amlogic/media/utils/amports_config.h>
+#include <linux/amlogic/media/frame_sync/tsync_pcr.h>
#include "tsdemux.h"
#include <linux/reset.h>
@@ -385,6 +386,7 @@ static int reset_pcr_regs(void)
{
u32 pcr_num;
u32 pcr_regs = 0;
+
if (curr_pcr_id >= 0x1FFF)
return 0;
/* set paramater to fetch pcr */
@@ -1201,4 +1203,53 @@ void tsdemux_tsync_func_init(void)
TSYNC_STBUF_SIZE, (void *)(stbuf_size));
}
+static int tsparser_stbuf_init(struct stream_buf_s *stbuf,
+ struct vdec_s *vdec)
+{
+ int ret = -1;
+
+ ret = stbuf_init(stbuf, vdec);
+ if (ret)
+ goto out;
+
+ ret = tsdemux_init(stbuf->pars.vid,
+ stbuf->pars.aid,
+ stbuf->pars.sid,
+ stbuf->pars.pcrid,
+ stbuf->is_hevc,
+ vdec);
+ if (ret)
+ goto out;
+
+ tsync_pcr_start();
+
+ stbuf->flag |= BUF_FLAG_IN_USE;
+out:
+ return ret;
+}
+
+static void tsparser_stbuf_release(struct stream_buf_s *stbuf)
+{
+ tsync_pcr_stop();
+
+ tsdemux_release();
+
+ stbuf_release(stbuf);
+}
+
+static struct stream_buf_ops tsparser_stbuf_ops = {
+ .init = tsparser_stbuf_init,
+ .release = tsparser_stbuf_release,
+ .get_wp = parser_get_wp,
+ .set_wp = parser_set_wp,
+ .get_rp = parser_get_rp,
+ .set_rp = parser_set_rp,
+};
+
+struct stream_buf_ops *get_tsparser_stbuf_ops(void)
+{
+ return &tsparser_stbuf_ops;
+}
+EXPORT_SYMBOL(get_tsparser_stbuf_ops);
+