author | Bin Yang <bin.yang@amlogic.com> | 2019-11-08 09:43:40 (GMT) |
---|---|---|
committer | Dai-Yang Wu <dywu@google.com> | 2019-11-14 05:49:44 (GMT) |
commit | 02d43d3ff042d22fd7b25b40c8639ce7100f1c20 (patch) | |
tree | b20e162b21afdf8ab55f9f443eea132a4db4d00c | |
parent | 66bd0c5e10ee610750730904aa338ed78c23afbe (diff) | |
download | media_modules-02d43d3ff042d22fd7b25b40c8639ce7100f1c20.zip media_modules-02d43d3ff042d22fd7b25b40c8639ce7100f1c20.tar.gz media_modules-02d43d3ff042d22fd7b25b40c8639ce7100f1c20.tar.bz2 |
Merge "sabrina: sync code with ref Q server [1/1]" into amlogic-4.9-dev
media_modules:148b9ad615306ad79388716d2d9f3d6d6c73965e
Change-Id: I38a5da87ad4452a76d65d9ec2681634629c1ee65
Signed-off-by: Bin Yang <bin.yang@amlogic.com>
Reviewed-on: https://eureka-partner-review.googlesource.com/c/amlogic/media_modules/+/145287
Reviewed-by: Ying Hsu <yinghsu@google.com>
71 files changed, 31950 insertions, 21543 deletions
diff --git a/drivers/amvdec_ports/Makefile b/drivers/amvdec_ports/Makefile index 76658a3..86bc158 100644 --- a/drivers/amvdec_ports/Makefile +++ b/drivers/amvdec_ports/Makefile @@ -9,5 +9,14 @@ amvdec_ports-objs += vdec_drv_if.o amvdec_ports-objs += decoder/vdec_h264_if.o amvdec_ports-objs += decoder/vdec_hevc_if.o amvdec_ports-objs += decoder/vdec_vp9_if.o -amvdec_ports-objs += decoder/h264_parse.o -amvdec_ports-objs += decoder/h264_stream.o +amvdec_ports-objs += decoder/vdec_mpeg12_if.o +amvdec_ports-objs += decoder/vdec_mpeg4_if.o +amvdec_ports-objs += decoder/vdec_mjpeg_if.o +amvdec_ports-objs += decoder/aml_h264_parser.o +amvdec_ports-objs += decoder/aml_hevc_parser.o +amvdec_ports-objs += decoder/aml_vp9_parser.o +amvdec_ports-objs += decoder/aml_mpeg12_parser.o +amvdec_ports-objs += decoder/aml_mpeg4_parser.o +amvdec_ports-objs += decoder/aml_mjpeg_parser.o +amvdec_ports-objs += utils/golomb.o +amvdec_ports-objs += utils/common.o diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.c b/drivers/amvdec_ports/aml_vcodec_adapt.c index b596d4d..f4bfc55 100644 --- a/drivers/amvdec_ports/aml_vcodec_adapt.c +++ b/drivers/amvdec_ports/aml_vcodec_adapt.c @@ -53,8 +53,9 @@ #define PTS_OUTSIDE (1) #define SYNC_OUTSIDE (2) #define USE_V4L_PORTS (0x80) +#define SCATTER_MEM (0x100) -#define DATA_DEBUG +//#define DATA_DEBUG static int def_4k_vstreambuf_sizeM = (DEFAULT_VIDEO_BUFFER_SIZE_4K >> 20); @@ -113,7 +114,9 @@ extern bool aml_set_vfm_enable, aml_set_vdec_type_enable; static void set_default_params(struct aml_vdec_adapt *vdec) { - unsigned long sync_mode = (PTS_OUTSIDE | SYNC_OUTSIDE | USE_V4L_PORTS); + ulong sync_mode = (PTS_OUTSIDE | SYNC_OUTSIDE | USE_V4L_PORTS); + + sync_mode |= vdec->ctx->scatter_mem_enable ? SCATTER_MEM : 0; vdec->dec_prop.param = (void *)sync_mode; vdec->dec_prop.format = vdec->format; vdec->dec_prop.width = 1920; @@ -463,7 +466,7 @@ static void set_vdec_properity(struct vdec_s *vdec, { vdec->sys_info = &ada_ctx->dec_prop; vdec->port = &ada_ctx->port; - vdec->format = ada_ctx->dec_prop.format; + vdec->format = ada_ctx->video_type; vdec->sys_info_store = ada_ctx->dec_prop; vdec->vf_receiver_name = ada_ctx->recv_name; @@ -668,22 +671,15 @@ int is_need_to_buf(struct aml_vdec_adapt *ada_ctx) } int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, - const char *buf, unsigned int count, unsigned long int timestamp) + const char *buf, unsigned int count, u64 timestamp) { int ret = -1; - int try_cnt = 100; struct vdec_s *vdec = ada_ctx->vdec; /* set timestamp */ vdec_set_timestamp(vdec, timestamp); - do { - ret = vdec_write_vframe(vdec, buf, count); - if (ret == -EAGAIN) { - /*vdec_input_level(&vdec->input);*/ - msleep(30); - } - } while (ret == -EAGAIN && try_cnt--); + ret = vdec_write_vframe(vdec, buf, count); if (slow_input) { pr_info("slow_input: frame codec write size %d\n", ret); @@ -694,7 +690,7 @@ int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, /* dump to file */ dump_write(buf, count); #endif - aml_v4l2_debug(2, "[%d] write frames, vbuf: %p, size: %u, ret: %d, crc: %x", + aml_v4l2_debug(4, "[%d] write frames, vbuf: %p, size: %u, ret: %d, crc: %x", ada_ctx->ctx->id, buf, count, ret, crc32_le(0, buf, count)); return ret; diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.h b/drivers/amvdec_ports/aml_vcodec_adapt.h index 9788718..5a69312 100644 --- a/drivers/amvdec_ports/aml_vcodec_adapt.h +++ b/drivers/amvdec_ports/aml_vcodec_adapt.h @@ -38,6 +38,7 @@ struct aml_vdec_adapt { struct vdec_s *vdec; struct stream_port_s port; struct dec_sysinfo dec_prop; + int video_type; char *recv_name; int vfm_path; }; @@ -50,7 +51,7 @@ int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx, const char *buf, unsigned int count); int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, - const char *buf, unsigned int count, unsigned long int timestamp); + const char *buf, unsigned int count, u64 timestamp); int is_need_to_buf(struct aml_vdec_adapt *ada_ctx); diff --git a/drivers/amvdec_ports/aml_vcodec_dec.c b/drivers/amvdec_ports/aml_vcodec_dec.c index a2a1b98..9c34b49 100644 --- a/drivers/amvdec_ports/aml_vcodec_dec.c +++ b/drivers/amvdec_ports/aml_vcodec_dec.c @@ -31,11 +31,12 @@ #include <linux/atomic.h> #include <linux/crc32.h> #include "aml_vcodec_adapt.h" +#include <linux/spinlock.h> #include "aml_vcodec_vfm.h" #define OUT_FMT_IDX 0 //default h264 -#define CAP_FMT_IDX 3 //capture nv21 +#define CAP_FMT_IDX 8 //capture nv21 #define AML_VDEC_MIN_W 64U #define AML_VDEC_MIN_H 64U @@ -72,8 +73,43 @@ static struct aml_video_fmt aml_video_formats[] = { .num_planes = 1, }, { + .fourcc = V4L2_PIX_FMT_MPEG1, + .type = AML_FMT_DEC, + .num_planes = 1, + }, + { + .fourcc = V4L2_PIX_FMT_MPEG2, + .type = AML_FMT_DEC, + .num_planes = 1, + }, + { + .fourcc = V4L2_PIX_FMT_MPEG4, + .type = AML_FMT_DEC, + .num_planes = 1, + }, + { + .fourcc = V4L2_PIX_FMT_MJPEG, + .type = AML_FMT_DEC, + .num_planes = 1, + }, + { + .fourcc = V4L2_PIX_FMT_NV21, + .type = AML_FMT_FRAME, + .num_planes = 1, + }, + { + .fourcc = V4L2_PIX_FMT_NV21M, + .type = AML_FMT_FRAME, + .num_planes = 2, + }, + { .fourcc = V4L2_PIX_FMT_NV12, .type = AML_FMT_FRAME, + .num_planes = 1, + }, + { + .fourcc = V4L2_PIX_FMT_NV12M, + .type = AML_FMT_FRAME, .num_planes = 2, }, }; @@ -94,16 +130,56 @@ static const struct aml_codec_framesizes aml_vdec_framesizes[] = { .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 8, AML_VDEC_MIN_H, AML_VDEC_MAX_H, 8 }, }, + { + .fourcc = V4L2_PIX_FMT_MPEG1, + .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 8, + AML_VDEC_MIN_H, AML_VDEC_MAX_H, 8 }, + }, + { + .fourcc = V4L2_PIX_FMT_MPEG2, + .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 8, + AML_VDEC_MIN_H, AML_VDEC_MAX_H, 8 }, + }, + { + .fourcc = V4L2_PIX_FMT_MPEG4, + .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 8, + AML_VDEC_MIN_H, AML_VDEC_MAX_H, 8 }, + }, + { + .fourcc = V4L2_PIX_FMT_MJPEG, + .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 8, + AML_VDEC_MIN_H, AML_VDEC_MAX_H, 8 }, + }, }; #define NUM_SUPPORTED_FRAMESIZE ARRAY_SIZE(aml_vdec_framesizes) #define NUM_FORMATS ARRAY_SIZE(aml_video_formats) +extern bool multiplanar; + +static ulong aml_vcodec_ctx_lock(struct aml_vcodec_ctx *ctx) +{ + ulong flags; + + spin_lock_irqsave(&ctx->slock, flags); + + return flags; +} + +static void aml_vcodec_ctx_unlock(struct aml_vcodec_ctx *ctx, ulong flags) +{ + spin_unlock_irqrestore(&ctx->slock, flags); +} + static struct aml_video_fmt *aml_vdec_find_format(struct v4l2_format *f) { struct aml_video_fmt *fmt; unsigned int k; + aml_v4l2_debug(4, "%s, type: %u, planes: %u, fmt: %u\n", + __func__, f->type, f->fmt.pix_mp.num_planes, + f->fmt.pix_mp.pixelformat); + for (k = 0; k < NUM_FORMATS; k++) { fmt = &aml_video_formats[k]; if (fmt->fourcc == f->fmt.pix_mp.pixelformat) @@ -179,59 +255,105 @@ static void aml_vdec_pic_info_update(struct aml_vcodec_ctx *ctx) ctx->picinfo = ctx->last_decoded_picinfo; } -int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb **out_fb) +int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_fb) { + ulong flags; struct vb2_buffer *dst_buf = NULL; - struct vdec_fb *pfb; + struct vdec_v4l2_buffer *pfb; struct aml_video_dec_buf *dst_buf_info, *info; struct vb2_v4l2_buffer *dst_vb2_v4l2; - int try_cnt = 100; - - aml_v4l2_debug(4, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); - do { - dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); - if (dst_buf) - break; - aml_v4l2_debug(3, "[%d] waitting enough dst buffers.", ctx->id); - msleep(30); - } while (try_cnt--); + flags = aml_vcodec_ctx_lock(ctx); - if (!dst_buf) + dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + if (!dst_buf) { + aml_vcodec_ctx_unlock(ctx, flags); return -1; + } + + aml_v4l2_debug(2, "[%d] %s() vbuf idx: %d, state: %d, ready: %d", + ctx->id, __func__, dst_buf->index, dst_buf->state, + v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)); dst_vb2_v4l2 = container_of(dst_buf, struct vb2_v4l2_buffer, vb2_buf); dst_buf_info = container_of(dst_vb2_v4l2, struct aml_video_dec_buf, vb); - pfb = &dst_buf_info->frame_buffer; - //pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0); - pfb->base_y.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); - pfb->base_y.va = phys_to_virt(dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->base_y.dma_addr)); - pfb->base_y.size = ctx->picinfo.y_len_sz; - - //pfb->base_c.va = vb2_plane_vaddr(dst_buf, 1); - pfb->base_c.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 1); - pfb->base_c.va = phys_to_virt(dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->base_c.dma_addr)); - pfb->base_c.size = ctx->picinfo.c_len_sz; - pfb->status = FB_ST_NORMAL; - - aml_v4l2_debug(4, "[%d] id=%d Framebuf pfb=%p VA=%p Y_DMA=%pad C_DMA=%pad y_size=%zx, c_size: %zx", - ctx->id, dst_buf->index, pfb, pfb->base_y.va, &pfb->base_y.dma_addr, - &pfb->base_c.dma_addr, pfb->base_y.size, pfb->base_c.size); + if (ctx->scatter_mem_enable) { + pfb = &dst_buf_info->frame_buffer; + pfb->mem_type = VDEC_SCATTER_MEMORY_TYPE; + pfb->status = FB_ST_NORMAL; + } else if (dst_buf->num_planes == 1) { + pfb = &dst_buf_info->frame_buffer; + pfb->m.mem[0].dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); + pfb->m.mem[0].addr = dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[0].dma_addr); + pfb->m.mem[0].size = ctx->picinfo.y_len_sz + ctx->picinfo.c_len_sz; + pfb->m.mem[0].offset = ctx->picinfo.y_len_sz; + pfb->num_planes = dst_buf->num_planes; + pfb->status = FB_ST_NORMAL; + + aml_v4l2_debug(4, "[%d] idx: %u, 1 plane, y:(0x%lx, %d)", + ctx->id, dst_buf->index, + pfb->m.mem[0].addr, pfb->m.mem[0].size); + } else if (dst_buf->num_planes == 2) { + pfb = &dst_buf_info->frame_buffer; + pfb->m.mem[0].dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); + pfb->m.mem[0].addr = dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[0].dma_addr); + pfb->m.mem[0].size = ctx->picinfo.y_len_sz; + pfb->m.mem[0].offset = 0; + + pfb->m.mem[1].dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 1); + pfb->m.mem[1].addr = dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[1].dma_addr); + pfb->m.mem[1].size = ctx->picinfo.c_len_sz; + pfb->m.mem[1].offset = ctx->picinfo.c_len_sz >> 1; + pfb->num_planes = dst_buf->num_planes; + pfb->status = FB_ST_NORMAL; + + aml_v4l2_debug(4, "[%d] idx: %u, 2 planes, y:(0x%lx, %d), c:(0x%lx, %d)", + ctx->id, dst_buf->index, + pfb->m.mem[0].addr, pfb->m.mem[0].size, + pfb->m.mem[1].addr, pfb->m.mem[1].size); + } else { + pfb = &dst_buf_info->frame_buffer; + pfb->m.mem[0].dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); + pfb->m.mem[0].addr = dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[0].dma_addr); + pfb->m.mem[0].size = ctx->picinfo.y_len_sz; + pfb->m.mem[0].offset = 0; + + pfb->m.mem[1].dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 1); + pfb->m.mem[1].addr = dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[2].dma_addr); + pfb->m.mem[1].size = ctx->picinfo.c_len_sz >> 1; + pfb->m.mem[1].offset = 0; + + pfb->m.mem[2].dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 2); + pfb->m.mem[2].addr = dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[3].dma_addr); + pfb->m.mem[2].size = ctx->picinfo.c_len_sz >> 1; + pfb->m.mem[2].offset = 0; + pfb->num_planes = dst_buf->num_planes; + pfb->status = FB_ST_NORMAL; + + aml_v4l2_debug(4, "[%d] idx: %u, 3 planes, y:(0x%lx, %d), u:(0x%lx, %d), v:(0x%lx, %d)", + ctx->id, dst_buf->index, + pfb->m.mem[0].addr, pfb->m.mem[0].size, + pfb->m.mem[1].addr, pfb->m.mem[1].size, + pfb->m.mem[2].addr, pfb->m.mem[2].size); + } dst_buf_info->used = true; - - v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); + ctx->buf_used_count++; *out_fb = pfb; info = container_of(pfb, struct aml_video_dec_buf, frame_buffer); + v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); + + aml_vcodec_ctx_unlock(ctx, flags); + return 0; } EXPORT_SYMBOL(get_fb_from_queue); -int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb *in_fb) +int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *in_fb) { struct aml_video_dec_buf *dstbuf; @@ -267,32 +389,57 @@ out: } EXPORT_SYMBOL(put_fb_to_queue); -void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_fb *fb) +void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *fb) { struct aml_video_dec_buf *dstbuf = NULL; struct vframe_s *vf = (struct vframe_s *)fb->vf_handle; - aml_v4l2_debug(2, "[%d] FROM (%s %s) vf: %p, ts: %llx, idx: %d", + aml_v4l2_debug(3, "[%d] FROM (%s %s) vf: %p, ts: %llx, idx: %d", ctx->id, vf_get_provider(ctx->ada_ctx->recv_name)->name, ctx->ada_ctx->vfm_path != FRAME_BASE_PATH_V4L_VIDEO ? "OSD" : "VIDEO", vf, vf->timestamp, vf->index); + aml_v4l2_debug(4, "[%d] FROM Y:(%lx, %u) C/U:(%lx, %u) V:(%lx, %u)", + ctx->id, fb->m.mem[0].addr, fb->m.mem[0].size, + fb->m.mem[1].addr, fb->m.mem[1].size, + fb->m.mem[2].addr, fb->m.mem[2].size); + dstbuf = container_of(fb, struct aml_video_dec_buf, frame_buffer); - vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, fb->base_y.bytes_used); - vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1, fb->base_c.bytes_used); + if (dstbuf->frame_buffer.num_planes == 1) { + vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, fb->m.mem[0].bytes_used); + } else if (dstbuf->frame_buffer.num_planes == 2) { + vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, fb->m.mem[0].bytes_used); + vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1, fb->m.mem[1].bytes_used); + } dstbuf->vb.vb2_buf.timestamp = vf->timestamp; dstbuf->ready_to_display = true; if (vf->flag & VFRAME_FLAG_EMPTY_FRAME_V4L) { dstbuf->lastframe = true; dstbuf->vb.flags = V4L2_BUF_FLAG_LAST; - vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, 0); - vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1, 0); + if (dstbuf->frame_buffer.num_planes == 1) { + vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, 0); + } else if (dstbuf->frame_buffer.num_planes == 2) { + vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, 0); + vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1, 0); + } ctx->has_receive_eos = true; - pr_info("[%d] recevie a empty frame.\n", ctx->id); + pr_info("[%d] recevie a empty frame. idx: %d, state: %d\n", + ctx->id, dstbuf->vb.vb2_buf.index, + dstbuf->vb.vb2_buf.state); } - v4l2_m2m_buf_done(&dstbuf->vb, VB2_BUF_STATE_DONE); + aml_v4l2_debug(4, "[%d] receive vbuf idx: %d, state: %d", + ctx->id, dstbuf->vb.vb2_buf.index, + dstbuf->vb.vb2_buf.state); + + if (dstbuf->vb.vb2_buf.state == VB2_BUF_STATE_ACTIVE) { + /* binding vframe handle. */ + if (fb->mem_type == VDEC_SCATTER_MEMORY_TYPE) + dstbuf->vb.private = fb->m.vf_fd; + + v4l2_m2m_buf_done(&dstbuf->vb, VB2_BUF_STATE_DONE); + } mutex_lock(&ctx->state_lock); if (ctx->state == AML_STATE_FLUSHING && @@ -319,7 +466,7 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_fb *fb) ctx->decoded_frame_cnt++; } -static int get_display_buffer(struct aml_vcodec_ctx *ctx, struct vdec_fb **out) +static int get_display_buffer(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out) { int ret = -1; @@ -355,8 +502,8 @@ static int is_vdec_ready(struct aml_vcodec_ctx *ctx) /* is there enough dst bufs for decoding? */ buf_ready_num = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx); - if (buf_ready_num < ctx->dpb_size) { - aml_v4l2_debug(4, "[%d] Not enough dst bufs, num: %d.\n", + if ((buf_ready_num + ctx->buf_used_count) < ctx->dpb_size) { + aml_v4l2_debug(4, "[%d] Not enough dst bufs, num: %d.", ctx->id, buf_ready_num); v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); v4l2_m2m_try_schedule(ctx->m2m_ctx); @@ -367,6 +514,8 @@ static int is_vdec_ready(struct aml_vcodec_ctx *ctx) mutex_lock(&ctx->state_lock); if (ctx->state == AML_STATE_PROBE) { ctx->state = AML_STATE_READY; + ctx->v4l_codec_ready = true; + wake_up_interruptible(&ctx->wq); aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_READY)", ctx->id, __func__); } @@ -375,9 +524,12 @@ static int is_vdec_ready(struct aml_vcodec_ctx *ctx) mutex_lock(&ctx->state_lock); if (ctx->state == AML_STATE_READY) { - ctx->state = AML_STATE_ACTIVE; - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ACTIVE)", - ctx->id, __func__); + if (ctx->m2m_ctx->out_q_ctx.q.streaming && + ctx->m2m_ctx->cap_q_ctx.q.streaming) { + ctx->state = AML_STATE_ACTIVE; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ACTIVE)", + ctx->id, __func__); + } } mutex_unlock(&ctx->state_lock); @@ -410,8 +562,6 @@ static void aml_vdec_worker(struct work_struct *work) aml_v4l2_debug(4, "[%d] entry [%d] [%s]", ctx->id, __LINE__, __func__); - aml_vdec_lock(ctx); - if (ctx->state < AML_STATE_INIT || ctx->state > AML_STATE_FLUSHED) { v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); @@ -458,19 +608,16 @@ static void aml_vdec_worker(struct work_struct *work) goto out; } - buf.va = vb2_plane_vaddr(src_buf, 0); + buf.vaddr = vb2_plane_vaddr(src_buf, 0); buf.dma_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0); - //buf.va = phys_to_virt(dma_to_phys(v4l_get_dev_from_codec_mm(), buf.dma_addr)); - buf.size = (size_t)src_buf->planes[0].bytesused; - if (!buf.va) { + buf.size = src_buf->planes[0].bytesused; + if (!buf.vaddr) { v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); aml_v4l2_err("[%d] id=%d src_addr is NULL!!", ctx->id, src_buf->index); goto out; } - aml_v4l2_debug(4, "[%d] Bitstream VA=%p DMA=%pad Size=%zx vb=%p", - ctx->id, buf.va, &buf.dma_addr, buf.size, src_buf); src_buf_info->used = true; @@ -521,56 +668,34 @@ static void aml_vdec_worker(struct work_struct *work) v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); out: - aml_vdec_unlock(ctx); + return; } -static void aml_reset_worker(struct work_struct *work) +void wait_vcodec_ending(struct aml_vcodec_ctx *ctx) { - struct aml_vcodec_ctx *ctx = - container_of(work, struct aml_vcodec_ctx, reset_work); - //struct aml_video_dec_buf *buf = NULL; - int try_cnt = 10; + struct aml_vcodec_dev *dev = ctx->dev; - aml_vdec_lock(ctx); + /* pause inject output data to vdec. */ + v4l2_m2m_job_pause(dev->m2m_dev_dec, ctx->m2m_ctx); - if (ctx->state == AML_STATE_ABORT) { - pr_err("[%d] %s() the decoder will be exited.\n", - ctx->id, __func__); - goto out; - } - - while (!v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx)) { - pr_err("[%d] %s() src data is not ready.\n", - ctx->id, __func__); + /* flush worker. */ + flush_workqueue(dev->decode_workqueue); - if (try_cnt--) { - msleep(30); - continue; - } + /* wait reset worker ending. */ + if (ctx->state == AML_STATE_RESET) { + wait_for_completion_timeout(&ctx->comp, + msecs_to_jiffies(200)); + } +} - ctx->state = AML_STATE_ABORT; - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", +static void aml_vdec_reset(struct aml_vcodec_ctx *ctx) +{ + if (ctx->state == AML_STATE_ABORT) { + pr_err("[%d] %s() the decoder will be exited.\n", ctx->id, __func__); goto out; } -#if 0 - /* - *fast enque capture buffers, but need to realloc - *bufs if the resolution change event was hanped. - */ - if (!ctx->q_data[AML_Q_DATA_SRC].resolution_changed) { - list_for_each_entry(buf, &ctx->capture_list, node) { - buf->que_in_m2m = true; - buf->queued_in_vb2 = true; - buf->queued_in_v4l2 = true; - buf->ready_to_display = false; - buf->frame_buffer.status = FB_ST_NORMAL; - v4l2_m2m_buf_queue(ctx->m2m_ctx, &buf->vb); - pr_err("que buf idx: %d\n", buf->vb.vb2_buf.index); - } - } -#endif if (aml_codec_reset(ctx->ada_ctx)) { ctx->state = AML_STATE_ABORT; aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", @@ -578,25 +703,24 @@ static void aml_reset_worker(struct work_struct *work) goto out; } - mutex_lock(&ctx->state_lock); if (ctx->state == AML_STATE_RESET) { - ctx->state = AML_STATE_READY; - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_READY)", + ctx->state = AML_STATE_PROBE; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_PROBE)", ctx->id, __func__); /* vdec has ready to decode subsequence data of new resolution. */ ctx->q_data[AML_Q_DATA_SRC].resolution_changed = false; v4l2_m2m_job_resume(ctx->dev->m2m_dev_dec, ctx->m2m_ctx); } - mutex_unlock(&ctx->state_lock); out: - aml_vdec_unlock(ctx); + complete(&ctx->comp); + return; } void try_to_capture(struct aml_vcodec_ctx *ctx) { int ret = 0; - struct vdec_fb *fb = NULL; + struct vdec_v4l2_buffer *fb = NULL; ret = get_display_buffer(ctx, &fb); if (ret) { @@ -611,11 +735,15 @@ EXPORT_SYMBOL_GPL(try_to_capture); static int vdec_thread(void *data) { + struct sched_param param = + {.sched_priority = MAX_RT_PRIO / 2}; struct aml_vdec_thread *thread = (struct aml_vdec_thread *) data; struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *) thread->priv; + sched_setscheduler(current, SCHED_FIFO, ¶m); + for (;;) { aml_v4l2_debug(3, "[%d] %s() state: %d", ctx->id, __func__, ctx->state); @@ -717,6 +845,7 @@ static int vidioc_try_decoder_cmd(struct file *file, void *priv, default: return -EINVAL; } + return 0; } @@ -734,7 +863,8 @@ static int vidioc_decoder_cmd(struct file *file, void *priv, aml_v4l2_debug(3, "[%d] %s() [%d], cmd: %u", ctx->id, __func__, __LINE__, cmd->cmd); dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, - V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + multiplanar ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : + V4L2_BUF_TYPE_VIDEO_CAPTURE); switch (cmd->cmd) { case V4L2_DEC_CMD_STOP: @@ -757,6 +887,9 @@ static int vidioc_decoder_cmd(struct file *file, void *priv, v4l2_m2m_buf_queue(ctx->m2m_ctx, &ctx->empty_flush_buf->vb); v4l2_m2m_try_schedule(ctx->m2m_ctx);//pay attention + /* remark cmd use to distinguish stop or seek. */ + ctx->receive_cmd_stop = true; + break; case V4L2_DEC_CMD_START: @@ -776,7 +909,6 @@ static int vidioc_decoder_streamon(struct file *file, void *priv, { struct v4l2_fh *fh = file->private_data; struct aml_vcodec_ctx *ctx = fh_to_ctx(fh); - struct aml_vcodec_dev *dev = ctx->dev; struct vb2_queue *q; int ret = 0; @@ -784,18 +916,35 @@ static int vidioc_decoder_streamon(struct file *file, void *priv, q = v4l2_m2m_get_vq(fh->m2m_ctx, i); - mutex_lock(&ctx->state_lock); + if (!V4L2_TYPE_IS_OUTPUT(q->type)) { + mutex_lock(&ctx->state_lock); - if (ctx->state == AML_STATE_FLUSHED) { - if (!V4L2_TYPE_IS_OUTPUT(q->type)) { - ctx->state = AML_STATE_RESET; - aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_RESET)", - ctx->id, __func__); - queue_work(dev->reset_workqueue, &ctx->reset_work); + /* + * if receive the cmd is not V4L2_DEC_CMD_STOP + * that request should be seek not stop, thus igorn status + * AML_STATE_FLUSHING and AML_STATE_FLUSHED. + */ + + if (ctx->state == AML_STATE_FLUSHED || + ctx->state == AML_STATE_FLUSHING || //???? + (ctx->state == AML_STATE_ACTIVE && + !ctx->receive_cmd_stop)) { + if (!V4L2_TYPE_IS_OUTPUT(q->type)) { + /*the short source will be fasted into flushing state. + then switch to abort state that caused seek failed.*/ + if (ctx->state == AML_STATE_FLUSHING) + ctx->receive_cmd_stop = false; + + ctx->state = AML_STATE_RESET; + ctx->v4l_codec_ready = false; + + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_RESET)", + ctx->id, __func__); + aml_vdec_reset(ctx); + } } + mutex_unlock(&ctx->state_lock); } - mutex_unlock(&ctx->state_lock); - return ret; } @@ -813,27 +962,14 @@ static int vidioc_decoder_reqbufs(struct file *file, void *priv, return v4l2_m2m_ioctl_reqbufs(file, priv, rb); } -void aml_vdec_unlock(struct aml_vcodec_ctx *ctx) -{ - mutex_unlock(&ctx->dev->dec_mutex); -} - -void aml_vdec_lock(struct aml_vcodec_ctx *ctx) -{ - mutex_lock(&ctx->dev->dec_mutex); -} - void aml_vcodec_dec_release(struct aml_vcodec_ctx *ctx) { - aml_vdec_lock(ctx); - ctx->state = AML_STATE_ABORT; + ctx->v4l_codec_ready = false; aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", ctx->id, __func__); vdec_if_deinit(ctx); - - aml_vdec_unlock(ctx); } void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx) @@ -844,12 +980,11 @@ void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx) ctx->fh.m2m_ctx = ctx->m2m_ctx; ctx->fh.ctrl_handler = &ctx->ctrl_hdl; INIT_WORK(&ctx->decode_work, aml_vdec_worker); - INIT_WORK(&ctx->reset_work, aml_reset_worker); ctx->colorspace = V4L2_COLORSPACE_REC709; ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; ctx->quantization = V4L2_QUANTIZATION_DEFAULT; ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT; - ctx->dev->dec_capability = VCODEC_CAPABILITY_4K_DISABLED;//disable 4k + ctx->dev->dec_capability = 0;//VCODEC_CAPABILITY_4K_DISABLED;//disable 4k q_data = &ctx->q_data[AML_Q_DATA_SRC]; memset(q_data, 0, sizeof(struct aml_q_data)); @@ -951,7 +1086,7 @@ static int vidioc_try_fmt(struct v4l2_format *f, struct aml_video_fmt *fmt) if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { pix_fmt_mp->num_planes = 1; pix_fmt_mp->plane_fmt[0].bytesperline = 0; - } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + } else if (!V4L2_TYPE_IS_OUTPUT(f->type)) { int tmp_w, tmp_h; pix_fmt_mp->height = clamp(pix_fmt_mp->height, @@ -1133,7 +1268,7 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv, aml_v4l2_err("[%d] out_q_ctx buffers already requested", ctx->id); } - if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) && + if ((!V4L2_TYPE_IS_OUTPUT(f->type)) && vb2_is_busy(&ctx->m2m_ctx->cap_q_ctx.q)) { aml_v4l2_err("[%d] cap_q_ctx buffers already requested", ctx->id); } @@ -1144,7 +1279,7 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv, f->fmt.pix.pixelformat = aml_video_formats[OUT_FMT_IDX].fourcc; fmt = aml_vdec_find_format(f); - } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + } else if (!V4L2_TYPE_IS_OUTPUT(f->type)) { f->fmt.pix.pixelformat = aml_video_formats[CAP_FMT_IDX].fourcc; fmt = aml_vdec_find_format(f); @@ -1283,7 +1418,7 @@ static int vidioc_vdec_g_fmt(struct file *file, void *priv, pix_mp->quantization = ctx->quantization; pix_mp->xfer_func = ctx->xfer_func; - if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) && + if ((!V4L2_TYPE_IS_OUTPUT(f->type)) && (ctx->state >= AML_STATE_PROBE)) { /* Until STREAMOFF is called on the CAPTURE queue * (acknowledging the event), the driver operates as if @@ -1346,6 +1481,7 @@ static int vidioc_vdec_g_fmt(struct file *file, void *priv, aml_v4l2_debug(4, "[%d] type=%d state=%d Format information could not be read, not ready yet!", ctx->id, f->type, ctx->state); + return -EINVAL; } return 0; @@ -1444,21 +1580,18 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) * check if this buffer is ready to be used after decode */ if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { - aml_v4l2_debug(3, "[%d] %s() [%d], y_va: %p, vf_h: %lx, state: %d", ctx->id, - __func__, __LINE__, buf->frame_buffer.base_y.va, + aml_v4l2_debug(3, "[%d] %s() [%d], y_addr: %lx, vf_h: %lx, state: %d", ctx->id, + __func__, __LINE__, buf->frame_buffer.m.mem[0].addr, buf->frame_buffer.vf_handle, buf->frame_buffer.status); if (!buf->que_in_m2m && buf->frame_buffer.status == FB_ST_NORMAL) { - aml_v4l2_debug(3, "[%d] enque capture buf idx %d, %p\n", + aml_v4l2_debug(2, "[%d] enque capture buf idx %d, %p", ctx->id, vb->index, vb); v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2); buf->que_in_m2m = true; buf->queued_in_vb2 = true; buf->queued_in_v4l2 = true; buf->ready_to_display = false; - - /*save capture bufs to be used for resetting config.*/ - list_add(&buf->node, &ctx->capture_list); } else if (buf->frame_buffer.status == FB_ST_DISPLAY) { buf->queued_in_vb2 = false; buf->queued_in_v4l2 = true; @@ -1488,11 +1621,14 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) return; } - src_mem.va = vb2_plane_vaddr(vb, 0); + src_mem.vaddr = vb2_plane_vaddr(vb, 0); src_mem.dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0); - src_mem.size = (size_t)vb->planes[0].bytesused; - if (vdec_if_probe(ctx, &src_mem, NULL)) + src_mem.size = vb->planes[0].bytesused; + if (vdec_if_probe(ctx, &src_mem, NULL)) { + v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + v4l2_m2m_buf_done(to_vb2_v4l2_buffer(vb), VB2_BUF_STATE_DONE); return; + } if (vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, &ctx->picinfo)) { pr_err("[%d] GET_PARAM_PICTURE_INFO err\n", ctx->id); @@ -1504,6 +1640,9 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) return; } + if (!dpb) + return; + ctx->dpb_size = dpb; ctx->last_decoded_picinfo = ctx->picinfo; aml_vdec_queue_res_chg_event(ctx); @@ -1527,13 +1666,11 @@ static void vb2ops_vdec_buf_finish(struct vb2_buffer *vb) vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf); buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); - //mutex_lock(&ctx->lock); - if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { buf->queued_in_v4l2 = false; buf->queued_in_vb2 = false; } buf_error = buf->error; - //mutex_unlock(&ctx->lock); if (buf_error) { aml_v4l2_err("[%d] Unrecoverable error on buffer.", ctx->id); @@ -1556,7 +1693,7 @@ static int vb2ops_vdec_buf_init(struct vb2_buffer *vb) aml_v4l2_debug(4, "[%d] (%d) id=%d", ctx->id, vb->vb2_queue->type, vb->index); - if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { buf->used = false; buf->ready_to_display = false; buf->queued_in_v4l2 = false; @@ -1578,23 +1715,32 @@ static int vb2ops_vdec_buf_init(struct vb2_buffer *vb) aml_v4l2_debug(3, "[%d] IN alloc, addr: %x, size: %u, idx: %u", ctx->id, phy_addr, size, vb->index); } else { - size = vb->planes[0].length; - phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0); snprintf(owner, PATH_MAX, "%s-%d", "v4l-output", ctx->id); strncpy(buf->mem_onwer, owner, sizeof(buf->mem_onwer)); buf->mem_onwer[sizeof(buf->mem_onwer) - 1] = '\0'; - buf->mem[0] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, - phy_addr, size, vb->index); - aml_v4l2_debug(3, "[%d] OUT Y alloc, addr: %x, size: %u, idx: %u", - ctx->id, phy_addr, size, vb->index); - - size = vb->planes[1].length; - phy_addr = vb2_dma_contig_plane_dma_addr(vb, 1); - buf->mem[1] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, + if ((vb->memory == VB2_MEMORY_MMAP) && (vb->num_planes == 1)) { + size = vb->planes[0].length; + phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0); + buf->mem[0] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, phy_addr, size, vb->index); - aml_v4l2_debug(3, "[%d] OUT C alloc, addr: %x, size: %u, idx: %u", - ctx->id, phy_addr, size, vb->index); + aml_v4l2_debug(3, "[%d] OUT Y alloc, addr: %x, size: %u, idx: %u", + ctx->id, phy_addr, size, vb->index); + } else if ((vb->memory == VB2_MEMORY_MMAP) && (vb->num_planes == 2)) { + size = vb->planes[0].length; + phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0); + buf->mem[0] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, + phy_addr, size, vb->index); + aml_v4l2_debug(3, "[%d] OUT Y alloc, addr: %x, size: %u, idx: %u", + ctx->id, phy_addr, size, vb->index); + + size = vb->planes[1].length; + phy_addr = vb2_dma_contig_plane_dma_addr(vb, 1); + buf->mem[1] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, + phy_addr, size, vb->index); + aml_v4l2_debug(3, "[%d] OUT C alloc, addr: %x, size: %u, idx: %u", + ctx->id, phy_addr, size, vb->index); + } } __putname(owner); @@ -1624,15 +1770,17 @@ static void codec_mm_bufs_cnt_clean(struct vb2_queue *q) continue; } - v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[0]); - v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[1]); + if (q->memory == VB2_MEMORY_MMAP) { + v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[0]); + v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[1]); - aml_v4l2_debug(3, "[%d] OUT Y clean, addr: %lx, size: %u, idx: %u", - ctx->id, buf->mem[0]->phy_addr, buf->mem[0]->buffer_size, i); - aml_v4l2_debug(3, "[%d] OUT C clean, addr: %lx, size: %u, idx: %u", - ctx->id, buf->mem[1]->phy_addr, buf->mem[1]->buffer_size, i); - buf->mem[0] = NULL; - buf->mem[1] = NULL; + aml_v4l2_debug(3, "[%d] OUT Y clean, addr: %lx, size: %u, idx: %u", + ctx->id, buf->mem[0]->phy_addr, buf->mem[0]->buffer_size, i); + aml_v4l2_debug(3, "[%d] OUT C clean, addr: %lx, size: %u, idx: %u", + ctx->id, buf->mem[1]->phy_addr, buf->mem[1]->buffer_size, i); + buf->mem[0] = NULL; + buf->mem[1] = NULL; + } } } @@ -1659,26 +1807,23 @@ static void vb2ops_vdec_stop_streaming(struct vb2_queue *q) codec_mm_bufs_cnt_clean(q); if (V4L2_TYPE_IS_OUTPUT(q->type)) { - while (v4l2_m2m_src_buf_remove(ctx->m2m_ctx)); - return; - } + while ((vb2_v4l2 = v4l2_m2m_src_buf_remove(ctx->m2m_ctx))) + v4l2_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR); + } else { + while ((vb2_v4l2 = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx))) + v4l2_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR); - while (v4l2_m2m_dst_buf_remove(ctx->m2m_ctx)); + for (i = 0; i < q->num_buffers; ++i) { + vb2_v4l2 = to_vb2_v4l2_buffer(q->bufs[i]); + buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); + buf->frame_buffer.status = FB_ST_NORMAL; + buf->que_in_m2m = false; - for (i = 0; i < q->num_buffers; ++i) { - if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) { - q->bufs[i]->state = VB2_BUF_STATE_DEQUEUED; - atomic_dec(&q->owned_by_drv_count); + /*pr_info("idx: %d, state: %d\n", + q->bufs[i]->index, q->bufs[i]->state);*/ } - vb2_v4l2 = to_vb2_v4l2_buffer(q->bufs[i]); - buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); - buf->frame_buffer.status = FB_ST_NORMAL; - } - while (!list_empty(&ctx->capture_list)) { - buf = list_entry(ctx->capture_list.next, - struct aml_video_dec_buf, node); - list_del(&buf->node); + ctx->buf_used_count = 0; } } @@ -1738,6 +1883,7 @@ static int aml_vdec_g_v_ctrl(struct v4l2_ctrl *ctrl) } else { pr_err("Seqinfo not ready.\n"); ctrl->val = 0; + ret = -EINVAL; } break; default: @@ -1846,28 +1992,36 @@ static const struct vb2_ops aml_vdec_vb2_ops = { }; const struct v4l2_ioctl_ops aml_vdec_ioctl_ops = { - .vidioc_streamon = vidioc_decoder_streamon, - .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, - .vidioc_reqbufs = vidioc_decoder_reqbufs, - .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, - .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,//?? - //.vidioc_g_ctrl = vidioc_vdec_g_ctrl, + .vidioc_streamon = vidioc_decoder_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, + .vidioc_reqbufs = vidioc_decoder_reqbufs, + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,//?? + //.vidioc_g_ctrl = vidioc_vdec_g_ctrl, - .vidioc_qbuf = vidioc_vdec_qbuf, - .vidioc_dqbuf = vidioc_vdec_dqbuf, + .vidioc_qbuf = vidioc_vdec_qbuf, + .vidioc_dqbuf = vidioc_vdec_dqbuf, .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap_mplane, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap_mplane, .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_vid_out_mplane, + .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out_mplane, .vidioc_s_fmt_vid_cap_mplane = vidioc_vdec_s_fmt, + .vidioc_s_fmt_vid_cap = vidioc_vdec_s_fmt, .vidioc_s_fmt_vid_out_mplane = vidioc_vdec_s_fmt, + .vidioc_s_fmt_vid_out = vidioc_vdec_s_fmt, .vidioc_g_fmt_vid_cap_mplane = vidioc_vdec_g_fmt, + .vidioc_g_fmt_vid_cap = vidioc_vdec_g_fmt, .vidioc_g_fmt_vid_out_mplane = vidioc_vdec_g_fmt, + .vidioc_g_fmt_vid_out = vidioc_vdec_g_fmt, .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, .vidioc_enum_fmt_vid_cap_mplane = vidioc_vdec_enum_fmt_vid_cap_mplane, + .vidioc_enum_fmt_vid_cap = vidioc_vdec_enum_fmt_vid_cap_mplane, .vidioc_enum_fmt_vid_out_mplane = vidioc_vdec_enum_fmt_vid_out_mplane, + .vidioc_enum_fmt_vid_out = vidioc_vdec_enum_fmt_vid_out_mplane, .vidioc_enum_framesizes = vidioc_enum_framesizes, .vidioc_querycap = vidioc_vdec_querycap, @@ -1896,13 +2050,14 @@ int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq, src_vq->mem_ops = &vb2_dma_contig_memops; src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; src_vq->lock = &ctx->dev->dev_mutex; - ret = vb2_queue_init(src_vq); if (ret) { aml_v4l2_err("[%d] Failed to initialize videobuf2 queue(output)", ctx->id); return ret; } - dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + + dst_vq->type = multiplanar ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : + V4L2_BUF_TYPE_VIDEO_CAPTURE; dst_vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR; dst_vq->drv_priv = ctx; dst_vq->buf_struct_size = sizeof(struct aml_video_dec_buf); @@ -1910,7 +2065,6 @@ int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq, dst_vq->mem_ops = &vb2_dma_contig_memops; dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; dst_vq->lock = &ctx->dev->dev_mutex; - ret = vb2_queue_init(dst_vq); if (ret) { vb2_queue_release(src_vq); diff --git a/drivers/amvdec_ports/aml_vcodec_dec.h b/drivers/amvdec_ports/aml_vcodec_dec.h index f6a9db0..19923c0 100644 --- a/drivers/amvdec_ports/aml_vcodec_dec.h +++ b/drivers/amvdec_ports/aml_vcodec_dec.h @@ -34,21 +34,34 @@ #define AML_VDEC_IRQ_STATUS_DEC_SUCCESS 0x10000 #define V4L2_BUF_FLAG_LAST 0x00100000 +#define VDEC_GATHER_MEMORY_TYPE 0 +#define VDEC_SCATTER_MEMORY_TYPE 1 + #define AML_V4L2_SET_DECMODE (V4L2_CID_USER_AMLOGIC_BASE + 0) /** * struct vdec_fb - decoder frame buffer - * @base_y : Y plane memory info - * @base_c : C plane memory info + * @mem_type : gather or scatter memory. + * @num_planes : used number of the plane + * @mem[4] : array mem for used planes, + * mem[0]: Y, mem[1]: C/U, mem[2]: V + * @vf_fd : the file handle of video frame + * @vf_handle : video frame handle * @status : frame buffer status (vdec_fb_status) */ -struct vdec_fb { - unsigned long vf_handle; - struct aml_vcodec_mem base_y; - struct aml_vcodec_mem base_c; - unsigned int status; + +struct vdec_v4l2_buffer { + int mem_type; + int num_planes; + union { + struct aml_vcodec_mem mem[4]; + u32 vf_fd; + } m; + ulong vf_handle; + u32 status; }; + /** * struct aml_video_dec_buf - Private data related to each VB2 buffer. * @b: VB2 buffer @@ -69,10 +82,9 @@ struct aml_video_dec_buf { struct vb2_v4l2_buffer vb; struct list_head list; - struct vdec_fb frame_buffer; + struct vdec_v4l2_buffer frame_buffer; struct codec_mm_s *mem[2]; char mem_onwer[32]; - struct list_head node; bool used; bool ready_to_display; bool que_in_m2m; @@ -82,6 +94,14 @@ struct aml_video_dec_buf { bool error; }; +struct aml_vdec_pic_infos { + u32 visible_width; + u32 visible_height; + u32 coded_width; + u32 coded_height; + int dpb_size; +}; + extern const struct v4l2_ioctl_ops aml_vdec_ioctl_ops; extern const struct v4l2_m2m_ops aml_vdec_m2m_ops; @@ -108,5 +128,6 @@ void aml_thread_notify(struct aml_vcodec_ctx *ctx, int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func, enum aml_thread_type type, const char *thread_name); void aml_thread_stop(struct aml_vcodec_ctx *ctx); +void wait_vcodec_ending(struct aml_vcodec_ctx *ctx); #endif /* _AML_VCODEC_DEC_H_ */ diff --git a/drivers/amvdec_ports/aml_vcodec_dec_drv.c b/drivers/amvdec_ports/aml_vcodec_dec_drv.c index fbaabe1..a50f9b1 100644 --- a/drivers/amvdec_ports/aml_vcodec_dec_drv.c +++ b/drivers/amvdec_ports/aml_vcodec_dec_drv.c @@ -33,15 +33,17 @@ #include "aml_vcodec_drv.h" #include "aml_vcodec_dec.h" #include "aml_vcodec_dec_pm.h" -//#include "aml_vcodec_intr.h" #include "aml_vcodec_util.h" #include "aml_vcodec_vfm.h" -#define VDEC_HW_ACTIVE 0x10 -#define VDEC_IRQ_CFG 0x11 -#define VDEC_IRQ_CLR 0x10 +#define VDEC_HW_ACTIVE 0x10 +#define VDEC_IRQ_CFG 0x11 +#define VDEC_IRQ_CLR 0x10 #define VDEC_IRQ_CFG_REG 0xa4 +bool scatter_mem_enable; +bool param_sets_from_ucode; + static int fops_vcodec_open(struct file *file) { struct aml_vcodec_dev *dev = video_drvdata(file); @@ -73,7 +75,12 @@ static int fops_vcodec_open(struct file *file) init_waitqueue_head(&ctx->queue); mutex_init(&ctx->state_lock); mutex_init(&ctx->lock); + spin_lock_init(&ctx->slock); init_waitqueue_head(&ctx->wq); + init_completion(&ctx->comp); + + ctx->scatter_mem_enable = scatter_mem_enable ? 1 : 0; + ctx->param_sets_from_ucode = param_sets_from_ucode ? 1 : 0; ctx->type = AML_INST_DECODER; ret = aml_vcodec_dec_ctrls_setup(ctx); @@ -136,15 +143,15 @@ static int fops_vcodec_release(struct file *file) * Second, the decoder will be flushed and all the buffers will be * returned in stop_streaming. */ - aml_vcodec_dec_release(ctx); + aml_thread_stop(ctx); + wait_vcodec_ending(ctx); v4l2_m2m_ctx_release(ctx->m2m_ctx); + aml_vcodec_dec_release(ctx); v4l2_fh_del(&ctx->fh); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->ctrl_hdl); - aml_thread_stop(ctx); - list_del_init(&ctx->list); kfree(ctx->empty_flush_buf); kfree(ctx); @@ -227,16 +234,6 @@ static int aml_vcodec_probe(struct platform_device *pdev) goto err_event_workq; } - dev->reset_workqueue = - alloc_ordered_workqueue("aml-vcodec-reset", - WQ_MEM_RECLAIM | WQ_FREEZABLE); - if (!dev->reset_workqueue) { - aml_v4l2_err("Failed to create decode workqueue"); - ret = -EINVAL; - destroy_workqueue(dev->decode_workqueue); - goto err_event_workq; - } - //dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num); ret = video_register_device(vfd_dec, VFL_TYPE_GRABBER, 26); @@ -250,7 +247,6 @@ static int aml_vcodec_probe(struct platform_device *pdev) return 0; err_dec_reg: - destroy_workqueue(dev->reset_workqueue); destroy_workqueue(dev->decode_workqueue); err_event_workq: v4l2_m2m_release(dev->m2m_dev_dec); @@ -274,9 +270,6 @@ static int aml_vcodec_dec_remove(struct platform_device *pdev) { struct aml_vcodec_dev *dev = platform_get_drvdata(pdev); - flush_workqueue(dev->reset_workqueue); - destroy_workqueue(dev->reset_workqueue); - flush_workqueue(dev->decode_workqueue); destroy_workqueue(dev->decode_workqueue); @@ -343,20 +336,34 @@ module_param(aml_vcodec_dbg, bool, 0644); bool aml_set_vfm_enable; EXPORT_SYMBOL(aml_set_vfm_enable); +module_param(aml_set_vfm_enable, bool, 0644); int aml_set_vfm_path; EXPORT_SYMBOL(aml_set_vfm_path); +module_param(aml_set_vfm_path, int, 0644); bool aml_set_vdec_type_enable; EXPORT_SYMBOL(aml_set_vdec_type_enable); +module_param(aml_set_vdec_type_enable, bool, 0644); int aml_set_vdec_type; EXPORT_SYMBOL(aml_set_vdec_type); - -module_param(aml_set_vdec_type_enable, bool, 0644); module_param(aml_set_vdec_type, int, 0644); -module_param(aml_set_vfm_enable, bool, 0644); -module_param(aml_set_vfm_path, int, 0644); + +int vp9_need_prefix; +EXPORT_SYMBOL(vp9_need_prefix); +module_param(vp9_need_prefix, int, 0644); + +bool multiplanar; +EXPORT_SYMBOL(multiplanar); +module_param(multiplanar, bool, 0644); + +EXPORT_SYMBOL(scatter_mem_enable); +module_param(scatter_mem_enable, bool, 0644); + +EXPORT_SYMBOL(param_sets_from_ucode); +module_param(param_sets_from_ucode, bool, 0644); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("AML video codec V4L2 decoder driver"); + diff --git a/drivers/amvdec_ports/aml_vcodec_drv.h b/drivers/amvdec_ports/aml_vcodec_drv.h index cd46964..a7c9aaf 100644 --- a/drivers/amvdec_ports/aml_vcodec_drv.h +++ b/drivers/amvdec_ports/aml_vcodec_drv.h @@ -323,7 +323,6 @@ struct aml_vcodec_ctx { struct v4l2_ctrl_handler ctrl_hdl; struct work_struct decode_work; struct work_struct encode_work; - struct work_struct reset_work; struct vdec_pic_info last_decoded_picinfo; struct aml_video_dec_buf *empty_flush_buf; @@ -334,12 +333,19 @@ struct aml_vcodec_ctx { int decoded_frame_cnt; struct mutex lock; - wait_queue_head_t wq; + struct completion comp; bool has_receive_eos; struct list_head capture_list; struct list_head vdec_thread_list; bool is_drm_mode; bool is_stream_mode; + int buf_used_count; + bool receive_cmd_stop; + bool scatter_mem_enable; + bool param_sets_from_ucode; + bool v4l_codec_ready; + wait_queue_head_t wq; + spinlock_t slock; }; /** @@ -400,7 +406,6 @@ struct aml_vcodec_dev { struct workqueue_struct *decode_workqueue; struct workqueue_struct *encode_workqueue; - struct workqueue_struct *reset_workqueue; int int_cond; int int_type; struct mutex dev_mutex; diff --git a/drivers/amvdec_ports/aml_vcodec_util.c b/drivers/amvdec_ports/aml_vcodec_util.c index 0026c6a..73a4b74 100644 --- a/drivers/amvdec_ports/aml_vcodec_util.c +++ b/drivers/amvdec_ports/aml_vcodec_util.c @@ -53,18 +53,18 @@ int aml_vcodec_mem_alloc(struct aml_vcodec_ctx *data, struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)data; struct device *dev = &ctx->dev->plat_dev->dev; - //mem->va = dma_alloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL); - mem->va = codec_mm_dma_alloc_coherent(dev_name(dev), size, + //mem->vaddr = dma_alloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL); + mem->vaddr = codec_mm_dma_alloc_coherent(dev_name(dev), size, &mem->dma_addr, GFP_KERNEL, 0); - if (!mem->va) { + if (!mem->vaddr) { aml_v4l2_err("%s dma_alloc size=%ld failed!", dev_name(dev), size); return -ENOMEM; } - memset(mem->va, 0, size); + memset(mem->vaddr, 0, size); - aml_v4l2_debug(4, "[%d] - va = %p", ctx->id, mem->va); + aml_v4l2_debug(4, "[%d] - va = %p", ctx->id, mem->vaddr); aml_v4l2_debug(4, "[%d] - dma = 0x%lx", ctx->id, (unsigned long)mem->dma_addr); aml_v4l2_debug(4, "[%d] size = 0x%lx", ctx->id, size); @@ -80,19 +80,19 @@ void aml_vcodec_mem_free(struct aml_vcodec_ctx *data, struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)data; struct device *dev = &ctx->dev->plat_dev->dev; - if (!mem->va) { + if (!mem->vaddr) { aml_v4l2_err("%s dma_free size=%ld failed!", dev_name(dev), size); return; } - aml_v4l2_debug(4, "[%d] - va = %p", ctx->id, mem->va); + aml_v4l2_debug(4, "[%d] - va = %p", ctx->id, mem->vaddr); aml_v4l2_debug(4, "[%d] - dma = 0x%lx", ctx->id, (unsigned long)mem->dma_addr); aml_v4l2_debug(4, "[%d] size = 0x%lx", ctx->id, size); - dma_free_coherent(dev, size, mem->va, mem->dma_addr); - mem->va = NULL; + dma_free_coherent(dev, size, mem->vaddr, mem->dma_addr); + mem->vaddr = NULL; mem->dma_addr = 0; mem->size = 0; } diff --git a/drivers/amvdec_ports/aml_vcodec_util.h b/drivers/amvdec_ports/aml_vcodec_util.h index 6192caa..e93900e 100644 --- a/drivers/amvdec_ports/aml_vcodec_util.h +++ b/drivers/amvdec_ports/aml_vcodec_util.h @@ -37,10 +37,12 @@ typedef unsigned char u8; (((u8)(a) << 24) | ((u8)(b) << 16) | ((u8)(c) << 8) | (u8)(d)) struct aml_vcodec_mem { - size_t size; - void *va; + ulong addr; + u32 size; + void *vaddr; + u32 bytes_used; + u32 offset; dma_addr_t dma_addr; - unsigned int bytes_used; }; struct aml_vcodec_ctx; diff --git a/drivers/amvdec_ports/aml_vcodec_vfm.c b/drivers/amvdec_ports/aml_vcodec_vfm.c index 36c1820..e7b85fb 100644 --- a/drivers/amvdec_ports/aml_vcodec_vfm.c +++ b/drivers/amvdec_ports/aml_vcodec_vfm.c @@ -87,14 +87,19 @@ static int vdec_vf_states(struct vframe_states *states, void *op_arg) return 0; } -void video_vf_put(char *receiver, struct vdec_fb *fb, int id) +void video_vf_put(char *receiver, struct vdec_v4l2_buffer *fb, int id) { struct vframe_provider_s *vfp = vf_get_provider(receiver); struct vframe_s *vf = (struct vframe_s *)fb->vf_handle; - aml_v4l2_debug(2, "[%d] TO (%s) vf: %p, idx: %d", + aml_v4l2_debug(3, "[%d] TO (%s) vf: %p, idx: %d", id, vfp->name, vf, vf->index); + aml_v4l2_debug(4, "[%d] TO Y:(%lx, %u) C/U:(%lx, %u) V:(%lx, %u)", + id, fb->m.mem[0].addr, fb->m.mem[0].size, + fb->m.mem[1].addr, fb->m.mem[1].size, + fb->m.mem[2].addr, fb->m.mem[2].size); + if (vfp && vf && atomic_dec_and_test(&vf->use_cnt)) vf_put(vf, receiver); } diff --git a/drivers/amvdec_ports/aml_vcodec_vfm.h b/drivers/amvdec_ports/aml_vcodec_vfm.h index 02358f6..9aaf266 100644 --- a/drivers/amvdec_ports/aml_vcodec_vfm.h +++ b/drivers/amvdec_ports/aml_vcodec_vfm.h @@ -51,9 +51,9 @@ struct vframe_s *peek_video_frame(struct vcodec_vfm_s *vfm); struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm); -int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb **out_fb); -int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb *in_fb); +int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_fb); +int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *in_fb); -void video_vf_put(char *receiver, struct vdec_fb *fb, int id); +void video_vf_put(char *receiver, struct vdec_v4l2_buffer *fb, int id); #endif /* __AML_VCODEC_VFM_H_ */ diff --git a/drivers/amvdec_ports/decoder/aml_h264_parser.c b/drivers/amvdec_ports/decoder/aml_h264_parser.c new file mode 100644 index 0000000..cf4e0e8 --- a/dev/null +++ b/drivers/amvdec_ports/decoder/aml_h264_parser.c @@ -0,0 +1,662 @@ +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/vmalloc.h> +#include <linux/mm.h> +#include <linux/string.h> + +#include "aml_h264_parser.h" +#include "../utils/get_bits.h" +#include "../utils/put_bits.h" +#include "../utils/golomb.h" +#include "../utils/common.h" +#include "utils.h" + +#define MAX_DELAYED_PIC_COUNT (16) +#define MAX_LOG2_MAX_FRAME_NUM (12 + 4) +#define MIN_LOG2_MAX_FRAME_NUM (4) +#define MAX_SPS_COUNT (32) +#define EXTENDED_SAR (255) + +static const struct rational h264_pixel_aspect[17] = { + { 0, 1 }, + { 1, 1 }, + { 12, 11 }, + { 10, 11 }, + { 16, 11 }, + { 40, 33 }, + { 24, 11 }, + { 20, 11 }, + { 32, 11 }, + { 80, 33 }, + { 18, 11 }, + { 15, 11 }, + { 64, 33 }, + { 160, 99 }, + { 4, 3 }, + { 3, 2 }, + { 2, 1 }, +}; + +/* maximum number of MBs in the DPB for a given level */ +static const int level_max_dpb_mbs[][2] = { + { 10, 396 }, + { 11, 900 }, + { 12, 2376 }, + { 13, 2376 }, + { 20, 2376 }, + { 21, 4752 }, + { 22, 8100 }, + { 30, 8100 }, + { 31, 18000 }, + { 32, 20480 }, + { 40, 32768 }, + { 41, 32768 }, + { 42, 34816 }, + { 50, 110400 }, + { 51, 184320 }, + { 52, 184320 }, +}; + +static const u8 default_scaling4[2][16] = { + { 6, 13, 20, 28, 13, 20, 28, 32, + 20, 28, 32, 37, 28, 32, 37, 42}, + { 10, 14, 20, 24, 14, 20, 24, 27, + 20, 24, 27, 30, 24, 27, 30, 34 } +}; + +static const u8 default_scaling8[2][64] = { + { 6, 10, 13, 16, 18, 23, 25, 27, + 10, 11, 16, 18, 23, 25, 27, 29, + 13, 16, 18, 23, 25, 27, 29, 31, + 16, 18, 23, 25, 27, 29, 31, 33, + 18, 23, 25, 27, 29, 31, 33, 36, + 23, 25, 27, 29, 31, 33, 36, 38, + 25, 27, 29, 31, 33, 36, 38, 40, + 27, 29, 31, 33, 36, 38, 40, 42 }, + { 9, 13, 15, 17, 19, 21, 22, 24, + 13, 13, 17, 19, 21, 22, 24, 25, + 15, 17, 19, 21, 22, 24, 25, 27, + 17, 19, 21, 22, 24, 25, 27, 28, + 19, 21, 22, 24, 25, 27, 28, 30, + 21, 22, 24, 25, 27, 28, 30, 32, + 22, 24, 25, 27, 28, 30, 32, 33, + 24, 25, 27, 28, 30, 32, 33, 35 } +}; + +extern const u8 ff_zigzag_scan[16 + 1]; +extern const u8 ff_zigzag_direct[64]; + +static int decode_scaling_list(struct get_bits_context *gb, + u8 *factors, int size, + const u8 *jvt_list, + const u8 *fallback_list) +{ + int i, last = 8, next = 8; + const u8 *scan = size == 16 ? ff_zigzag_scan : ff_zigzag_direct; + + if (!get_bits1(gb)) /* matrix not written, we use the predicted one */ + memcpy(factors, fallback_list, size * sizeof(u8)); + else + for (i = 0; i < size; i++) { + if (next) { + int v = get_se_golomb(gb); + if (v < -128 || v > 127) { + pr_err( "delta scale %d is invalid\n", v); + return -1; + } + next = (last + v) & 0xff; + } + if (!i && !next) { /* matrix not written, we use the preset one */ + memcpy(factors, jvt_list, size * sizeof(u8)); + break; + } + last = factors[scan[i]] = next ? next : last; + } + return 0; +} + +/* returns non zero if the provided SPS scaling matrix has been filled */ +static int decode_scaling_matrices(struct get_bits_context *gb, + const struct h264_SPS_t *sps, + const struct h264_PPS_t *pps, int is_sps, + u8(*scaling_matrix4)[16], + u8(*scaling_matrix8)[64]) +{ + int ret = 0; + int fallback_sps = !is_sps && sps->scaling_matrix_present; + const u8 *fallback[4] = { + fallback_sps ? sps->scaling_matrix4[0] : default_scaling4[0], + fallback_sps ? sps->scaling_matrix4[3] : default_scaling4[1], + fallback_sps ? sps->scaling_matrix8[0] : default_scaling8[0], + fallback_sps ? sps->scaling_matrix8[3] : default_scaling8[1] + }; + + if (get_bits1(gb)) { + ret |= decode_scaling_list(gb, scaling_matrix4[0], 16, default_scaling4[0], fallback[0]); // Intra, Y + ret |= decode_scaling_list(gb, scaling_matrix4[1], 16, default_scaling4[0], scaling_matrix4[0]); // Intra, Cr + ret |= decode_scaling_list(gb, scaling_matrix4[2], 16, default_scaling4[0], scaling_matrix4[1]); // Intra, Cb + ret |= decode_scaling_list(gb, scaling_matrix4[3], 16, default_scaling4[1], fallback[1]); // Inter, Y + ret |= decode_scaling_list(gb, scaling_matrix4[4], 16, default_scaling4[1], scaling_matrix4[3]); // Inter, Cr + ret |= decode_scaling_list(gb, scaling_matrix4[5], 16, default_scaling4[1], scaling_matrix4[4]); // Inter, Cb + if (is_sps || pps->transform_8x8_mode) { + ret |= decode_scaling_list(gb, scaling_matrix8[0], 64, default_scaling8[0], fallback[2]); // Intra, Y + ret |= decode_scaling_list(gb, scaling_matrix8[3], 64, default_scaling8[1], fallback[3]); // Inter, Y + if (sps->chroma_format_idc == 3) { + ret |= decode_scaling_list(gb, scaling_matrix8[1], 64, default_scaling8[0], scaling_matrix8[0]); // Intra, Cr + ret |= decode_scaling_list(gb, scaling_matrix8[4], 64, default_scaling8[1], scaling_matrix8[3]); // Inter, Cr + ret |= decode_scaling_list(gb, scaling_matrix8[2], 64, default_scaling8[0], scaling_matrix8[1]); // Intra, Cb + ret |= decode_scaling_list(gb, scaling_matrix8[5], 64, default_scaling8[1], scaling_matrix8[4]); // Inter, Cb + } + } + if (!ret) + ret = is_sps; + } + + return ret; +} + +static int decode_hrd_parameters(struct get_bits_context *gb, + struct h264_SPS_t *sps) +{ + int cpb_count, i; + + cpb_count = get_ue_golomb_31(gb) + 1; + if (cpb_count > 32U) { + pr_err("cpb_count %d invalid\n", cpb_count); + return -1; + } + + get_bits(gb, 4); /* bit_rate_scale */ + get_bits(gb, 4); /* cpb_size_scale */ + for (i = 0; i < cpb_count; i++) { + get_ue_golomb_long(gb); /* bit_rate_value_minus1 */ + get_ue_golomb_long(gb); /* cpb_size_value_minus1 */ + get_bits1(gb); /* cbr_flag */ + } + + sps->initial_cpb_removal_delay_length = get_bits(gb, 5) + 1; + sps->cpb_removal_delay_length = get_bits(gb, 5) + 1; + sps->dpb_output_delay_length = get_bits(gb, 5) + 1; + sps->time_offset_length = get_bits(gb, 5); + sps->cpb_cnt = cpb_count; + + return 0; +} + +static int decode_vui_parameters(struct get_bits_context *gb, struct h264_SPS_t *sps) +{ + int aspect_ratio_info_present_flag; + u32 aspect_ratio_idc; + + aspect_ratio_info_present_flag = get_bits1(gb); + + if (aspect_ratio_info_present_flag) { + aspect_ratio_idc = get_bits(gb, 8); + if (aspect_ratio_idc == EXTENDED_SAR) { + sps->sar.num = get_bits(gb, 16); + sps->sar.den = get_bits(gb, 16); + } else if (aspect_ratio_idc < ARRAY_SIZE(h264_pixel_aspect)) { + sps->sar = h264_pixel_aspect[aspect_ratio_idc]; + } else { + return -1; + } + } else { + sps->sar.num = + sps->sar.den = 0; + } + + if (get_bits1(gb)) /* overscan_info_present_flag */ + get_bits1(gb); /* overscan_appropriate_flag */ + + sps->video_signal_type_present_flag = get_bits1(gb); + if (sps->video_signal_type_present_flag) { + get_bits(gb, 3); /* video_format */ + sps->full_range = get_bits1(gb); /* video_full_range_flag */ + + sps->colour_description_present_flag = get_bits1(gb); + if (sps->colour_description_present_flag) { + sps->color_primaries = get_bits(gb, 8); /* colour_primaries */ + sps->color_trc = get_bits(gb, 8); /* transfer_characteristics */ + sps->colorspace = get_bits(gb, 8); /* matrix_coefficients */ + + // Set invalid values to "unspecified" + if (!av_color_primaries_name(sps->color_primaries)) + sps->color_primaries = AVCOL_PRI_UNSPECIFIED; + if (!av_color_transfer_name(sps->color_trc)) + sps->color_trc = AVCOL_TRC_UNSPECIFIED; + if (!av_color_space_name(sps->colorspace)) + sps->colorspace = AVCOL_SPC_UNSPECIFIED; + } + } + + /* chroma_location_info_present_flag */ + if (get_bits1(gb)) { + /* chroma_sample_location_type_top_field */ + //avctx->chroma_sample_location = get_ue_golomb(gb) + 1; + get_ue_golomb(gb); /* chroma_sample_location_type_bottom_field */ + } + + if (show_bits1(gb) && get_bits_left(gb) < 10) { + pr_info("Truncated VUI\n"); + return 0; + } + + sps->timing_info_present_flag = get_bits1(gb); + if (sps->timing_info_present_flag) { + unsigned num_units_in_tick = get_bits_long(gb, 32); + unsigned time_scale = get_bits_long(gb, 32); + if (!num_units_in_tick || !time_scale) { + pr_info("time_scale/num_units_in_tick invalid or unsupported (%u/%u)\n", + time_scale, num_units_in_tick); + sps->timing_info_present_flag = 0; + } else { + sps->num_units_in_tick = num_units_in_tick; + sps->time_scale = time_scale; + } + sps->fixed_frame_rate_flag = get_bits1(gb); + } + + sps->nal_hrd_parameters_present_flag = get_bits1(gb); + if (sps->nal_hrd_parameters_present_flag) + if (decode_hrd_parameters(gb, sps) < 0) + return -1; + sps->vcl_hrd_parameters_present_flag = get_bits1(gb); + if (sps->vcl_hrd_parameters_present_flag) + if (decode_hrd_parameters(gb, sps) < 0) + return -1; + if (sps->nal_hrd_parameters_present_flag || + sps->vcl_hrd_parameters_present_flag) + get_bits1(gb); /* low_delay_hrd_flag */ + sps->pic_struct_present_flag = get_bits1(gb); + if (!get_bits_left(gb)) + return 0; + sps->bitstream_restriction_flag = get_bits1(gb); + if (sps->bitstream_restriction_flag) { + get_bits1(gb); /* motion_vectors_over_pic_boundaries_flag */ + get_ue_golomb(gb); /* max_bytes_per_pic_denom */ + get_ue_golomb(gb); /* max_bits_per_mb_denom */ + get_ue_golomb(gb); /* log2_max_mv_length_horizontal */ + get_ue_golomb(gb); /* log2_max_mv_length_vertical */ + sps->num_reorder_frames = get_ue_golomb(gb); + sps->max_dec_frame_buffering = get_ue_golomb(gb); /*max_dec_frame_buffering*/ + + if (get_bits_left(gb) < 0) { + sps->num_reorder_frames = 0; + sps->bitstream_restriction_flag = 0; + } + + if (sps->num_reorder_frames > 16U + /* max_dec_frame_buffering || max_dec_frame_buffering > 16 */) { + pr_info("Clipping illegal num_reorder_frames %d\n", + sps->num_reorder_frames); + sps->num_reorder_frames = 16; + return -1; + } + } + + return 0; +} + +static int aml_h264_parser_sps(struct get_bits_context *gb, struct h264_SPS_t *sps) +{ + int ret; + u32 sps_id; + int profile_idc, level_idc, constraint_set_flags = 0; + int i, log2_max_frame_num_minus4; + + profile_idc = get_bits(gb, 8); + constraint_set_flags |= get_bits1(gb) << 0; // constraint_set0_flag + constraint_set_flags |= get_bits1(gb) << 1; // constraint_set1_flag + constraint_set_flags |= get_bits1(gb) << 2; // constraint_set2_flag + constraint_set_flags |= get_bits1(gb) << 3; // constraint_set3_flag + constraint_set_flags |= get_bits1(gb) << 4; // constraint_set4_flag + constraint_set_flags |= get_bits1(gb) << 5; // constraint_set5_flag + skip_bits(gb, 2); // reserved_zero_2bits + level_idc = get_bits(gb, 8); + sps_id = get_ue_golomb_31(gb); + + if (sps_id >= MAX_SPS_COUNT) { + pr_info( "sps_id %u out of range\n", sps_id); + goto fail; + } + + sps->sps_id = sps_id; + sps->time_offset_length = 24; + sps->profile_idc = profile_idc; + sps->constraint_set_flags = constraint_set_flags; + sps->level_idc = level_idc; + sps->full_range = -1; + + memset(sps->scaling_matrix4, 16, sizeof(sps->scaling_matrix4)); + memset(sps->scaling_matrix8, 16, sizeof(sps->scaling_matrix8)); + sps->scaling_matrix_present = 0; + sps->colorspace = 2; //AVCOL_SPC_UNSPECIFIED + + if (sps->profile_idc == 100 || // High profile + sps->profile_idc == 110 || // High10 profile + sps->profile_idc == 122 || // High422 profile + sps->profile_idc == 244 || // High444 Predictive profile + sps->profile_idc == 44 || // Cavlc444 profile + sps->profile_idc == 83 || // Scalable Constrained High profile (SVC) + sps->profile_idc == 86 || // Scalable High Intra profile (SVC) + sps->profile_idc == 118 || // Stereo High profile (MVC) + sps->profile_idc == 128 || // Multiview High profile (MVC) + sps->profile_idc == 138 || // Multiview Depth High profile (MVCD) + sps->profile_idc == 144) { // old High444 profile + sps->chroma_format_idc = get_ue_golomb_31(gb); + + if (sps->chroma_format_idc > 3U) { + pr_err("chroma_format_idc %u\n", sps->chroma_format_idc); + goto fail; + } else if (sps->chroma_format_idc == 3) { + sps->residual_color_transform_flag = get_bits1(gb); + if (sps->residual_color_transform_flag) { + pr_info( "separate color planes are not supported\n"); + goto fail; + } + } + + sps->bit_depth_luma = get_ue_golomb(gb) + 8; + sps->bit_depth_chroma = get_ue_golomb(gb) + 8; + if (sps->bit_depth_chroma != sps->bit_depth_luma) { + pr_err("Different chroma and luma bit depth\n"); + goto fail; + } + + if (sps->bit_depth_luma < 8 || sps->bit_depth_luma > 14 || + sps->bit_depth_chroma < 8 || sps->bit_depth_chroma > 14) { + pr_info("illegal bit depth value (%d, %d)\n", + sps->bit_depth_luma, sps->bit_depth_chroma); + goto fail; + } + + sps->transform_bypass = get_bits1(gb); + ret = decode_scaling_matrices(gb, sps, NULL, 1, + sps->scaling_matrix4, sps->scaling_matrix8); + if (ret < 0) + goto fail; + sps->scaling_matrix_present |= ret; + } else { + sps->chroma_format_idc = 1; + sps->bit_depth_luma = 8; + sps->bit_depth_chroma = 8; + } + + log2_max_frame_num_minus4 = get_ue_golomb(gb); + if (log2_max_frame_num_minus4 < MIN_LOG2_MAX_FRAME_NUM - 4 || + log2_max_frame_num_minus4 > MAX_LOG2_MAX_FRAME_NUM - 4) { + pr_info( + "log2_max_frame_num_minus4 out of range (0-12): %d\n", + log2_max_frame_num_minus4); + goto fail; + } + sps->log2_max_frame_num = log2_max_frame_num_minus4 + 4; + + sps->poc_type = get_ue_golomb_31(gb); + if (sps->poc_type == 0) { // FIXME #define + u32 t = get_ue_golomb(gb); + if (t > 12) { + pr_info( "log2_max_poc_lsb (%d) is out of range\n", t); + goto fail; + } + sps->log2_max_poc_lsb = t + 4; + } else if (sps->poc_type == 1) { // FIXME #define + sps->delta_pic_order_always_zero_flag = get_bits1(gb); + sps->offset_for_non_ref_pic = get_se_golomb_long(gb); + sps->offset_for_top_to_bottom_field = get_se_golomb_long(gb); + + sps->poc_cycle_length = get_ue_golomb(gb); + if ((u32)sps->poc_cycle_length >= ARRAY_SIZE(sps->offset_for_ref_frame)) { + pr_info("poc_cycle_length overflow %d\n", sps->poc_cycle_length); + goto fail; + } + + for (i = 0; i < sps->poc_cycle_length; i++) + sps->offset_for_ref_frame[i] = get_se_golomb_long(gb); + } else if (sps->poc_type != 2) { + pr_info( "illegal POC type %d\n", sps->poc_type); + goto fail; + } + + sps->ref_frame_count = get_ue_golomb_31(gb); + if (sps->ref_frame_count > MAX_DELAYED_PIC_COUNT) { + pr_info("too many reference frames %d\n", sps->ref_frame_count); + goto fail; + } + sps->gaps_in_frame_num_allowed_flag = get_bits1(gb); + sps->mb_width = get_ue_golomb(gb) + 1; + sps->mb_height = get_ue_golomb(gb) + 1; + + sps->frame_mbs_only_flag = get_bits1(gb); + + if (sps->mb_height >= INT_MAX / 2U) { + pr_info("height overflow\n"); + goto fail; + } + sps->mb_height *= 2 - sps->frame_mbs_only_flag; + + if (!sps->frame_mbs_only_flag) + sps->mb_aff = get_bits1(gb); + else + sps->mb_aff = 0; + + if ((u32)sps->mb_width >= INT_MAX / 16 || + (u32)sps->mb_height >= INT_MAX / 16) { + pr_info( "mb_width/height overflow\n"); + goto fail; + } + + sps->direct_8x8_inference_flag = get_bits1(gb); + + sps->crop = get_bits1(gb); + if (sps->crop) { + u32 crop_left = get_ue_golomb(gb); + u32 crop_right = get_ue_golomb(gb); + u32 crop_top = get_ue_golomb(gb); + u32 crop_bottom = get_ue_golomb(gb); + int width = 16 * sps->mb_width; + int height = 16 * sps->mb_height; + int vsub = (sps->chroma_format_idc == 1) ? 1 : 0; + int hsub = (sps->chroma_format_idc == 1 || sps->chroma_format_idc == 2) ? 1 : 0; + int step_x = 1 << hsub; + int step_y = (2 - sps->frame_mbs_only_flag) << vsub; + + if (crop_left > (u32)INT_MAX / 4 / step_x || + crop_right > (u32)INT_MAX / 4 / step_x || + crop_top > (u32)INT_MAX / 4 / step_y || + crop_bottom > (u32)INT_MAX / 4 / step_y || + (crop_left + crop_right ) * step_x >= width || + (crop_top + crop_bottom) * step_y >= height) { + pr_info( "crop values invalid %u %u %u %u / %d %d\n", crop_left, crop_right, crop_top, crop_bottom, width, height); + goto fail; + } + + sps->crop_left = crop_left * step_x; + sps->crop_right = crop_right * step_x; + sps->crop_top = crop_top * step_y; + sps->crop_bottom = crop_bottom * step_y; + } else { + sps->crop_left = + sps->crop_right = + sps->crop_top = + sps->crop_bottom = + sps->crop = 0; + } + + sps->vui_parameters_present_flag = get_bits1(gb); + if (sps->vui_parameters_present_flag) { + int ret = decode_vui_parameters(gb, sps); + if (ret < 0) + goto fail; + } + + if (get_bits_left(gb) < 0) { + pr_info("Overread %s by %d bits\n", sps->vui_parameters_present_flag ? "VUI" : "SPS", -get_bits_left(gb)); + goto out; + } + + /* if the maximum delay is not stored in the SPS, derive it based on the level */ + if (!sps->bitstream_restriction_flag && sps->ref_frame_count) { + sps->num_reorder_frames = MAX_DELAYED_PIC_COUNT - 1; + for (i = 0; i < ARRAY_SIZE(level_max_dpb_mbs); i++) { + if (level_max_dpb_mbs[i][0] == sps->level_idc) { + sps->num_reorder_frames = + MIN(level_max_dpb_mbs[i][1] / (sps->mb_width * sps->mb_height), + sps->num_reorder_frames); + break; + } + } + } + + if (!sps->sar.den) + sps->sar.den = 1; +out: + if (1) { + static const char csp[4][5] = { "Gray", "420", "422", "444" }; + pr_info("sps:%u profile:%d/%d poc:%d ref:%d %dx%d %s %s crop:%u/%u/%u/%u %s %s %d/%d b%d reo:%d\n", + sps_id, sps->profile_idc, sps->level_idc, + sps->poc_type, + sps->ref_frame_count, + sps->mb_width, sps->mb_height, + sps->frame_mbs_only_flag ? "FRM" : (sps->mb_aff ? "MB-AFF" : "PIC-AFF"), + sps->direct_8x8_inference_flag ? "8B8" : "", + sps->crop_left, sps->crop_right, + sps->crop_top, sps->crop_bottom, + sps->vui_parameters_present_flag ? "VUI" : "", + csp[sps->chroma_format_idc], + sps->timing_info_present_flag ? sps->num_units_in_tick : 0, + sps->timing_info_present_flag ? sps->time_scale : 0, + sps->bit_depth_luma, + sps->bitstream_restriction_flag ? sps->num_reorder_frames : -1); + } + + return 0; + +fail: + return -1; +} + +static const char *h264_nal_type_name[32] = { + "Unspecified 0", //H264_NAL_UNSPECIFIED + "Coded slice of a non-IDR picture", // H264_NAL_SLICE + "Coded slice data partition A", // H264_NAL_DPA + "Coded slice data partition B", // H264_NAL_DPB + "Coded slice data partition C", // H264_NAL_DPC + "IDR", // H264_NAL_IDR_SLICE + "SEI", // H264_NAL_SEI + "SPS", // H264_NAL_SPS + "PPS", // H264_NAL_PPS + "AUD", // H264_NAL_AUD + "End of sequence", // H264_NAL_END_SEQUENCE + "End of stream", // H264_NAL_END_STREAM + "Filler data", // H264_NAL_FILLER_DATA + "SPS extension", // H264_NAL_SPS_EXT + "Prefix", // H264_NAL_PREFIX + "Subset SPS", // H264_NAL_SUB_SPS + "Depth parameter set", // H264_NAL_DPS + "Reserved 17", // H264_NAL_RESERVED17 + "Reserved 18", // H264_NAL_RESERVED18 + "Auxiliary coded picture without partitioning", // H264_NAL_AUXILIARY_SLICE + "Slice extension", // H264_NAL_EXTEN_SLICE + "Slice extension for a depth view or a 3D-AVC texture view", // H264_NAL_DEPTH_EXTEN_SLICE + "Reserved 22", // H264_NAL_RESERVED22 + "Reserved 23", // H264_NAL_RESERVED23 + "Unspecified 24", // H264_NAL_UNSPECIFIED24 + "Unspecified 25", // H264_NAL_UNSPECIFIED25 + "Unspecified 26", // H264_NAL_UNSPECIFIED26 + "Unspecified 27", // H264_NAL_UNSPECIFIED27 + "Unspecified 28", // H264_NAL_UNSPECIFIED28 + "Unspecified 29", // H264_NAL_UNSPECIFIED29 + "Unspecified 30", // H264_NAL_UNSPECIFIED30 + "Unspecified 31", // H264_NAL_UNSPECIFIED31 +}; + +static const char *h264_nal_unit_name(int nal_type) +{ + return h264_nal_type_name[nal_type]; +} + +static int decode_extradata_ps(u8 *data, int size, struct h264_param_sets *ps) +{ + int ret = 0; + struct get_bits_context gb; + u32 src_len, rbsp_size = 0; + u8 *rbsp_buf = NULL; + int ref_idc, nalu_pos; + u32 nal_type; + u8 *p = data; + u32 len = size; + + nalu_pos = find_start_code(p, len); + if (nalu_pos < 0) + return -1; + + src_len = calc_nal_len(p + nalu_pos, size - nalu_pos); + rbsp_buf = nal_unit_extract_rbsp(p + nalu_pos, src_len, &rbsp_size); + if (rbsp_buf == NULL) + return -ENOMEM; + + ret = init_get_bits8(&gb, rbsp_buf, rbsp_size); + if (ret < 0) + goto out; + + if (get_bits1(&gb) != 0) { + pr_err("invalid h264 data,return!\n"); + goto out; + } + + ref_idc = get_bits(&gb, 2); + nal_type = get_bits(&gb, 5); + + pr_info("nal_unit_type: %d(%s), nal_ref_idc: %d\n", + nal_type, h264_nal_unit_name(nal_type), ref_idc); + + switch (nal_type) { + case H264_NAL_SPS: + ret = aml_h264_parser_sps(&gb, &ps->sps); + if (ret < 0) + goto out; + ps->sps_parsed = true; + break; + /*case H264_NAL_PPS: + ret = ff_h264_decode_picture_parameter_set(&gb, &ps->pps, rbsp_size); + if (ret < 0) + goto fail; + ps->pps_parsed = true; + break;*/ + default: + pr_err("Unsupport parser nal type (%s).\n", + h264_nal_unit_name(nal_type)); + break; + } + +out: + vfree(rbsp_buf); + + return ret; +} + +int h264_decode_extradata_ps(u8 *buf, int size, struct h264_param_sets *ps) +{ + int ret = 0, i = 0, j = 0; + u8 *p = buf; + int len = size; + + for (i = 4; i < size; i++) { + j = find_start_code(p, len); + if (j > 0) { + len = size - (p - buf); + ret = decode_extradata_ps(p, len, ps); + if (ret) { + pr_err("parse extra data failed. err: %d\n", ret); + return ret; + } + p += j; + } + p++; + } + + return ret; +} + + diff --git a/drivers/amvdec_ports/decoder/aml_h264_parser.h b/drivers/amvdec_ports/decoder/aml_h264_parser.h index 38d84b4..af48d78 100755..100644 --- a/drivers/amvdec_ports/decoder/aml_h264_parser.h +++ b/drivers/amvdec_ports/decoder/aml_h264_parser.h @@ -15,74 +15,186 @@ * */ - #ifndef AML_H264_PARSER_H #define AML_H264_PARSER_H -#define QP_MAX_NUM (51 + 6*6) // The maximum supported qp +#include "../utils/pixfmt.h" + +#define QP_MAX_NUM (51 + 6 * 6) // The maximum supported qp /* NAL unit types */ enum { - H264_NAL_SLICE = 1, - H264_NAL_DPA = 2, - H264_NAL_DPB = 3, - H264_NAL_DPC = 4, - H264_NAL_IDR_SLICE = 5, - H264_NAL_SEI = 6, - H264_NAL_SPS = 7, - H264_NAL_PPS = 8, - H264_NAL_AUD = 9, - H264_NAL_END_SEQUENCE = 10, - H264_NAL_END_STREAM = 11, - H264_NAL_FILLER_DATA = 12, - H264_NAL_SPS_EXT = 13, - H264_NAL_AUXILIARY_SLICE = 19, + H264_NAL_SLICE = 1, + H264_NAL_DPA = 2, + H264_NAL_DPB = 3, + H264_NAL_DPC = 4, + H264_NAL_IDR_SLICE = 5, + H264_NAL_SEI = 6, + H264_NAL_SPS = 7, + H264_NAL_PPS = 8, + H264_NAL_AUD = 9, + H264_NAL_END_SEQUENCE = 10, + H264_NAL_END_STREAM = 11, + H264_NAL_FILLER_DATA = 12, + H264_NAL_SPS_EXT = 13, + H264_NAL_AUXILIARY_SLICE = 19, }; - enum { - // 7.4.2.1.1: seq_parameter_set_id is in [0, 31]. - H264_MAX_SPS_COUNT = 32, - // 7.4.2.2: pic_parameter_set_id is in [0, 255]. - H264_MAX_PPS_COUNT = 256, - - // A.3: MaxDpbFrames is bounded above by 16. - H264_MAX_DPB_FRAMES = 16, - // 7.4.2.1.1: max_num_ref_frames is in [0, MaxDpbFrames], and - // each reference frame can have two fields. - H264_MAX_REFS = 2 * H264_MAX_DPB_FRAMES, - - // 7.4.3.1: modification_of_pic_nums_idc is not equal to 3 at most - // num_ref_idx_lN_active_minus1 + 1 times (that is, once for each - // possible reference), then equal to 3 once. - H264_MAX_RPLM_COUNT = H264_MAX_REFS + 1, - - // 7.4.3.3: in the worst case, we begin with a full short-term - // reference picture list. Each picture in turn is moved to the - // long-term list (type 3) and then discarded from there (type 2). - // Then, we set the length of the long-term list (type 4), mark - // the current picture as long-term (type 6) and terminate the - // process (type 0). - H264_MAX_MMCO_COUNT = H264_MAX_REFS * 2 + 3, - - // A.2.1, A.2.3: profiles supporting FMO constrain - // num_slice_groups_minus1 to be in [0, 7]. - H264_MAX_SLICE_GROUPS = 8, - - // E.2.2: cpb_cnt_minus1 is in [0, 31]. - H264_MAX_CPB_CNT = 32, - - // A.3: in table A-1 the highest level allows a MaxFS of 139264. - H264_MAX_MB_PIC_SIZE = 139264, - // A.3.1, A.3.2: PicWidthInMbs and PicHeightInMbs are constrained - // to be not greater than sqrt(MaxFS * 8). Hence height/width are - // bounded above by sqrt(139264 * 8) = 1055.5 macroblocks. - H264_MAX_MB_WIDTH = 1055, - H264_MAX_MB_HEIGHT = 1055, - H264_MAX_WIDTH = H264_MAX_MB_WIDTH * 16, - H264_MAX_HEIGHT = H264_MAX_MB_HEIGHT * 16, + // 7.4.2.1.1: seq_parameter_set_id is in [0, 31]. + H264_MAX_SPS_COUNT = 32, + // 7.4.2.2: pic_parameter_set_id is in [0, 255]. + H264_MAX_PPS_COUNT = 256, + + // A.3: MaxDpbFrames is bounded above by 16. + H264_MAX_DPB_FRAMES = 16, + // 7.4.2.1.1: max_num_ref_frames is in [0, MaxDpbFrames], and + // each reference frame can have two fields. + H264_MAX_REFS = 2 * H264_MAX_DPB_FRAMES, + + // 7.4.3.1: modification_of_pic_nums_idc is not equal to 3 at most + // num_ref_idx_lN_active_minus1 + 1 times (that is, once for each + // possible reference), then equal to 3 once. + H264_MAX_RPLM_COUNT = H264_MAX_REFS + 1, + + // 7.4.3.3: in the worst case, we begin with a full short-term + // reference picture list. Each picture in turn is moved to the + // long-term list (type 3) and then discarded from there (type 2). + // Then, we set the length of the long-term list (type 4), mark + // the current picture as long-term (type 6) and terminate the + // process (type 0). + H264_MAX_MMCO_COUNT = H264_MAX_REFS * 2 + 3, + + // A.2.1, A.2.3: profiles supporting FMO constrain + // num_slice_groups_minus1 to be in [0, 7]. + H264_MAX_SLICE_GROUPS = 8, + + // E.2.2: cpb_cnt_minus1 is in [0, 31]. + H264_MAX_CPB_CNT = 32, + + // A.3: in table A-1 the highest level allows a MaxFS of 139264. + H264_MAX_MB_PIC_SIZE = 139264, + // A.3.1, A.3.2: PicWidthInMbs and PicHeightInMbs are constrained + // to be not greater than sqrt(MaxFS * 8). Hence height/width are + // bounded above by sqrt(139264 * 8) = 1055.5 macroblocks. + H264_MAX_MB_WIDTH = 1055, + H264_MAX_MB_HEIGHT = 1055, + H264_MAX_WIDTH = H264_MAX_MB_WIDTH * 16, + H264_MAX_HEIGHT = H264_MAX_MB_HEIGHT * 16, +}; + +/** + * Rational number (pair of numerator and denominator). + */ +struct rational{ + int num; ///< Numerator + int den; ///< Denominator +}; + +/** + * Sequence parameter set + */ +struct h264_SPS_t { + u32 sps_id; + int profile_idc; + int level_idc; + int chroma_format_idc; + int transform_bypass; ///< qpprime_y_zero_transform_bypass_flag + int log2_max_frame_num; ///< log2_max_frame_num_minus4 + 4 + int poc_type; ///< pic_order_cnt_type + int log2_max_poc_lsb; ///< log2_max_pic_order_cnt_lsb_minus4 + int delta_pic_order_always_zero_flag; + int offset_for_non_ref_pic; + int offset_for_top_to_bottom_field; + int poc_cycle_length; ///< num_ref_frames_in_pic_order_cnt_cycle + int ref_frame_count; ///< num_ref_frames + int gaps_in_frame_num_allowed_flag; + int mb_width; ///< pic_width_in_mbs_minus1 + 1 + ///< (pic_height_in_map_units_minus1 + 1) * (2 - frame_mbs_only_flag) + int mb_height; + int frame_mbs_only_flag; + int mb_aff; ///< mb_adaptive_frame_field_flag + int direct_8x8_inference_flag; + int crop; ///< frame_cropping_flag + + /* those 4 are already in luma samples */ + u32 crop_left; ///< frame_cropping_rect_left_offset + u32 crop_right; ///< frame_cropping_rect_right_offset + u32 crop_top; ///< frame_cropping_rect_top_offset + u32 crop_bottom; ///< frame_cropping_rect_bottom_offset + int vui_parameters_present_flag; + struct rational sar; + int video_signal_type_present_flag; + int full_range; + int colour_description_present_flag; + enum AVColorPrimaries color_primaries; + enum AVColorTransferCharacteristic color_trc; + enum AVColorSpace colorspace; + int timing_info_present_flag; + u32 num_units_in_tick; + u32 time_scale; + int fixed_frame_rate_flag; + int32_t offset_for_ref_frame[256]; + int bitstream_restriction_flag; + int num_reorder_frames; + int max_dec_frame_buffering; + int scaling_matrix_present; + u8 scaling_matrix4[6][16]; + u8 scaling_matrix8[6][64]; + int nal_hrd_parameters_present_flag; + int vcl_hrd_parameters_present_flag; + int pic_struct_present_flag; + int time_offset_length; + int cpb_cnt; ///< See H.264 E.1.2 + int initial_cpb_removal_delay_length; ///< initial_cpb_removal_delay_length_minus1 + 1 + int cpb_removal_delay_length; ///< cpb_removal_delay_length_minus1 + 1 + int dpb_output_delay_length; ///< dpb_output_delay_length_minus1 + 1 + int bit_depth_luma; ///< bit_depth_luma_minus8 + 8 + int bit_depth_chroma; ///< bit_depth_chroma_minus8 + 8 + int residual_color_transform_flag; ///< residual_colour_transform_flag + int constraint_set_flags; ///< constraint_set[0-3]_flag +} ; + +/** + * Picture parameter set + */ +struct h264_PPS_t { + u32 sps_id; + int cabac; ///< entropy_coding_mode_flag + int pic_order_present; ///< pic_order_present_flag + int slice_group_count; ///< num_slice_groups_minus1 + 1 + int mb_slice_group_map_type; + u32 ref_count[2]; ///< num_ref_idx_l0/1_active_minus1 + 1 + int weighted_pred; ///< weighted_pred_flag + int weighted_bipred_idc; + int init_qp; ///< pic_init_qp_minus26 + 26 + int init_qs; ///< pic_init_qs_minus26 + 26 + int chroma_qp_index_offset[2]; + int deblocking_filter_parameters_present; ///< deblocking_filter_parameters_present_flag + int constrained_intra_pred; ///< constrained_intra_pred_flag + int redundant_pic_cnt_present; ///< redundant_pic_cnt_present_flag + int transform_8x8_mode; ///< transform_8x8_mode_flag + u8 scaling_matrix4[6][16]; + u8 scaling_matrix8[6][64]; + u8 chroma_qp_table[2][87+1]; ///< pre-scaled (with chroma_qp_index_offset) version of qp_table + int chroma_qp_diff; + u8 data[4096]; + int data_size; + + u32 dequant4_buffer[6][87 + 1][16]; + u32 dequant8_buffer[6][87 + 1][64]; + u32(*dequant4_coeff[6])[16]; + u32(*dequant8_coeff[6])[64]; +} ; + +struct h264_param_sets { + bool sps_parsed; + bool pps_parsed; + struct h264_SPS_t sps; + struct h264_PPS_t pps; }; +int h264_decode_extradata_ps(u8 *data, int size, struct h264_param_sets *ps); #endif /* AML_H264_PARSER_H */ diff --git a/drivers/amvdec_ports/decoder/aml_hevc_parser.c b/drivers/amvdec_ports/decoder/aml_hevc_parser.c new file mode 100644 index 0000000..33d44f1 --- a/dev/null +++ b/drivers/amvdec_ports/decoder/aml_hevc_parser.c @@ -0,0 +1,1274 @@ +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/vmalloc.h> +#include <linux/mm.h> +#include <linux/string.h> + +#include "aml_hevc_parser.h" +#include "../utils/get_bits.h" +#include "../utils/put_bits.h" +#include "../utils/golomb.h" +#include "../utils/common.h" +#include "utils.h" + +const u8 ff_hevc_diag_scan4x4_x[16] = { + 0, 0, 1, 0, + 1, 2, 0, 1, + 2, 3, 1, 2, + 3, 2, 3, 3, +}; + +const u8 ff_hevc_diag_scan4x4_y[16] = { + 0, 1, 0, 2, + 1, 0, 3, 2, + 1, 0, 3, 2, + 1, 3, 2, 3, +}; + +const u8 ff_hevc_diag_scan8x8_x[64] = { + 0, 0, 1, 0, + 1, 2, 0, 1, + 2, 3, 0, 1, + 2, 3, 4, 0, + 1, 2, 3, 4, + 5, 0, 1, 2, + 3, 4, 5, 6, + 0, 1, 2, 3, + 4, 5, 6, 7, + 1, 2, 3, 4, + 5, 6, 7, 2, + 3, 4, 5, 6, + 7, 3, 4, 5, + 6, 7, 4, 5, + 6, 7, 5, 6, + 7, 6, 7, 7, +}; + +const u8 ff_hevc_diag_scan8x8_y[64] = { + 0, 1, 0, 2, + 1, 0, 3, 2, + 1, 0, 4, 3, + 2, 1, 0, 5, + 4, 3, 2, 1, + 0, 6, 5, 4, + 3, 2, 1, 0, + 7, 6, 5, 4, + 3, 2, 1, 0, + 7, 6, 5, 4, + 3, 2, 1, 7, + 6, 5, 4, 3, + 2, 7, 6, 5, + 4, 3, 7, 6, + 5, 4, 7, 6, + 5, 7, 6, 7, +}; + +static const u8 default_scaling_list_intra[] = { + 16, 16, 16, 16, 17, 18, 21, 24, + 16, 16, 16, 16, 17, 19, 22, 25, + 16, 16, 17, 18, 20, 22, 25, 29, + 16, 16, 18, 21, 24, 27, 31, 36, + 17, 17, 20, 24, 30, 35, 41, 47, + 18, 19, 22, 27, 35, 44, 54, 65, + 21, 22, 25, 31, 41, 54, 70, 88, + 24, 25, 29, 36, 47, 65, 88, 115 +}; + +static const u8 default_scaling_list_inter[] = { + 16, 16, 16, 16, 17, 18, 20, 24, + 16, 16, 16, 17, 18, 20, 24, 25, + 16, 16, 17, 18, 20, 24, 25, 28, + 16, 17, 18, 20, 24, 25, 28, 33, + 17, 18, 20, 24, 25, 28, 33, 41, + 18, 20, 24, 25, 28, 33, 41, 54, + 20, 24, 25, 28, 33, 41, 54, 71, + 24, 25, 28, 33, 41, 54, 71, 91 +}; + +static const struct AVRational vui_sar[] = { + { 0, 1 }, + { 1, 1 }, + { 12, 11 }, + { 10, 11 }, + { 16, 11 }, + { 40, 33 }, + { 24, 11 }, + { 20, 11 }, + { 32, 11 }, + { 80, 33 }, + { 18, 11 }, + { 15, 11 }, + { 64, 33 }, + { 160, 99 }, + { 4, 3 }, + { 3, 2 }, + { 2, 1 }, +}; + +static const u8 hevc_sub_width_c[] = { + 1, 2, 2, 1 +}; + +static const u8 hevc_sub_height_c[] = { + 1, 2, 1, 1 +}; + +static int decode_profile_tier_level(struct get_bits_context *gb, struct PTLCommon *ptl) +{ + int i; + + if (get_bits_left(gb) < 2+1+5 + 32 + 4 + 16 + 16 + 12) + return -1; + + ptl->profile_space = get_bits(gb, 2); + ptl->tier_flag = get_bits1(gb); + ptl->profile_idc = get_bits(gb, 5); + if (ptl->profile_idc == FF_PROFILE_HEVC_MAIN) + pr_info("Main profile bitstream\n"); + else if (ptl->profile_idc == FF_PROFILE_HEVC_MAIN_10) + pr_info("Main 10 profile bitstream\n"); + else if (ptl->profile_idc == FF_PROFILE_HEVC_MAIN_STILL_PICTURE) + pr_info("Main Still Picture profile bitstream\n"); + else if (ptl->profile_idc == FF_PROFILE_HEVC_REXT) + pr_info("Range Extension profile bitstream\n"); + else + pr_info("Unknown HEVC profile: %d\n", ptl->profile_idc); + + for (i = 0; i < 32; i++) { + ptl->profile_compatibility_flag[i] = get_bits1(gb); + + if (ptl->profile_idc == 0 && i > 0 && ptl->profile_compatibility_flag[i]) + ptl->profile_idc = i; + } + ptl->progressive_source_flag = get_bits1(gb); + ptl->interlaced_source_flag = get_bits1(gb); + ptl->non_packed_constraint_flag = get_bits1(gb); + ptl->frame_only_constraint_flag = get_bits1(gb); + + skip_bits(gb, 16); // XXX_reserved_zero_44bits[0..15] + skip_bits(gb, 16); // XXX_reserved_zero_44bits[16..31] + skip_bits(gb, 12); // XXX_reserved_zero_44bits[32..43] + + return 0; +} + +static int parse_ptl(struct get_bits_context *gb, struct PTL *ptl, int max_num_sub_layers) +{ + int i; + if (decode_profile_tier_level(gb, &ptl->general_ptl) < 0 || + get_bits_left(gb) < 8 + (8*2 * (max_num_sub_layers - 1 > 0))) { + pr_err("PTL information too short\n"); + return -1; + } + + ptl->general_ptl.level_idc = get_bits(gb, 8); + + for (i = 0; i < max_num_sub_layers - 1; i++) { + ptl->sub_layer_profile_present_flag[i] = get_bits1(gb); + ptl->sub_layer_level_present_flag[i] = get_bits1(gb); + } + + if (max_num_sub_layers - 1> 0) + for (i = max_num_sub_layers - 1; i < 8; i++) + skip_bits(gb, 2); // reserved_zero_2bits[i] + for (i = 0; i < max_num_sub_layers - 1; i++) { + if (ptl->sub_layer_profile_present_flag[i] && + decode_profile_tier_level(gb, &ptl->sub_layer_ptl[i]) < 0) { + pr_err("PTL information for sublayer %i too short\n", i); + return -1; + } + if (ptl->sub_layer_level_present_flag[i]) { + if (get_bits_left(gb) < 8) { + pr_err("Not enough data for sublayer %i level_idc\n", i); + return -1; + } else + ptl->sub_layer_ptl[i].level_idc = get_bits(gb, 8); + } + } + + return 0; +} + +static void decode_sublayer_hrd(struct get_bits_context *gb, + u32 nb_cpb, int subpic_params_present) +{ + int i; + + for (i = 0; i < nb_cpb; i++) { + get_ue_golomb_long(gb); // bit_rate_value_minus1 + get_ue_golomb_long(gb); // cpb_size_value_minus1 + + if (subpic_params_present) { + get_ue_golomb_long(gb); // cpb_size_du_value_minus1 + get_ue_golomb_long(gb); // bit_rate_du_value_minus1 + } + skip_bits1(gb); // cbr_flag + } +} + +static int decode_hrd(struct get_bits_context *gb, + int common_inf_present, int max_sublayers) +{ + int nal_params_present = 0, vcl_params_present = 0; + int subpic_params_present = 0; + int i; + + if (common_inf_present) { + nal_params_present = get_bits1(gb); + vcl_params_present = get_bits1(gb); + + if (nal_params_present || vcl_params_present) { + subpic_params_present = get_bits1(gb); + + if (subpic_params_present) { + skip_bits(gb, 8); // tick_divisor_minus2 + skip_bits(gb, 5); // du_cpb_removal_delay_increment_length_minus1 + skip_bits(gb, 1); // sub_pic_cpb_params_in_pic_timing_sei_flag + skip_bits(gb, 5); // dpb_output_delay_du_length_minus1 + } + + skip_bits(gb, 4); // bit_rate_scale + skip_bits(gb, 4); // cpb_size_scale + + if (subpic_params_present) + skip_bits(gb, 4); // cpb_size_du_scale + + skip_bits(gb, 5); // initial_cpb_removal_delay_length_minus1 + skip_bits(gb, 5); // au_cpb_removal_delay_length_minus1 + skip_bits(gb, 5); // dpb_output_delay_length_minus1 + } + } + + for (i = 0; i < max_sublayers; i++) { + int low_delay = 0; + u32 nb_cpb = 1; + int fixed_rate = get_bits1(gb); + + if (!fixed_rate) + fixed_rate = get_bits1(gb); + + if (fixed_rate) + get_ue_golomb_long(gb); // elemental_duration_in_tc_minus1 + else + low_delay = get_bits1(gb); + + if (!low_delay) { + nb_cpb = get_ue_golomb_long(gb) + 1; + if (nb_cpb < 1 || nb_cpb > 32) { + pr_err("nb_cpb %d invalid\n", nb_cpb); + return -1; + } + } + + if (nal_params_present) + decode_sublayer_hrd(gb, nb_cpb, subpic_params_present); + if (vcl_params_present) + decode_sublayer_hrd(gb, nb_cpb, subpic_params_present); + } + return 0; +} + +int ff_hevc_parse_vps(struct get_bits_context *gb, struct h265_VPS_t *vps) +{ + int i,j; + int vps_id = 0; + + pr_info("Decoding VPS\n"); + + vps_id = get_bits(gb, 4); + if (vps_id >= HEVC_MAX_VPS_COUNT) { + pr_err("VPS id out of range: %d\n", vps_id); + goto err; + } + + if (get_bits(gb, 2) != 3) { // vps_reserved_three_2bits + pr_err("vps_reserved_three_2bits is not three\n"); + goto err; + } + + vps->vps_max_layers = get_bits(gb, 6) + 1; + vps->vps_max_sub_layers = get_bits(gb, 3) + 1; + vps->vps_temporal_id_nesting_flag = get_bits1(gb); + + if (get_bits(gb, 16) != 0xffff) { // vps_reserved_ffff_16bits + pr_err("vps_reserved_ffff_16bits is not 0xffff\n"); + goto err; + } + + if (vps->vps_max_sub_layers > HEVC_MAX_SUB_LAYERS) { + pr_err("vps_max_sub_layers out of range: %d\n", + vps->vps_max_sub_layers); + goto err; + } + + if (parse_ptl(gb, &vps->ptl, vps->vps_max_sub_layers) < 0) + goto err; + + vps->vps_sub_layer_ordering_info_present_flag = get_bits1(gb); + + i = vps->vps_sub_layer_ordering_info_present_flag ? 0 : vps->vps_max_sub_layers - 1; + for (; i < vps->vps_max_sub_layers; i++) { + vps->vps_max_dec_pic_buffering[i] = get_ue_golomb_long(gb) + 1; + vps->vps_num_reorder_pics[i] = get_ue_golomb_long(gb); + vps->vps_max_latency_increase[i] = get_ue_golomb_long(gb) - 1; + + if (vps->vps_max_dec_pic_buffering[i] > HEVC_MAX_DPB_SIZE || !vps->vps_max_dec_pic_buffering[i]) { + pr_err("vps_max_dec_pic_buffering_minus1 out of range: %d\n", + vps->vps_max_dec_pic_buffering[i] - 1); + goto err; + } + if (vps->vps_num_reorder_pics[i] > vps->vps_max_dec_pic_buffering[i] - 1) { + pr_err("vps_max_num_reorder_pics out of range: %d\n", + vps->vps_num_reorder_pics[i]); + goto err; + } + } + + vps->vps_max_layer_id = get_bits(gb, 6); + vps->vps_num_layer_sets = get_ue_golomb_long(gb) + 1; + if (vps->vps_num_layer_sets < 1 || vps->vps_num_layer_sets > 1024 || + (vps->vps_num_layer_sets - 1LL) * (vps->vps_max_layer_id + 1LL) > get_bits_left(gb)) { + pr_err("too many layer_id_included_flags\n"); + goto err; + } + + for (i = 1; i < vps->vps_num_layer_sets; i++) + for (j = 0; j <= vps->vps_max_layer_id; j++) + skip_bits(gb, 1); // layer_id_included_flag[i][j] + + vps->vps_timing_info_present_flag = get_bits1(gb); + if (vps->vps_timing_info_present_flag) { + vps->vps_num_units_in_tick = get_bits_long(gb, 32); + vps->vps_time_scale = get_bits_long(gb, 32); + vps->vps_poc_proportional_to_timing_flag = get_bits1(gb); + if (vps->vps_poc_proportional_to_timing_flag) + vps->vps_num_ticks_poc_diff_one = get_ue_golomb_long(gb) + 1; + vps->vps_num_hrd_parameters = get_ue_golomb_long(gb); + if (vps->vps_num_hrd_parameters > (u32)vps->vps_num_layer_sets) { + pr_err("vps_num_hrd_parameters %d is invalid\n", vps->vps_num_hrd_parameters); + goto err; + } + for (i = 0; i < vps->vps_num_hrd_parameters; i++) { + int common_inf_present = 1; + + get_ue_golomb_long(gb); // hrd_layer_set_idx + if (i) + common_inf_present = get_bits1(gb); + decode_hrd(gb, common_inf_present, vps->vps_max_sub_layers); + } + } + get_bits1(gb); /* vps_extension_flag */ + + if (get_bits_left(gb) < 0) { + pr_err("Overread VPS by %d bits\n", -get_bits_left(gb)); + goto err; + } + + return 0; +err: + return -1; +} + +static int map_pixel_format(struct h265_SPS_t *sps) +{ + /*const AVPixFmtDescriptor *desc;*/ + switch (sps->bit_depth) { + case 8: + if (sps->chroma_format_idc == 0) sps->pix_fmt = AV_PIX_FMT_GRAY8; + if (sps->chroma_format_idc == 1) sps->pix_fmt = AV_PIX_FMT_YUV420P; + if (sps->chroma_format_idc == 2) sps->pix_fmt = AV_PIX_FMT_YUV422P; + if (sps->chroma_format_idc == 3) sps->pix_fmt = AV_PIX_FMT_YUV444P; + break; + case 9: + if (sps->chroma_format_idc == 0) sps->pix_fmt = AV_PIX_FMT_GRAY9; + if (sps->chroma_format_idc == 1) sps->pix_fmt = AV_PIX_FMT_YUV420P9; + if (sps->chroma_format_idc == 2) sps->pix_fmt = AV_PIX_FMT_YUV422P9; + if (sps->chroma_format_idc == 3) sps->pix_fmt = AV_PIX_FMT_YUV444P9; + break; + case 10: + if (sps->chroma_format_idc == 0) sps->pix_fmt = AV_PIX_FMT_GRAY10; + if (sps->chroma_format_idc == 1) sps->pix_fmt = AV_PIX_FMT_YUV420P10; + if (sps->chroma_format_idc == 2) sps->pix_fmt = AV_PIX_FMT_YUV422P10; + if (sps->chroma_format_idc == 3) sps->pix_fmt = AV_PIX_FMT_YUV444P10; + break; + case 12: + if (sps->chroma_format_idc == 0) sps->pix_fmt = AV_PIX_FMT_GRAY12; + if (sps->chroma_format_idc == 1) sps->pix_fmt = AV_PIX_FMT_YUV420P12; + if (sps->chroma_format_idc == 2) sps->pix_fmt = AV_PIX_FMT_YUV422P12; + if (sps->chroma_format_idc == 3) sps->pix_fmt = AV_PIX_FMT_YUV444P12; + break; + default: + pr_info("The following bit-depths are currently specified: 8, 9, 10 and 12 bits, " + "chroma_format_idc is %d, depth is %d\n", + sps->chroma_format_idc, sps->bit_depth); + return -1; + } + + /*desc = av_pix_fmt_desc_get(sps->pix_fmt); + if (!desc) + return AVERROR(EINVAL); + + sps->hshift[0] = sps->vshift[0] = 0; + sps->hshift[2] = sps->hshift[1] = desc->log2_chroma_w; + sps->vshift[2] = sps->vshift[1] = desc->log2_chroma_h;*/ + + sps->pixel_shift = sps->bit_depth > 8; + + return 0; +} + +static void set_default_scaling_list_data(struct ScalingList *sl) +{ + int matrixId; + + for (matrixId = 0; matrixId < 6; matrixId++) { + // 4x4 default is 16 + memset(sl->sl[0][matrixId], 16, 16); + sl->sl_dc[0][matrixId] = 16; // default for 16x16 + sl->sl_dc[1][matrixId] = 16; // default for 32x32 + } + memcpy(sl->sl[1][0], default_scaling_list_intra, 64); + memcpy(sl->sl[1][1], default_scaling_list_intra, 64); + memcpy(sl->sl[1][2], default_scaling_list_intra, 64); + memcpy(sl->sl[1][3], default_scaling_list_inter, 64); + memcpy(sl->sl[1][4], default_scaling_list_inter, 64); + memcpy(sl->sl[1][5], default_scaling_list_inter, 64); + memcpy(sl->sl[2][0], default_scaling_list_intra, 64); + memcpy(sl->sl[2][1], default_scaling_list_intra, 64); + memcpy(sl->sl[2][2], default_scaling_list_intra, 64); + memcpy(sl->sl[2][3], default_scaling_list_inter, 64); + memcpy(sl->sl[2][4], default_scaling_list_inter, 64); + memcpy(sl->sl[2][5], default_scaling_list_inter, 64); + memcpy(sl->sl[3][0], default_scaling_list_intra, 64); + memcpy(sl->sl[3][1], default_scaling_list_intra, 64); + memcpy(sl->sl[3][2], default_scaling_list_intra, 64); + memcpy(sl->sl[3][3], default_scaling_list_inter, 64); + memcpy(sl->sl[3][4], default_scaling_list_inter, 64); + memcpy(sl->sl[3][5], default_scaling_list_inter, 64); +} + +static int scaling_list_data(struct get_bits_context *gb, + struct ScalingList *sl, struct h265_SPS_t *sps) +{ + u8 scaling_list_pred_mode_flag; + int scaling_list_dc_coef[2][6]; + int size_id, matrix_id, pos; + int i; + + for (size_id = 0; size_id < 4; size_id++) + for (matrix_id = 0; matrix_id < 6; matrix_id += ((size_id == 3) ? 3 : 1)) { + scaling_list_pred_mode_flag = get_bits1(gb); + if (!scaling_list_pred_mode_flag) { + u32 delta = get_ue_golomb_long(gb); + /* Only need to handle non-zero delta. Zero means default, + * which should already be in the arrays. */ + if (delta) { + // Copy from previous array. + delta *= (size_id == 3) ? 3 : 1; + if (matrix_id < delta) { + pr_err("Invalid delta in scaling list data: %d.\n", delta); + return -1; + } + + memcpy(sl->sl[size_id][matrix_id], + sl->sl[size_id][matrix_id - delta], + size_id > 0 ? 64 : 16); + if (size_id > 1) + sl->sl_dc[size_id - 2][matrix_id] = sl->sl_dc[size_id - 2][matrix_id - delta]; + } + } else { + int next_coef, coef_num; + int scaling_list_delta_coef; + + next_coef = 8; + coef_num = FFMIN(64, 1 << (4 + (size_id << 1))); + if (size_id > 1) { + scaling_list_dc_coef[size_id - 2][matrix_id] = get_se_golomb(gb) + 8; + next_coef = scaling_list_dc_coef[size_id - 2][matrix_id]; + sl->sl_dc[size_id - 2][matrix_id] = next_coef; + } + for (i = 0; i < coef_num; i++) { + if (size_id == 0) + pos = 4 * ff_hevc_diag_scan4x4_y[i] + + ff_hevc_diag_scan4x4_x[i]; + else + pos = 8 * ff_hevc_diag_scan8x8_y[i] + + ff_hevc_diag_scan8x8_x[i]; + + scaling_list_delta_coef = get_se_golomb(gb); + next_coef = (next_coef + 256U + scaling_list_delta_coef) % 256; + sl->sl[size_id][matrix_id][pos] = next_coef; + } + } + } + + if (sps->chroma_format_idc == 3) { + for (i = 0; i < 64; i++) { + sl->sl[3][1][i] = sl->sl[2][1][i]; + sl->sl[3][2][i] = sl->sl[2][2][i]; + sl->sl[3][4][i] = sl->sl[2][4][i]; + sl->sl[3][5][i] = sl->sl[2][5][i]; + } + sl->sl_dc[1][1] = sl->sl_dc[0][1]; + sl->sl_dc[1][2] = sl->sl_dc[0][2]; + sl->sl_dc[1][4] = sl->sl_dc[0][4]; + sl->sl_dc[1][5] = sl->sl_dc[0][5]; + } + + return 0; +} + +int ff_hevc_decode_short_term_rps(struct get_bits_context *gb, + struct ShortTermRPS *rps, const struct h265_SPS_t *sps, int is_slice_header) +{ + u8 rps_predict = 0; + int delta_poc; + int k0 = 0; + int k1 = 0; + int k = 0; + int i; + + if (rps != sps->st_rps && sps->nb_st_rps) + rps_predict = get_bits1(gb); + + if (rps_predict) { + const struct ShortTermRPS *rps_ridx; + int delta_rps; + u32 abs_delta_rps; + u8 use_delta_flag = 0; + u8 delta_rps_sign; + + if (is_slice_header) { + u32 delta_idx = get_ue_golomb_long(gb) + 1; + if (delta_idx > sps->nb_st_rps) { + pr_err("Invalid value of delta_idx in slice header RPS: %d > %d.\n", + delta_idx, sps->nb_st_rps); + return -1; + } + rps_ridx = &sps->st_rps[sps->nb_st_rps - delta_idx]; + rps->rps_idx_num_delta_pocs = rps_ridx->num_delta_pocs; + } else + rps_ridx = &sps->st_rps[rps - sps->st_rps - 1]; + + delta_rps_sign = get_bits1(gb); + abs_delta_rps = get_ue_golomb_long(gb) + 1; + if (abs_delta_rps < 1 || abs_delta_rps > 32768) { + pr_err("Invalid value of abs_delta_rps: %d\n", + abs_delta_rps); + return -1; + } + delta_rps = (1 - (delta_rps_sign << 1)) * abs_delta_rps; + for (i = 0; i <= rps_ridx->num_delta_pocs; i++) { + int used = rps->used[k] = get_bits1(gb); + + if (!used) + use_delta_flag = get_bits1(gb); + + if (used || use_delta_flag) { + if (i < rps_ridx->num_delta_pocs) + delta_poc = delta_rps + rps_ridx->delta_poc[i]; + else + delta_poc = delta_rps; + rps->delta_poc[k] = delta_poc; + if (delta_poc < 0) + k0++; + else + k1++; + k++; + } + } + + if (k >= ARRAY_SIZE(rps->used)) { + pr_err( "Invalid num_delta_pocs: %d\n", k); + return -1; + } + + rps->num_delta_pocs = k; + rps->num_negative_pics = k0; + // sort in increasing order (smallest first) + if (rps->num_delta_pocs != 0) { + int used, tmp; + for (i = 1; i < rps->num_delta_pocs; i++) { + delta_poc = rps->delta_poc[i]; + used = rps->used[i]; + for (k = i - 1; k >= 0; k--) { + tmp = rps->delta_poc[k]; + if (delta_poc < tmp) { + rps->delta_poc[k + 1] = tmp; + rps->used[k + 1] = rps->used[k]; + rps->delta_poc[k] = delta_poc; + rps->used[k] = used; + } + } + } + } + if ((rps->num_negative_pics >> 1) != 0) { + int used; + k = rps->num_negative_pics - 1; + // flip the negative values to largest first + for (i = 0; i < rps->num_negative_pics >> 1; i++) { + delta_poc = rps->delta_poc[i]; + used = rps->used[i]; + rps->delta_poc[i] = rps->delta_poc[k]; + rps->used[i] = rps->used[k]; + rps->delta_poc[k] = delta_poc; + rps->used[k] = used; + k--; + } + } + } else { + u32 prev, nb_positive_pics; + rps->num_negative_pics = get_ue_golomb_long(gb); + nb_positive_pics = get_ue_golomb_long(gb); + + if (rps->num_negative_pics >= HEVC_MAX_REFS || + nb_positive_pics >= HEVC_MAX_REFS) { + pr_err("Too many refs in a short term RPS.\n"); + return -1; + } + + rps->num_delta_pocs = rps->num_negative_pics + nb_positive_pics; + if (rps->num_delta_pocs) { + prev = 0; + for (i = 0; i < rps->num_negative_pics; i++) { + delta_poc = get_ue_golomb_long(gb) + 1; + if (delta_poc < 1 || delta_poc > 32768) { + pr_err("Invalid value of delta_poc: %d\n", + delta_poc); + return -1; + } + prev -= delta_poc; + rps->delta_poc[i] = prev; + rps->used[i] = get_bits1(gb); + } + prev = 0; + for (i = 0; i < nb_positive_pics; i++) { + delta_poc = get_ue_golomb_long(gb) + 1; + if (delta_poc < 1 || delta_poc > 32768) { + pr_err("Invalid value of delta_poc: %d\n", + delta_poc); + return -1; + } + prev += delta_poc; + rps->delta_poc[rps->num_negative_pics + i] = prev; + rps->used[rps->num_negative_pics + i] = get_bits1(gb); + } + } + } + return 0; +} + +static void decode_vui(struct get_bits_context *gb, struct h265_SPS_t *sps) +{ + struct VUI backup_vui, *vui = &sps->vui; + struct get_bits_context backup; + int sar_present, alt = 0; + + pr_info("Decoding VUI\n"); + + sar_present = get_bits1(gb); + if (sar_present) { + u8 sar_idx = get_bits(gb, 8); + if (sar_idx < ARRAY_SIZE(vui_sar)) + vui->sar = vui_sar[sar_idx]; + else if (sar_idx == 255) { + vui->sar.num = get_bits(gb, 16); + vui->sar.den = get_bits(gb, 16); + } else + pr_info("Unknown SAR index: %u.\n", sar_idx); + } + + vui->overscan_info_present_flag = get_bits1(gb); + if (vui->overscan_info_present_flag) + vui->overscan_appropriate_flag = get_bits1(gb); + + vui->video_signal_type_present_flag = get_bits1(gb); + if (vui->video_signal_type_present_flag) { + vui->video_format = get_bits(gb, 3); + vui->video_full_range_flag = get_bits1(gb); + vui->colour_description_present_flag = get_bits1(gb); + if (vui->video_full_range_flag && sps->pix_fmt == AV_PIX_FMT_YUV420P) + sps->pix_fmt = AV_PIX_FMT_YUVJ420P; + if (vui->colour_description_present_flag) { + vui->colour_primaries = get_bits(gb, 8); + vui->transfer_characteristic = get_bits(gb, 8); + vui->matrix_coeffs = get_bits(gb, 8); + + // Set invalid values to "unspecified" + if (!av_color_primaries_name(vui->colour_primaries)) + vui->colour_primaries = AVCOL_PRI_UNSPECIFIED; + if (!av_color_transfer_name(vui->transfer_characteristic)) + vui->transfer_characteristic = AVCOL_TRC_UNSPECIFIED; + if (!av_color_space_name(vui->matrix_coeffs)) + vui->matrix_coeffs = AVCOL_SPC_UNSPECIFIED; + if (vui->matrix_coeffs == AVCOL_SPC_RGB) { + switch (sps->pix_fmt) { + case AV_PIX_FMT_YUV444P: + sps->pix_fmt = AV_PIX_FMT_GBRP; + break; + case AV_PIX_FMT_YUV444P10: + sps->pix_fmt = AV_PIX_FMT_GBRP10; + break; + case AV_PIX_FMT_YUV444P12: + sps->pix_fmt = AV_PIX_FMT_GBRP12; + break; + } + } + } + } + + vui->chroma_loc_info_present_flag = get_bits1(gb); + if (vui->chroma_loc_info_present_flag) { + vui->chroma_sample_loc_type_top_field = get_ue_golomb_long(gb); + vui->chroma_sample_loc_type_bottom_field = get_ue_golomb_long(gb); + } + + vui->neutra_chroma_indication_flag = get_bits1(gb); + vui->field_seq_flag = get_bits1(gb); + vui->frame_field_info_present_flag = get_bits1(gb); + + // Backup context in case an alternate header is detected + memcpy(&backup, gb, sizeof(backup)); + memcpy(&backup_vui, vui, sizeof(backup_vui)); + if (get_bits_left(gb) >= 68 && show_bits_long(gb, 21) == 0x100000) { + vui->default_display_window_flag = 0; + pr_info("Invalid default display window\n"); + } else + vui->default_display_window_flag = get_bits1(gb); + + if (vui->default_display_window_flag) { + int vert_mult = hevc_sub_height_c[sps->chroma_format_idc]; + int horiz_mult = hevc_sub_width_c[sps->chroma_format_idc]; + vui->def_disp_win.left_offset = get_ue_golomb_long(gb) * horiz_mult; + vui->def_disp_win.right_offset = get_ue_golomb_long(gb) * horiz_mult; + vui->def_disp_win.top_offset = get_ue_golomb_long(gb) * vert_mult; + vui->def_disp_win.bottom_offset = get_ue_golomb_long(gb) * vert_mult; + } + +timing_info: + vui->vui_timing_info_present_flag = get_bits1(gb); + + if (vui->vui_timing_info_present_flag) { + if (get_bits_left(gb) < 66 && !alt) { + // The alternate syntax seem to have timing info located + // at where def_disp_win is normally located + pr_info("Strange VUI timing information, retrying...\n"); + memcpy(vui, &backup_vui, sizeof(backup_vui)); + memcpy(gb, &backup, sizeof(backup)); + alt = 1; + goto timing_info; + } + vui->vui_num_units_in_tick = get_bits_long(gb, 32); + vui->vui_time_scale = get_bits_long(gb, 32); + if (alt) { + pr_info("Retry got %u/%u fps\n", + vui->vui_time_scale, vui->vui_num_units_in_tick); + } + vui->vui_poc_proportional_to_timing_flag = get_bits1(gb); + if (vui->vui_poc_proportional_to_timing_flag) + vui->vui_num_ticks_poc_diff_one_minus1 = get_ue_golomb_long(gb); + vui->vui_hrd_parameters_present_flag = get_bits1(gb); + if (vui->vui_hrd_parameters_present_flag) + decode_hrd(gb, 1, sps->max_sub_layers); + } + + vui->bitstream_restriction_flag = get_bits1(gb); + if (vui->bitstream_restriction_flag) { + if (get_bits_left(gb) < 8 && !alt) { + pr_info("Strange VUI bitstream restriction information, retrying" + " from timing information...\n"); + memcpy(vui, &backup_vui, sizeof(backup_vui)); + memcpy(gb, &backup, sizeof(backup)); + alt = 1; + goto timing_info; + } + vui->tiles_fixed_structure_flag = get_bits1(gb); + vui->motion_vectors_over_pic_boundaries_flag = get_bits1(gb); + vui->restricted_ref_pic_lists_flag = get_bits1(gb); + vui->min_spatial_segmentation_idc = get_ue_golomb_long(gb); + vui->max_bytes_per_pic_denom = get_ue_golomb_long(gb); + vui->max_bits_per_min_cu_denom = get_ue_golomb_long(gb); + vui->log2_max_mv_length_horizontal = get_ue_golomb_long(gb); + vui->log2_max_mv_length_vertical = get_ue_golomb_long(gb); + } + + if (get_bits_left(gb) < 1 && !alt) { + // XXX: Alternate syntax when sps_range_extension_flag != 0? + pr_info("Overread in VUI, retrying from timing information...\n"); + memcpy(vui, &backup_vui, sizeof(backup_vui)); + memcpy(gb, &backup, sizeof(backup)); + alt = 1; + goto timing_info; + } +} + +int ff_hevc_parse_sps(struct get_bits_context *gb, struct h265_SPS_t *sps) +{ + int i, ret = 0; + int log2_diff_max_min_transform_block_size; + int bit_depth_chroma, start, vui_present, sublayer_ordering_info; + struct HEVCWindow *ow; + + sps->vps_id = get_bits(gb, 4); + if (sps->vps_id >= HEVC_MAX_VPS_COUNT) { + pr_err("VPS id out of range: %d\n", sps->vps_id); + return -1; + } + + sps->max_sub_layers = get_bits(gb, 3) + 1; + if (sps->max_sub_layers > HEVC_MAX_SUB_LAYERS) { + pr_err("sps_max_sub_layers out of range: %d\n", + sps->max_sub_layers); + return -1; + } + + sps->temporal_id_nesting_flag = get_bits(gb, 1); + + if ((ret = parse_ptl(gb, &sps->ptl, sps->max_sub_layers)) < 0) + return ret; + + sps->sps_id = get_ue_golomb_long(gb); + if (sps->sps_id >= HEVC_MAX_SPS_COUNT) { + pr_err("SPS id out of range: %d\n", sps->sps_id); + return -1; + } + + sps->chroma_format_idc = get_ue_golomb_long(gb); + if (sps->chroma_format_idc > 3U) { + pr_err("chroma_format_idc %d is invalid\n", sps->chroma_format_idc); + return -1; + } + + if (sps->chroma_format_idc == 3) + sps->separate_colour_plane_flag = get_bits1(gb); + + if (sps->separate_colour_plane_flag) + sps->chroma_format_idc = 0; + + sps->width = get_ue_golomb_long(gb); + sps->height = get_ue_golomb_long(gb); + if (sps->width > 8192 || sps->height > 8192) { + pr_err("width or height oversize.\n"); + return -1; + } + + if (get_bits1(gb)) { // pic_conformance_flag + int vert_mult = hevc_sub_height_c[sps->chroma_format_idc]; + int horiz_mult = hevc_sub_width_c[sps->chroma_format_idc]; + sps->pic_conf_win.left_offset = get_ue_golomb_long(gb) * horiz_mult; + sps->pic_conf_win.right_offset = get_ue_golomb_long(gb) * horiz_mult; + sps->pic_conf_win.top_offset = get_ue_golomb_long(gb) * vert_mult; + sps->pic_conf_win.bottom_offset = get_ue_golomb_long(gb) * vert_mult; + sps->output_window = sps->pic_conf_win; + } + + sps->bit_depth = get_ue_golomb_long(gb) + 8; + bit_depth_chroma = get_ue_golomb_long(gb) + 8; + if (sps->chroma_format_idc && bit_depth_chroma != sps->bit_depth) { + pr_err("Luma bit depth (%d) is different from chroma bit depth (%d), this is unsupported.\n", + sps->bit_depth, bit_depth_chroma); + return -1; + } + sps->bit_depth_chroma = bit_depth_chroma; + + ret = map_pixel_format(sps); + if (ret < 0) + return ret; + + sps->log2_max_poc_lsb = get_ue_golomb_long(gb) + 4; + if (sps->log2_max_poc_lsb > 16) { + pr_err("log2_max_pic_order_cnt_lsb_minus4 out range: %d\n", + sps->log2_max_poc_lsb - 4); + return -1; + } + + sublayer_ordering_info = get_bits1(gb); + start = sublayer_ordering_info ? 0 : sps->max_sub_layers - 1; + for (i = start; i < sps->max_sub_layers; i++) { + sps->temporal_layer[i].max_dec_pic_buffering = get_ue_golomb_long(gb) + 1; + sps->temporal_layer[i].num_reorder_pics = get_ue_golomb_long(gb); + sps->temporal_layer[i].max_latency_increase = get_ue_golomb_long(gb) - 1; + if (sps->temporal_layer[i].max_dec_pic_buffering > (u32)HEVC_MAX_DPB_SIZE) { + pr_err("sps_max_dec_pic_buffering_minus1 out of range: %d\n", + sps->temporal_layer[i].max_dec_pic_buffering - 1U); + return -1; + } + if (sps->temporal_layer[i].num_reorder_pics > sps->temporal_layer[i].max_dec_pic_buffering - 1) { + pr_info("sps_max_num_reorder_pics out of range: %d\n", + sps->temporal_layer[i].num_reorder_pics); + if (sps->temporal_layer[i].num_reorder_pics > HEVC_MAX_DPB_SIZE - 1) { + return -1; + } + sps->temporal_layer[i].max_dec_pic_buffering = sps->temporal_layer[i].num_reorder_pics + 1; + } + } + + if (!sublayer_ordering_info) { + for (i = 0; i < start; i++) { + sps->temporal_layer[i].max_dec_pic_buffering = sps->temporal_layer[start].max_dec_pic_buffering; + sps->temporal_layer[i].num_reorder_pics = sps->temporal_layer[start].num_reorder_pics; + sps->temporal_layer[i].max_latency_increase = sps->temporal_layer[start].max_latency_increase; + } + } + + sps->log2_min_cb_size = get_ue_golomb_long(gb) + 3; + sps->log2_diff_max_min_coding_block_size = get_ue_golomb_long(gb); + sps->log2_min_tb_size = get_ue_golomb_long(gb) + 2; + log2_diff_max_min_transform_block_size = get_ue_golomb_long(gb); + sps->log2_max_trafo_size = log2_diff_max_min_transform_block_size + sps->log2_min_tb_size; + + if (sps->log2_min_cb_size < 3 || sps->log2_min_cb_size > 30) { + pr_err("Invalid value %d for log2_min_cb_size", sps->log2_min_cb_size); + return -1; + } + + if (sps->log2_diff_max_min_coding_block_size > 30) { + pr_err("Invalid value %d for log2_diff_max_min_coding_block_size", sps->log2_diff_max_min_coding_block_size); + return -1; + } + + if (sps->log2_min_tb_size >= sps->log2_min_cb_size || sps->log2_min_tb_size < 2) { + pr_err("Invalid value for log2_min_tb_size"); + return -1; + } + + if (log2_diff_max_min_transform_block_size < 0 || log2_diff_max_min_transform_block_size > 30) { + pr_err("Invalid value %d for log2_diff_max_min_transform_block_size", log2_diff_max_min_transform_block_size); + return -1; + } + + sps->max_transform_hierarchy_depth_inter = get_ue_golomb_long(gb); + sps->max_transform_hierarchy_depth_intra = get_ue_golomb_long(gb); + + sps->scaling_list_enable_flag = get_bits1(gb); + if (sps->scaling_list_enable_flag) { + set_default_scaling_list_data(&sps->scaling_list); + + if (get_bits1(gb)) { + ret = scaling_list_data(gb, &sps->scaling_list, sps); + if (ret < 0) + return ret; + } + } + + sps->amp_enabled_flag = get_bits1(gb); + sps->sao_enabled = get_bits1(gb); + + sps->pcm_enabled_flag = get_bits1(gb); + if (sps->pcm_enabled_flag) { + sps->pcm.bit_depth = get_bits(gb, 4) + 1; + sps->pcm.bit_depth_chroma = get_bits(gb, 4) + 1; + sps->pcm.log2_min_pcm_cb_size = get_ue_golomb_long(gb) + 3; + sps->pcm.log2_max_pcm_cb_size = sps->pcm.log2_min_pcm_cb_size + + get_ue_golomb_long(gb); + if (FFMAX(sps->pcm.bit_depth, sps->pcm.bit_depth_chroma) > sps->bit_depth) { + pr_err("PCM bit depth (%d, %d) is greater than normal bit depth (%d)\n", + sps->pcm.bit_depth, sps->pcm.bit_depth_chroma, sps->bit_depth); + return -1; + } + + sps->pcm.loop_filter_disable_flag = get_bits1(gb); + } + + sps->nb_st_rps = get_ue_golomb_long(gb); + if (sps->nb_st_rps > HEVC_MAX_SHORT_TERM_REF_PIC_SETS) { + pr_err("Too many short term RPS: %d.\n", sps->nb_st_rps); + return -1; + } + for (i = 0; i < sps->nb_st_rps; i++) { + if ((ret = ff_hevc_decode_short_term_rps(gb, &sps->st_rps[i], sps, 0)) < 0) + return ret; + } + + sps->long_term_ref_pics_present_flag = get_bits1(gb); + if (sps->long_term_ref_pics_present_flag) { + sps->num_long_term_ref_pics_sps = get_ue_golomb_long(gb); + if (sps->num_long_term_ref_pics_sps > HEVC_MAX_LONG_TERM_REF_PICS) { + pr_err("Too many long term ref pics: %d.\n", + sps->num_long_term_ref_pics_sps); + return -1; + } + for (i = 0; i < sps->num_long_term_ref_pics_sps; i++) { + sps->lt_ref_pic_poc_lsb_sps[i] = get_bits(gb, sps->log2_max_poc_lsb); + sps->used_by_curr_pic_lt_sps_flag[i] = get_bits1(gb); + } + } + + sps->sps_temporal_mvp_enabled_flag = get_bits1(gb); + sps->sps_strong_intra_smoothing_enable_flag = get_bits1(gb); + sps->vui.sar = (struct AVRational){0, 1}; + vui_present = get_bits1(gb); + if (vui_present) + decode_vui(gb, sps); + + if (get_bits1(gb)) { // sps_extension_flag + sps->sps_range_extension_flag = get_bits1(gb); + skip_bits(gb, 7); //sps_extension_7bits = get_bits(gb, 7); + if (sps->sps_range_extension_flag) { + sps->transform_skip_rotation_enabled_flag = get_bits1(gb); + sps->transform_skip_context_enabled_flag = get_bits1(gb); + sps->implicit_rdpcm_enabled_flag = get_bits1(gb); + sps->explicit_rdpcm_enabled_flag = get_bits1(gb); + sps->extended_precision_processing_flag = get_bits1(gb); + if (sps->extended_precision_processing_flag) + pr_info("extended_precision_processing_flag not yet implemented\n"); + + sps->intra_smoothing_disabled_flag = get_bits1(gb); + sps->high_precision_offsets_enabled_flag = get_bits1(gb); + if (sps->high_precision_offsets_enabled_flag) + pr_info("high_precision_offsets_enabled_flag not yet implemented\n"); + + sps->persistent_rice_adaptation_enabled_flag = get_bits1(gb); + sps->cabac_bypass_alignment_enabled_flag = get_bits1(gb); + if (sps->cabac_bypass_alignment_enabled_flag) + pr_info("cabac_bypass_alignment_enabled_flag not yet implemented\n"); + } + } + + ow = &sps->output_window; + if (ow->left_offset >= INT_MAX - ow->right_offset || + ow->top_offset >= INT_MAX - ow->bottom_offset || + ow->left_offset + ow->right_offset >= sps->width || + ow->top_offset + ow->bottom_offset >= sps->height) { + pr_err("Invalid cropping offsets: %u/%u/%u/%u\n", + ow->left_offset, ow->right_offset, ow->top_offset, ow->bottom_offset); + return -1; + } + + // Inferred parameters + sps->log2_ctb_size = sps->log2_min_cb_size + + sps->log2_diff_max_min_coding_block_size; + sps->log2_min_pu_size = sps->log2_min_cb_size - 1; + + if (sps->log2_ctb_size > HEVC_MAX_LOG2_CTB_SIZE) { + pr_err("CTB size out of range: 2^%d\n", sps->log2_ctb_size); + return -1; + } + if (sps->log2_ctb_size < 4) { + pr_err("log2_ctb_size %d differs from the bounds of any known profile\n", sps->log2_ctb_size); + pr_err("log2_ctb_size %d", sps->log2_ctb_size); + return -1; + } + + sps->ctb_width = (sps->width + (1 << sps->log2_ctb_size) - 1) >> sps->log2_ctb_size; + sps->ctb_height = (sps->height + (1 << sps->log2_ctb_size) - 1) >> sps->log2_ctb_size; + sps->ctb_size = sps->ctb_width * sps->ctb_height; + + sps->min_cb_width = sps->width >> sps->log2_min_cb_size; + sps->min_cb_height = sps->height >> sps->log2_min_cb_size; + sps->min_tb_width = sps->width >> sps->log2_min_tb_size; + sps->min_tb_height = sps->height >> sps->log2_min_tb_size; + sps->min_pu_width = sps->width >> sps->log2_min_pu_size; + sps->min_pu_height = sps->height >> sps->log2_min_pu_size; + sps->tb_mask = (1 << (sps->log2_ctb_size - sps->log2_min_tb_size)) - 1; + sps->qp_bd_offset = 6 * (sps->bit_depth - 8); + + if (av_mod_uintp2(sps->width, sps->log2_min_cb_size) || + av_mod_uintp2(sps->height, sps->log2_min_cb_size)) { + pr_err("Invalid coded frame dimensions.\n"); + return -1; + } + + if (sps->max_transform_hierarchy_depth_inter > sps->log2_ctb_size - sps->log2_min_tb_size) { + pr_err("max_transform_hierarchy_depth_inter out of range: %d\n", + sps->max_transform_hierarchy_depth_inter); + return -1; + } + if (sps->max_transform_hierarchy_depth_intra > sps->log2_ctb_size - sps->log2_min_tb_size) { + pr_err("max_transform_hierarchy_depth_intra out of range: %d\n", + sps->max_transform_hierarchy_depth_intra); + return -1; + } + if (sps->log2_max_trafo_size > FFMIN(sps->log2_ctb_size, 5)) { + pr_err("max transform block size out of range: %d\n", + sps->log2_max_trafo_size); + return -1; + } + + if (get_bits_left(gb) < 0) { + pr_err("Overread SPS by %d bits\n", -get_bits_left(gb)); + return -1; + } + + pr_info("Parsed SPS: id %d; ref: %d, coded wxh: %dx%d, cropped wxh: %dx%d; pix_fmt: %d.\n", + sps->sps_id, sps->temporal_layer[0].num_reorder_pics, sps->width, sps->height, + sps->width - (sps->output_window.left_offset + sps->output_window.right_offset), + sps->height - (sps->output_window.top_offset + sps->output_window.bottom_offset), + sps->pix_fmt); + + return 0; +} + +const char *hevc_nal_type_name[64] = { + "TRAIL_N", // HEVC_NAL_TRAIL_N + "TRAIL_R", // HEVC_NAL_TRAIL_R + "TSA_N", // HEVC_NAL_TSA_N + "TSA_R", // HEVC_NAL_TSA_R + "STSA_N", // HEVC_NAL_STSA_N + "STSA_R", // HEVC_NAL_STSA_R + "RADL_N", // HEVC_NAL_RADL_N + "RADL_R", // HEVC_NAL_RADL_R + "RASL_N", // HEVC_NAL_RASL_N + "RASL_R", // HEVC_NAL_RASL_R + "RSV_VCL_N10", // HEVC_NAL_VCL_N10 + "RSV_VCL_R11", // HEVC_NAL_VCL_R11 + "RSV_VCL_N12", // HEVC_NAL_VCL_N12 + "RSV_VLC_R13", // HEVC_NAL_VCL_R13 + "RSV_VCL_N14", // HEVC_NAL_VCL_N14 + "RSV_VCL_R15", // HEVC_NAL_VCL_R15 + "BLA_W_LP", // HEVC_NAL_BLA_W_LP + "BLA_W_RADL", // HEVC_NAL_BLA_W_RADL + "BLA_N_LP", // HEVC_NAL_BLA_N_LP + "IDR_W_RADL", // HEVC_NAL_IDR_W_RADL + "IDR_N_LP", // HEVC_NAL_IDR_N_LP + "CRA_NUT", // HEVC_NAL_CRA_NUT + "IRAP_IRAP_VCL22", // HEVC_NAL_IRAP_VCL22 + "IRAP_IRAP_VCL23", // HEVC_NAL_IRAP_VCL23 + "RSV_VCL24", // HEVC_NAL_RSV_VCL24 + "RSV_VCL25", // HEVC_NAL_RSV_VCL25 + "RSV_VCL26", // HEVC_NAL_RSV_VCL26 + "RSV_VCL27", // HEVC_NAL_RSV_VCL27 + "RSV_VCL28", // HEVC_NAL_RSV_VCL28 + "RSV_VCL29", // HEVC_NAL_RSV_VCL29 + "RSV_VCL30", // HEVC_NAL_RSV_VCL30 + "RSV_VCL31", // HEVC_NAL_RSV_VCL31 + "VPS", // HEVC_NAL_VPS + "SPS", // HEVC_NAL_SPS + "PPS", // HEVC_NAL_PPS + "AUD", // HEVC_NAL_AUD + "EOS_NUT", // HEVC_NAL_EOS_NUT + "EOB_NUT", // HEVC_NAL_EOB_NUT + "FD_NUT", // HEVC_NAL_FD_NUT + "SEI_PREFIX", // HEVC_NAL_SEI_PREFIX + "SEI_SUFFIX", // HEVC_NAL_SEI_SUFFIX + "RSV_NVCL41", // HEVC_NAL_RSV_NVCL41 + "RSV_NVCL42", // HEVC_NAL_RSV_NVCL42 + "RSV_NVCL43", // HEVC_NAL_RSV_NVCL43 + "RSV_NVCL44", // HEVC_NAL_RSV_NVCL44 + "RSV_NVCL45", // HEVC_NAL_RSV_NVCL45 + "RSV_NVCL46", // HEVC_NAL_RSV_NVCL46 + "RSV_NVCL47", // HEVC_NAL_RSV_NVCL47 + "UNSPEC48", // HEVC_NAL_UNSPEC48 + "UNSPEC49", // HEVC_NAL_UNSPEC49 + "UNSPEC50", // HEVC_NAL_UNSPEC50 + "UNSPEC51", // HEVC_NAL_UNSPEC51 + "UNSPEC52", // HEVC_NAL_UNSPEC52 + "UNSPEC53", // HEVC_NAL_UNSPEC53 + "UNSPEC54", // HEVC_NAL_UNSPEC54 + "UNSPEC55", // HEVC_NAL_UNSPEC55 + "UNSPEC56", // HEVC_NAL_UNSPEC56 + "UNSPEC57", // HEVC_NAL_UNSPEC57 + "UNSPEC58", // HEVC_NAL_UNSPEC58 + "UNSPEC59", // HEVC_NAL_UNSPEC59 + "UNSPEC60", // HEVC_NAL_UNSPEC60 + "UNSPEC61", // HEVC_NAL_UNSPEC61 + "UNSPEC62", // HEVC_NAL_UNSPEC62 + "UNSPEC63", // HEVC_NAL_UNSPEC63 +}; + +static const char *hevc_nal_unit_name(int nal_type) +{ + return hevc_nal_type_name[nal_type]; +} + +/** +* Parse NAL units of found picture and decode some basic information. +* +* @param s parser context. +* @param avctx codec context. +* @param buf buffer with field/frame data. +* @param buf_size size of the buffer. +*/ +static int decode_extradata_ps(u8 *data, int size, struct h265_param_sets *ps) +{ + int ret = 0; + struct get_bits_context gb; + u32 src_len, rbsp_size = 0; + u8 *rbsp_buf = NULL; + int nalu_pos, nuh_layer_id, temporal_id; + u32 nal_type; + u8 *p = data; + u32 len = size; + + nalu_pos = find_start_code(p, len); + if (nalu_pos < 0) + return -1; + + src_len = calc_nal_len(p + nalu_pos, size - nalu_pos); + rbsp_buf = nal_unit_extract_rbsp(p + nalu_pos, src_len, &rbsp_size); + if (rbsp_buf == NULL) + return -ENOMEM; + + ret = init_get_bits8(&gb, rbsp_buf, rbsp_size); + if (ret < 0) + goto out; + + if (get_bits1(&gb) != 0) { + pr_err("invalid data, return!\n"); + goto out; + } + + nal_type = get_bits(&gb, 6); + nuh_layer_id = get_bits(&gb, 6); + temporal_id = get_bits(&gb, 3) - 1; + if (temporal_id < 0) + goto out; + + /*pr_info("nal_unit_type: %d(%s), nuh_layer_id: %d, temporal_id: %d\n", + nal_type, hevc_nal_unit_name(nal_type), + nuh_layer_id, temporal_id);*/ + + switch (nal_type) { + case HEVC_NAL_VPS: + ret = ff_hevc_parse_vps(&gb, &ps->vps); + if (ret < 0) + goto out; + ps->vps_parsed = true; + break; + case HEVC_NAL_SPS: + ret = ff_hevc_parse_sps(&gb, &ps->sps); + if (ret < 0) + goto out; + ps->sps_parsed = true; + break; + /*case HEVC_NAL_PPS: + ret = ff_hevc_decode_nal_pps(&gb, NULL, ps); + if (ret < 0) + goto out; + ps->pps_parsed = true; + break;*/ + default: + pr_err("Unsupport parser nal type (%s).\n", + hevc_nal_unit_name(nal_type)); + break; + } + +out: + vfree(rbsp_buf); + + return 0; +} + +int h265_decode_extradata_ps(u8 *buf, int size, struct h265_param_sets *ps) +{ + int ret = 0, i = 0, j = 0; + u8 *p = buf; + int len = size; + + for (i = 4; i < size; i++) { + j = find_start_code(p, len); + if (j > 0) { + len = size - (p - buf); + ret = decode_extradata_ps(p, len, ps); + if (ret) { + pr_err("parse extra data failed. err: %d\n", ret); + return ret; + } + p += j; + } + p++; + } + + return ret; +} + diff --git a/drivers/amvdec_ports/decoder/aml_hevc_parser.h b/drivers/amvdec_ports/decoder/aml_hevc_parser.h index be21f14..267450f 100755..100644 --- a/drivers/amvdec_ports/decoder/aml_hevc_parser.h +++ b/drivers/amvdec_ports/decoder/aml_hevc_parser.h @@ -19,41 +19,48 @@ #ifndef AML_HEVC_PARSER_H #define AML_HEVC_PARSER_H -#define MAX_DPB_SIZE 16 // A.4.1 -#define MAX_REFS 16 +#include "../utils/common.h" -#define MAX_NB_THREADS 16 -#define SHIFT_CTB_WPP 2 +#define MAX_DPB_SIZE 16 // A.4.1 +#define MAX_REFS 16 + +#define MAX_NB_THREADS 16 +#define SHIFT_CTB_WPP 2 /** * 7.4.2.1 */ -#define MAX_SUB_LAYERS 7 -#define MAX_VPS_COUNT 16 -#define MAX_SPS_COUNT 32 -#define MAX_PPS_COUNT 256 -#define MAX_SHORT_TERM_RPS_COUNT 64 -#define MAX_CU_SIZE 128 +#define MAX_SUB_LAYERS 7 +#define MAX_VPS_COUNT 16 +#define MAX_SPS_COUNT 32 +#define MAX_PPS_COUNT 256 +#define MAX_SHORT_TERM_RPS_COUNT 64 +#define MAX_CU_SIZE 128 //TODO: check if this is really the maximum -#define MAX_TRANSFORM_DEPTH 5 +#define MAX_TRANSFORM_DEPTH 5 + +#define MAX_TB_SIZE 32 +#define MAX_PB_SIZE 64 +#define MAX_LOG2_CTB_SIZE 6 +#define MAX_QP 51 +#define DEFAULT_INTRA_TC_OFFSET 2 -#define MAX_TB_SIZE 32 -#define MAX_PB_SIZE 64 -#define MAX_LOG2_CTB_SIZE 6 -#define MAX_QP 51 -#define DEFAULT_INTRA_TC_OFFSET 2 +#define HEVC_CONTEXTS 183 -#define HEVC_CONTEXTS 183 +#define MRG_MAX_NUM_CANDS 5 -#define MRG_MAX_NUM_CANDS 5 +#define L0 0 +#define L1 1 -#define L0 0 -#define L1 1 +#define EPEL_EXTRA_BEFORE 1 +#define EPEL_EXTRA_AFTER 2 +#define EPEL_EXTRA 3 -#define EPEL_EXTRA_BEFORE 1 -#define EPEL_EXTRA_AFTER 2 -#define EPEL_EXTRA 3 +#define FF_PROFILE_HEVC_MAIN 1 +#define FF_PROFILE_HEVC_MAIN_10 2 +#define FF_PROFILE_HEVC_MAIN_STILL_PICTURE 3 +#define FF_PROFILE_HEVC_REXT 4 /** * Value of the luma sample at position (x, y) in the 2D array tab. @@ -273,11 +280,6 @@ struct HEVCWindow { u32 bottom_offset; }; -struct AVRational{ - int num; ///< numerator - int den; ///< denominator -}; - struct VUI { struct AVRational sar; @@ -322,35 +324,26 @@ struct VUI { }; struct PTLCommon { - u8 profile_space; - u8 tier_flag; - u8 profile_idc; - u8 profile_compatibility_flag[32]; - u8 level_idc; - u8 progressive_source_flag; - u8 interlaced_source_flag; - u8 non_packed_constraint_flag; - u8 frame_only_constraint_flag; + u8 profile_space; + u8 tier_flag; + u8 profile_idc; + u8 profile_compatibility_flag[32]; + u8 level_idc; + u8 progressive_source_flag; + u8 interlaced_source_flag; + u8 non_packed_constraint_flag; + u8 frame_only_constraint_flag; }; struct PTL { - int general_profile_space; - u8 general_tier_flag; - int general_profile_idc; - int general_profile_compatibility_flag[32]; - int general_level_idc; - - u8 sub_layer_profile_present_flag[MAX_SUB_LAYERS]; - u8 sub_layer_level_present_flag[MAX_SUB_LAYERS]; - - int sub_layer_profile_space[MAX_SUB_LAYERS]; - u8 sub_layer_tier_flag[MAX_SUB_LAYERS]; - int sub_layer_profile_idc[MAX_SUB_LAYERS]; - u8 sub_layer_profile_compatibility_flags[MAX_SUB_LAYERS][32]; - int sub_layer_level_idc[MAX_SUB_LAYERS]; + struct PTLCommon general_ptl; + struct PTLCommon sub_layer_ptl[HEVC_MAX_SUB_LAYERS]; + + u8 sub_layer_profile_present_flag[HEVC_MAX_SUB_LAYERS]; + u8 sub_layer_level_present_flag[HEVC_MAX_SUB_LAYERS]; }; -struct HEVCVPS { +struct h265_VPS_t { u8 vps_temporal_id_nesting_flag; int vps_max_layers; int vps_max_sub_layers; ///< vps_max_temporal_layers_minus1 + 1 @@ -368,9 +361,6 @@ struct HEVCVPS { u8 vps_poc_proportional_to_timing_flag; int vps_num_ticks_poc_diff_one; ///< vps_num_ticks_poc_diff_one_minus1 + 1 int vps_num_hrd_parameters; - - u8 data[4096]; - int data_size; }; struct ScalingList { @@ -380,8 +370,9 @@ struct ScalingList { u8 sl_dc[2][6]; }; -struct HEVCSPS { +struct h265_SPS_t { u8 vps_id; + u8 sps_id; int chroma_format_idc; u8 separate_colour_plane_flag; @@ -398,9 +389,9 @@ struct HEVCSPS { int max_sub_layers; struct { - int max_dec_pic_buffering; - int num_reorder_pics; - int max_latency_increase; + int max_dec_pic_buffering; + int num_reorder_pics; + int max_latency_increase; } temporal_layer[HEVC_MAX_SUB_LAYERS]; u8 temporal_id_nesting_flag; @@ -422,11 +413,11 @@ struct HEVCSPS { u8 num_long_term_ref_pics_sps; struct { - u8 bit_depth; - u8 bit_depth_chroma; - u32 log2_min_pcm_cb_size; - u32 log2_max_pcm_cb_size; - u8 loop_filter_disable_flag; + u8 bit_depth; + u8 bit_depth_chroma; + u32 log2_min_pcm_cb_size; + u32 log2_max_pcm_cb_size; + u8 loop_filter_disable_flag; } pcm; u8 sps_temporal_mvp_enabled_flag; u8 sps_strong_intra_smoothing_enable_flag; @@ -441,13 +432,16 @@ struct HEVCSPS { int max_transform_hierarchy_depth_inter; int max_transform_hierarchy_depth_intra; + int sps_range_extension_flag; int transform_skip_rotation_enabled_flag; int transform_skip_context_enabled_flag; int implicit_rdpcm_enabled_flag; int explicit_rdpcm_enabled_flag; + int extended_precision_processing_flag; int intra_smoothing_disabled_flag; int high_precision_offsets_enabled_flag; int persistent_rice_adaptation_enabled_flag; + int cabac_bypass_alignment_enabled_flag; ///< coded frame dimension in various units int width; @@ -472,7 +466,7 @@ struct HEVCSPS { int data_size; }; -struct HEVCPPS { +struct h265_PPS_t { u32 sps_id; ///< seq_parameter_set_id u8 sign_data_hiding_flag; @@ -544,20 +538,19 @@ struct HEVCPPS { int *tile_pos_rs; ///< TilePosRS int *min_tb_addr_zs; ///< MinTbAddrZS int *min_tb_addr_zs_tab;///< MinTbAddrZS - - u8 data[4096]; - int data_size; }; -struct HEVCParamSets { +struct h265_param_sets { bool vps_parsed; bool sps_parsed; bool pps_parsed; /* currently active parameter sets */ - struct HEVCVPS vps; - struct HEVCSPS sps; - struct HEVCPPS pps; + struct h265_VPS_t vps; + struct h265_SPS_t sps; + struct h265_PPS_t pps; }; +int h265_decode_extradata_ps(u8 *data, int size, struct h265_param_sets *ps); + #endif /* AML_HEVC_PARSER_H */ diff --git a/drivers/amvdec_ports/decoder/aml_mjpeg_parser.c b/drivers/amvdec_ports/decoder/aml_mjpeg_parser.c new file mode 100644 index 0000000..1d9d94b --- a/dev/null +++ b/drivers/amvdec_ports/decoder/aml_mjpeg_parser.c @@ -0,0 +1,397 @@ +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/vmalloc.h> +#include <linux/mm.h> +#include <linux/string.h> + +#include "aml_mjpeg_parser.h" +#include "../utils/get_bits.h" +#include "../utils/put_bits.h" +#include "../utils/golomb.h" +#include "../utils/common.h" +#include "utils.h" + +/* return the 8 bit start code value and update the search +state. Return -1 if no start code found */ +static int find_marker(const u8 **pbuf_ptr, const u8 *buf_end) +{ + const u8 *buf_ptr; + u32 v, v2; + int val; + int skipped = 0; + + buf_ptr = *pbuf_ptr; + while (buf_end - buf_ptr > 1) { + v = *buf_ptr++; + v2 = *buf_ptr; + if ((v == 0xff) && (v2 >= 0xc0) && (v2 <= 0xfe) && buf_ptr < buf_end) { + val = *buf_ptr++; + goto found; + } + skipped++; + } + buf_ptr = buf_end; + val = -1; +found: + pr_info("find_marker skipped %d bytes\n", skipped); + *pbuf_ptr = buf_ptr; + + return val; +} + +int ff_mjpeg_find_marker(struct MJpegDecodeContext *s, + const u8 **buf_ptr, const u8 *buf_end, + const u8 **unescaped_buf_ptr, + int *unescaped_buf_size) +{ + int start_code; + + start_code = find_marker(buf_ptr, buf_end); + + /* unescape buffer of SOS, use special treatment for JPEG-LS */ + if (start_code == SOS && !s->ls) { + const u8 *src = *buf_ptr; + const u8 *ptr = src; + u8 *dst = s->buffer; + + #define copy_data_segment(skip) do { \ + int length = (ptr - src) - (skip); \ + if (length > 0) { \ + memcpy(dst, src, length); \ + dst += length; \ + src = ptr; \ + } \ + } while (0) + + + while (ptr < buf_end) { + u8 x = *(ptr++); + + if (x == 0xff) { + int skip = 0; + while (ptr < buf_end && x == 0xff) { + x = *(ptr++); + skip++; + } + + /* 0xFF, 0xFF, ... */ + if (skip > 1) { + copy_data_segment(skip); + + /* decrement src as it is equal to ptr after the + * copy_data_segment macro and we might want to + * copy the current value of x later on */ + src--; + } + + if (x < 0xd0 || x > 0xd7) { + copy_data_segment(1); + if (x) + break; + } + } + if (src < ptr) + copy_data_segment(0); + } + #undef copy_data_segment + + *unescaped_buf_ptr = s->buffer; + *unescaped_buf_size = dst - s->buffer; + memset(s->buffer + *unescaped_buf_size, 0, + AV_INPUT_BUFFER_PADDING_SIZE); + + pr_info("escaping removed %d bytes\n", + (int)((buf_end - *buf_ptr) - (dst - s->buffer))); + } else if (start_code == SOS && s->ls) { + const u8 *src = *buf_ptr; + u8 *dst = s->buffer; + int bit_count = 0; + int t = 0, b = 0; + struct put_bits_context pb; + + /* find marker */ + while (src + t < buf_end) { + u8 x = src[t++]; + if (x == 0xff) { + while ((src + t < buf_end) && x == 0xff) + x = src[t++]; + if (x & 0x80) { + t -= FFMIN(2, t); + break; + } + } + } + bit_count = t * 8; + init_put_bits(&pb, dst, t); + + /* unescape bitstream */ + while (b < t) { + u8 x = src[b++]; + put_bits(&pb, 8, x); + if (x == 0xFF && b < t) { + x = src[b++]; + if (x & 0x80) { + pr_err("Invalid escape sequence\n"); + x &= 0x7f; + } + put_bits(&pb, 7, x); + bit_count--; + } + } + flush_put_bits(&pb); + + *unescaped_buf_ptr = dst; + *unescaped_buf_size = (bit_count + 7) >> 3; + memset(s->buffer + *unescaped_buf_size, 0, + AV_INPUT_BUFFER_PADDING_SIZE); + } else { + *unescaped_buf_ptr = *buf_ptr; + *unescaped_buf_size = buf_end - *buf_ptr; + } + + return start_code; +} + + +int ff_mjpeg_decode_sof(struct MJpegDecodeContext *s) +{ + int len, nb_components, i, width, height, bits, size_change; + int h_count[MAX_COMPONENTS] = { 0 }; + int v_count[MAX_COMPONENTS] = { 0 }; + + s->cur_scan = 0; + memset(s->upscale_h, 0, sizeof(s->upscale_h)); + memset(s->upscale_v, 0, sizeof(s->upscale_v)); + + /* XXX: verify len field validity */ + len = get_bits(&s->gb, 16); + bits = get_bits(&s->gb, 8); + + if (bits > 16 || bits < 1) { + pr_err("bits %d is invalid\n", bits); + return -1; + } + + height = get_bits(&s->gb, 16); + width = get_bits(&s->gb, 16); + + pr_info("sof0: picture: %dx%d\n", width, height); + + nb_components = get_bits(&s->gb, 8); + if (nb_components <= 0 || + nb_components > MAX_COMPONENTS) + return -1; + + s->nb_components = nb_components; + s->h_max = 1; + s->v_max = 1; + for (i = 0; i < nb_components; i++) { + /* component id */ + s->component_id[i] = get_bits(&s->gb, 8) - 1; + h_count[i] = get_bits(&s->gb, 4); + v_count[i] = get_bits(&s->gb, 4); + /* compute hmax and vmax (only used in interleaved case) */ + if (h_count[i] > s->h_max) + s->h_max = h_count[i]; + if (v_count[i] > s->v_max) + s->v_max = v_count[i]; + s->quant_index[i] = get_bits(&s->gb, 8); + if (s->quant_index[i] >= 4) { + pr_err("quant_index is invalid\n"); + return -1; + } + if (!h_count[i] || !v_count[i]) { + pr_err("Invalid sampling factor in component %d %d:%d\n", + i, h_count[i], v_count[i]); + return -1; + } + + pr_info("component %d %d:%d id: %d quant:%d\n", + i, h_count[i], v_count[i], + s->component_id[i], s->quant_index[i]); + } + if (nb_components == 4 + && s->component_id[0] == 'C' - 1 + && s->component_id[1] == 'M' - 1 + && s->component_id[2] == 'Y' - 1 + && s->component_id[3] == 'K' - 1) + s->adobe_transform = 0; + + /* if different size, realloc/alloc picture */ + if (width != s->width || height != s->height || bits != s->bits || + memcmp(s->h_count, h_count, sizeof(h_count)) || + memcmp(s->v_count, v_count, sizeof(v_count))) { + size_change = 1; + + s->width = width; + s->height = height; + s->bits = bits; + memcpy(s->h_count, h_count, sizeof(h_count)); + memcpy(s->v_count, v_count, sizeof(v_count)); + s->interlaced = 0; + s->got_picture = 0; + } else { + size_change = 0; + } + + return 0; +} + +static int ff_mjpeg_decode_frame(u8 *buf, int buf_size, struct MJpegDecodeContext *s) +{ + const u8 *buf_end, *buf_ptr; + const u8 *unescaped_buf_ptr; + int unescaped_buf_size; + int start_code; + int ret = 0; + + buf_ptr = buf; + buf_end = buf + buf_size; + while (buf_ptr < buf_end) { + /* find start next marker */ + start_code = ff_mjpeg_find_marker(s, &buf_ptr, buf_end, + &unescaped_buf_ptr, + &unescaped_buf_size); + /* EOF */ + if (start_code < 0) { + break; + } else if (unescaped_buf_size > INT_MAX / 8) { + pr_err("MJPEG packet 0x%x too big (%d/%d), corrupt data?\n", + start_code, unescaped_buf_size, buf_size); + return -1; + } + pr_info("marker=%x avail_size_in_buf=%d\n", + start_code, (int)(buf_end - buf_ptr)); + + ret = init_get_bits8(&s->gb, unescaped_buf_ptr, unescaped_buf_size); + if (ret < 0) { + pr_err("invalid buffer\n"); + goto fail; + } + + s->start_code = start_code; + pr_info("startcode: %X\n", start_code); + + switch (start_code) { + case SOF0: + case SOF1: + case SOF2: + case SOF3: + case SOF48: + case SOI: + case SOS: + case EOI: + break; + default: + goto skip; + } + + switch (start_code) { + case SOI: + s->restart_interval = 0; + s->restart_count = 0; + s->raw_image_buffer = buf_ptr; + s->raw_image_buffer_size = buf_end - buf_ptr; + /* nothing to do on SOI */ + break; + case SOF0: + case SOF1: + if (start_code == SOF0) + s->profile = FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT; + else + s->profile = FF_PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT; + s->lossless = 0; + s->ls = 0; + s->progressive = 0; + if ((ret = ff_mjpeg_decode_sof(s)) < 0) + goto fail; + break; + case SOF2: + s->profile = FF_PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT; + s->lossless = 0; + s->ls = 0; + s->progressive = 1; + if ((ret = ff_mjpeg_decode_sof(s)) < 0) + goto fail; + break; + case SOF3: + s->profile = FF_PROFILE_MJPEG_HUFFMAN_LOSSLESS; + s->properties |= FF_CODEC_PROPERTY_LOSSLESS; + s->lossless = 1; + s->ls = 0; + s->progressive = 0; + if ((ret = ff_mjpeg_decode_sof(s)) < 0) + goto fail; + break; + case SOF48: + s->profile = FF_PROFILE_MJPEG_JPEG_LS; + s->properties |= FF_CODEC_PROPERTY_LOSSLESS; + s->lossless = 1; + s->ls = 1; + s->progressive = 0; + if ((ret = ff_mjpeg_decode_sof(s)) < 0) + goto fail; + break; + case EOI: + goto the_end; + case DHT: + case LSE: + case SOS: + case DRI: + case SOF5: + case SOF6: + case SOF7: + case SOF9: + case SOF10: + case SOF11: + case SOF13: + case SOF14: + case SOF15: + case JPG: + pr_err("mjpeg: unsupported coding type (%x)\n", start_code); + break; + } +skip: + /* eof process start code */ + buf_ptr += (get_bits_count(&s->gb) + 7) / 8; + pr_info("marker parser used %d bytes (%d bits)\n", + (get_bits_count(&s->gb) + 7) / 8, get_bits_count(&s->gb)); + } + + pr_err("No JPEG data found in image\n"); + return -1; +fail: + s->got_picture = 0; + return ret; +the_end: + pr_info("decode frame unused %d bytes\n", (int)(buf_end - buf_ptr)); + + return 0; +} + +int mjpeg_decode_extradata_ps(u8 *buf, int size, struct mjpeg_param_sets *ps) +{ + int ret; + + ps->head_parsed = false; + + ps->dec_ps.buf_size = size; + ps->dec_ps.buffer = vzalloc(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!ps->dec_ps.buffer) + return -1; + + ret = ff_mjpeg_decode_frame(buf, size, &ps->dec_ps); + if (ret) { + pr_err("parse extra data failed. err: %d\n", ret); + vfree(ps->dec_ps.buffer); + return ret; + } + + if (ps->dec_ps.width && ps->dec_ps.height) + ps->head_parsed = true; + + vfree(ps->dec_ps.buffer); + + return 0; +} + diff --git a/drivers/amvdec_ports/decoder/aml_mjpeg_parser.h b/drivers/amvdec_ports/decoder/aml_mjpeg_parser.h new file mode 100644 index 0000000..20fdbbc --- a/dev/null +++ b/drivers/amvdec_ports/decoder/aml_mjpeg_parser.h @@ -0,0 +1,163 @@ +#ifndef AML_MPEG12_PARSER_H +#define AML_MPEG12_PARSER_H + +#include "../utils/pixfmt.h" +#include "../utils/common.h" +#include "../utils/get_bits.h" +#include "../utils/put_bits.h" + +#define FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT 0xc0 +#define FF_PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT 0xc1 +#define FF_PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT 0xc2 +#define FF_PROFILE_MJPEG_HUFFMAN_LOSSLESS 0xc3 +#define FF_PROFILE_MJPEG_JPEG_LS 0xf7 + +#define FF_CODEC_PROPERTY_LOSSLESS 0x00000001 +#define FF_CODEC_PROPERTY_CLOSED_CAPTIONS 0x00000002 + +#define MAX_COMPONENTS 4 + +/* JPEG marker codes */ +enum JpegMarker { + /* start of frame */ + SOF0 = 0xc0, /* baseline */ + SOF1 = 0xc1, /* extended sequential, huffman */ + SOF2 = 0xc2, /* progressive, huffman */ + SOF3 = 0xc3, /* lossless, huffman */ + + SOF5 = 0xc5, /* differential sequential, huffman */ + SOF6 = 0xc6, /* differential progressive, huffman */ + SOF7 = 0xc7, /* differential lossless, huffman */ + JPG = 0xc8, /* reserved for JPEG extension */ + SOF9 = 0xc9, /* extended sequential, arithmetic */ + SOF10 = 0xca, /* progressive, arithmetic */ + SOF11 = 0xcb, /* lossless, arithmetic */ + + SOF13 = 0xcd, /* differential sequential, arithmetic */ + SOF14 = 0xce, /* differential progressive, arithmetic */ + SOF15 = 0xcf, /* differential lossless, arithmetic */ + + DHT = 0xc4, /* define huffman tables */ + + DAC = 0xcc, /* define arithmetic-coding conditioning */ + + /* restart with modulo 8 count "m" */ + RST0 = 0xd0, + RST1 = 0xd1, + RST2 = 0xd2, + RST3 = 0xd3, + RST4 = 0xd4, + RST5 = 0xd5, + RST6 = 0xd6, + RST7 = 0xd7, + + SOI = 0xd8, /* start of image */ + EOI = 0xd9, /* end of image */ + SOS = 0xda, /* start of scan */ + DQT = 0xdb, /* define quantization tables */ + DNL = 0xdc, /* define number of lines */ + DRI = 0xdd, /* define restart interval */ + DHP = 0xde, /* define hierarchical progression */ + EXP = 0xdf, /* expand reference components */ + + APP0 = 0xe0, + APP1 = 0xe1, + APP2 = 0xe2, + APP3 = 0xe3, + APP4 = 0xe4, + APP5 = 0xe5, + APP6 = 0xe6, + APP7 = 0xe7, + APP8 = 0xe8, + APP9 = 0xe9, + APP10 = 0xea, + APP11 = 0xeb, + APP12 = 0xec, + APP13 = 0xed, + APP14 = 0xee, + APP15 = 0xef, + + JPG0 = 0xf0, + JPG1 = 0xf1, + JPG2 = 0xf2, + JPG3 = 0xf3, + JPG4 = 0xf4, + JPG5 = 0xf5, + JPG6 = 0xf6, + SOF48 = 0xf7, ///< JPEG-LS + LSE = 0xf8, ///< JPEG-LS extension parameters + JPG9 = 0xf9, + JPG10 = 0xfa, + JPG11 = 0xfb, + JPG12 = 0xfc, + JPG13 = 0xfd, + + COM = 0xfe, /* comment */ + + TEM = 0x01, /* temporary private use for arithmetic coding */ + + /* 0x02 -> 0xbf reserved */ +}; + +struct VLC { + int bits; + short (*table)[2]; ///< code, bits + int table_size, table_allocated; +}; + +struct MJpegDecodeContext { + struct get_bits_context gb; + int buf_size; + + int start_code; /* current start code */ + int buffer_size; + u8 *buffer; + + u16 quant_matrixes[4][64]; + struct VLC vlcs[3][4]; + int qscale[4]; ///< quantizer scale calculated from quant_matrixes + + int first_picture; /* true if decoding first picture */ + int interlaced; /* true if interlaced */ + int bottom_field; /* true if bottom field */ + int lossless; + int ls; + int progressive; + u8 upscale_h[4]; + u8 upscale_v[4]; + int bits; /* bits per component */ + int adobe_transform; + + int width, height; + int mb_width, mb_height; + int nb_components; + int block_stride[MAX_COMPONENTS]; + int component_id[MAX_COMPONENTS]; + int h_count[MAX_COMPONENTS]; /* horizontal and vertical count for each component */ + int v_count[MAX_COMPONENTS]; + int h_scount[MAX_COMPONENTS]; + int v_scount[MAX_COMPONENTS]; + int h_max, v_max; /* maximum h and v counts */ + int quant_index[4]; /* quant table index for each component */ + int got_picture; ///< we found a SOF and picture is valid, too. + int restart_interval; + int restart_count; + int cur_scan; /* current scan, used by JPEG-LS */ + + // Raw stream data for hwaccel use. + const u8 *raw_image_buffer; + int raw_image_buffer_size; + + int profile; + u32 properties; +}; + +struct mjpeg_param_sets { + bool head_parsed; + /* currently active parameter sets */ + struct MJpegDecodeContext dec_ps; +}; + +int mjpeg_decode_extradata_ps(u8 *buf, int size, struct mjpeg_param_sets *ps); + +#endif diff --git a/drivers/amvdec_ports/decoder/aml_mpeg12_parser.c b/drivers/amvdec_ports/decoder/aml_mpeg12_parser.c new file mode 100644 index 0000000..748a83f --- a/dev/null +++ b/drivers/amvdec_ports/decoder/aml_mpeg12_parser.c @@ -0,0 +1,198 @@ +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/vmalloc.h> +#include <linux/mm.h> +#include <linux/string.h> + +#include "aml_mpeg12_parser.h" +#include "../utils/get_bits.h" +#include "../utils/put_bits.h" +#include "../utils/golomb.h" +#include "../utils/common.h" +#include "utils.h" + +const struct AVRational ff_mpeg12_frame_rate_tab[16] = { + { 0, 0}, + {24000, 1001}, + { 24, 1}, + { 25, 1}, + {30000, 1001}, + { 30, 1}, + { 50, 1}, + {60000, 1001}, + { 60, 1}, + // Xing's 15fps: (9) + { 15, 1}, + // libmpeg3's "Unofficial economy rates": (10-13) + { 5, 1}, + { 10, 1}, + { 12, 1}, + { 15, 1}, + { 0, 0}, +}; + +const u8 *avpriv_find_start_code(const u8 *p, const u8 *end, u32 *state) +{ + int i; + + if (p >= end) + return end; + + for (i = 0; i < 3; i++) { + u32 tmp = *state << 8; + *state = tmp + *(p++); + if (tmp == 0x100 || p == end) + return p; + } + + while (p < end) { + if (p[-1] > 1 ) p += 3; + else if (p[-2] ) p += 2; + else if (p[-3]|(p[-1]-1)) p++; + else { + p++; + break; + } + } + + p = FFMIN(p, end) - 4; + *state = AV_RB32(p); + + return p + 4; +} + +static void mpegvideo_extract_headers(const u8 *buf, int buf_size, + struct mpeg12_param_sets *ps) +{ + struct MpvParseContext *pc = &ps->dec_ps; + const u8 *buf_end = buf + buf_size; + u32 start_code; + int frame_rate_index, ext_type, bytes_left; + int frame_rate_ext_n, frame_rate_ext_d; + int top_field_first, repeat_first_field, progressive_frame; + int horiz_size_ext, vert_size_ext, bit_rate_ext; + int bit_rate = 0; + int vbv_delay = 0; + int chroma_format; + enum AVPixelFormat pix_fmt = AV_PIX_FMT_NONE; + //FIXME replace the crap with get_bits() + pc->repeat_pict = 0; + + while (buf < buf_end) { + start_code= -1; + buf= avpriv_find_start_code(buf, buf_end, &start_code); + bytes_left = buf_end - buf; + switch (start_code) { + case PICTURE_START_CODE: + if (bytes_left >= 2) { + pc->pict_type = (buf[1] >> 3) & 7; + if (bytes_left >= 4) + vbv_delay = ((buf[1] & 0x07) << 13) | (buf[2] << 5) | (buf[3] >> 3); + } + break; + case SEQ_START_CODE: + if (bytes_left >= 7) { + pc->width = (buf[0] << 4) | (buf[1] >> 4); + pc->height = ((buf[1] & 0x0f) << 8) | buf[2]; + + pix_fmt = AV_PIX_FMT_YUV420P; + frame_rate_index = buf[3] & 0xf; + pc->frame_rate = ff_mpeg12_frame_rate_tab[frame_rate_index]; + bit_rate = (buf[4]<<10) | (buf[5]<<2) | (buf[6]>>6); + pc->ticks_per_frame = 1; + } + break; + case EXT_START_CODE: + if (bytes_left >= 1) { + ext_type = (buf[0] >> 4); + switch (ext_type) { + case 0x1: /* sequence extension */ + if (bytes_left >= 6) { + horiz_size_ext = ((buf[1] & 1) << 1) | (buf[2] >> 7); + vert_size_ext = (buf[2] >> 5) & 3; + bit_rate_ext = ((buf[2] & 0x1F)<<7) | (buf[3]>>1); + frame_rate_ext_n = (buf[5] >> 5) & 3; + frame_rate_ext_d = (buf[5] & 0x1f); + pc->progressive_sequence = buf[1] & (1 << 3); + pc->has_b_frames= !(buf[5] >> 7); + + chroma_format = (buf[1] >> 1) & 3; + switch (chroma_format) { + case 1: pix_fmt = AV_PIX_FMT_YUV420P; break; + case 2: pix_fmt = AV_PIX_FMT_YUV422P; break; + case 3: pix_fmt = AV_PIX_FMT_YUV444P; break; + } + + pc->width = (pc->width & 0xFFF) | (horiz_size_ext << 12); + pc->height = (pc->height& 0xFFF) | ( vert_size_ext << 12); + bit_rate = (bit_rate&0x3FFFF) | (bit_rate_ext << 18); + //if(did_set_size) + //set_dim_ret = ff_set_dimensions(avctx, pc->width, pc->height); + pc->framerate.num = pc->frame_rate.num * (frame_rate_ext_n + 1); + pc->framerate.den = pc->frame_rate.den * (frame_rate_ext_d + 1); + pc->ticks_per_frame = 2; + } + break; + case 0x8: /* picture coding extension */ + if (bytes_left >= 5) { + top_field_first = buf[3] & (1 << 7); + repeat_first_field = buf[3] & (1 << 1); + progressive_frame = buf[4] & (1 << 7); + + /* check if we must repeat the frame */ + pc->repeat_pict = 1; + if (repeat_first_field) { + if (pc->progressive_sequence) { + if (top_field_first) + pc->repeat_pict = 5; + else + pc->repeat_pict = 3; + } else if (progressive_frame) { + pc->repeat_pict = 2; + } + } + + if (!pc->progressive_sequence && !progressive_frame) { + if (top_field_first) + pc->field_order = AV_FIELD_TT; + else + pc->field_order = AV_FIELD_BB; + } else + pc->field_order = AV_FIELD_PROGRESSIVE; + } + break; + } + } + break; + case -1: + goto the_end; + default: + /* we stop parsing when we encounter a slice. It ensures + that this function takes a negligible amount of time */ + if (start_code >= SLICE_MIN_START_CODE && + start_code <= SLICE_MAX_START_CODE) + goto the_end; + break; + } + } +the_end: + + if (pix_fmt != AV_PIX_FMT_NONE) { + pc->format = pix_fmt; + pc->coded_width = ALIGN(pc->width, 16); + pc->coded_height = ALIGN(pc->height, 16); + } +} + +int mpeg12_decode_extradata_ps(u8 *buf, int size, struct mpeg12_param_sets *ps) +{ + ps->head_parsed = false; + + mpegvideo_extract_headers(buf, size, ps); + + if (ps->dec_ps.width && ps->dec_ps.height) + ps->head_parsed = true; + + return 0; +} + diff --git a/drivers/amvdec_ports/decoder/aml_mpeg12_parser.h b/drivers/amvdec_ports/decoder/aml_mpeg12_parser.h new file mode 100644 index 0000000..de1292d --- a/dev/null +++ b/drivers/amvdec_ports/decoder/aml_mpeg12_parser.h @@ -0,0 +1,74 @@ +#ifndef AML_MPEG12_PARSER_H +#define AML_MPEG12_PARSER_H + +#include "../utils/pixfmt.h" +#include "../utils/common.h" + +/* Start codes. */ +#define SEQ_END_CODE 0x000001b7 +#define SEQ_START_CODE 0x000001b3 +#define GOP_START_CODE 0x000001b8 +#define PICTURE_START_CODE 0x00000100 +#define SLICE_MIN_START_CODE 0x00000101 +#define SLICE_MAX_START_CODE 0x000001af +#define EXT_START_CODE 0x000001b5 +#define USER_START_CODE 0x000001b2 +#define SLICE_START_CODE 0x000001b7 + +enum AVFieldOrder { + AV_FIELD_UNKNOWN, + AV_FIELD_PROGRESSIVE, + AV_FIELD_TT, //< Top coded_first, top displayed first + AV_FIELD_BB, //< Bottom coded first, bottom displayed first + AV_FIELD_TB, //< Top coded first, bottom displayed first + AV_FIELD_BT, //< Bottom coded first, top displayed first +}; + +struct MpvParseContext { + struct AVRational frame_rate; + int progressive_sequence; + int width, height; + + int repeat_pict; /* XXX: Put it back in AVCodecContext. */ + int pict_type; /* XXX: Put it back in AVCodecContext. */ + enum AVFieldOrder field_order; + int format; + /** + * Dimensions of the coded video. + */ + int coded_width; + int coded_height; + /** + * For some codecs, the time base is closer to the field rate than the frame rate. + * Most notably, H.264 and MPEG-2 specify time_base as half of frame duration + * if no telecine is used ... + * + * Set to time_base ticks per frame. Default 1, e.g., H.264/MPEG-2 set it to 2. + */ + int ticks_per_frame; + /** + * Size of the frame reordering buffer in the decoder. + * For MPEG-2 it is 1 IPB or 0 low delay IP. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int has_b_frames; + /** + * - decoding: For codecs that store a framerate value in the compressed + * bitstream, the decoder may export it here. { 0, 1} when + * unknown. + * - encoding: May be used to signal the framerate of CFR content to an + * encoder. + */ + struct AVRational framerate; +}; + +struct mpeg12_param_sets { + bool head_parsed; + /* currently active parameter sets */ + struct MpvParseContext dec_ps; +}; + +int mpeg12_decode_extradata_ps(u8 *buf, int size, struct mpeg12_param_sets *ps); + +#endif diff --git a/drivers/amvdec_ports/decoder/aml_mpeg4_parser.c b/drivers/amvdec_ports/decoder/aml_mpeg4_parser.c new file mode 100644 index 0000000..b16c2d1 --- a/dev/null +++ b/drivers/amvdec_ports/decoder/aml_mpeg4_parser.c @@ -0,0 +1,1233 @@ +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/vmalloc.h> +#include <linux/mm.h> +#include <linux/string.h> + +#include "aml_mpeg4_parser.h" +#include "../utils/get_bits.h" +#include "../utils/put_bits.h" +#include "../utils/golomb.h" +#include "../utils/common.h" +#include "utils.h" + +const u8 ff_mpeg4_dc_threshold[8]={ + 99, 13, 15, 17, 19, 21, 23, 0 +}; + +/* these matrixes will be permuted for the idct */ +const int16_t ff_mpeg4_default_intra_matrix[64] = { + 8, 17, 18, 19, 21, 23, 25, 27, + 17, 18, 19, 21, 23, 25, 27, 28, + 20, 21, 22, 23, 24, 26, 28, 30, + 21, 22, 23, 24, 26, 28, 30, 32, + 22, 23, 24, 26, 28, 30, 32, 35, + 23, 24, 26, 28, 30, 32, 35, 38, + 25, 26, 28, 30, 32, 35, 38, 41, + 27, 28, 30, 32, 35, 38, 41, 45, +}; + +const int16_t ff_mpeg4_default_non_intra_matrix[64] = { + 16, 17, 18, 19, 20, 21, 22, 23, + 17, 18, 19, 20, 21, 22, 23, 24, + 18, 19, 20, 21, 22, 23, 24, 25, + 19, 20, 21, 22, 23, 24, 26, 27, + 20, 21, 22, 23, 25, 26, 27, 28, + 21, 22, 23, 24, 26, 27, 28, 30, + 22, 23, 24, 26, 27, 28, 30, 31, + 23, 24, 25, 27, 28, 30, 31, 33, +}; + +const struct AVRational ff_h263_pixel_aspect[16] = { + { 0, 1 }, + { 1, 1 }, + { 12, 11 }, + { 10, 11 }, + { 16, 11 }, + { 40, 33 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, +}; + +/* As per spec, studio start code search isn't the same as the old type of start code */ +static void next_start_code_studio(struct get_bits_context *gb) +{ + align_get_bits(gb); + + while (get_bits_left(gb) >= 24 && show_bits_long(gb, 24) != 0x1) { + get_bits(gb, 8); + } +} + +static int read_quant_matrix_ext(struct MpegEncContext *s, struct get_bits_context *gb) +{ + int i, /*j,*/ v; + + if (get_bits1(gb)) { + if (get_bits_left(gb) < 64*8) + return -1; + /* intra_quantiser_matrix */ + for (i = 0; i < 64; i++) { + v = get_bits(gb, 8); + //j = s->idsp.idct_permutation[ff_zigzag_direct[i]]; + //s->intra_matrix[j] = v; + //s->chroma_intra_matrix[j] = v; + } + } + + if (get_bits1(gb)) { + if (get_bits_left(gb) < 64*8) + return -1; + /* non_intra_quantiser_matrix */ + for (i = 0; i < 64; i++) { + get_bits(gb, 8); + } + } + + if (get_bits1(gb)) { + if (get_bits_left(gb) < 64*8) + return -1; + /* chroma_intra_quantiser_matrix */ + for (i = 0; i < 64; i++) { + v = get_bits(gb, 8); + //j = s->idsp.idct_permutation[ff_zigzag_direct[i]]; + //s->chroma_intra_matrix[j] = v; + } + } + + if (get_bits1(gb)) { + if (get_bits_left(gb) < 64*8) + return -1; + /* chroma_non_intra_quantiser_matrix */ + for (i = 0; i < 64; i++) { + get_bits(gb, 8); + } + } + + next_start_code_studio(gb); + return 0; +} + +static void extension_and_user_data(struct MpegEncContext *s, struct get_bits_context *gb, int id) +{ + u32 startcode; + u8 extension_type; + + startcode = show_bits_long(gb, 32); + if (startcode == USER_DATA_STARTCODE || startcode == EXT_STARTCODE) { + if ((id == 2 || id == 4) && startcode == EXT_STARTCODE) { + skip_bits_long(gb, 32); + extension_type = get_bits(gb, 4); + if (extension_type == QUANT_MATRIX_EXT_ID) + read_quant_matrix_ext(s, gb); + } + } +} + + +static int decode_studio_vol_header(struct mpeg4_dec_param *ctx, struct get_bits_context *gb) +{ + struct MpegEncContext *s = &ctx->m; + int width, height; + int bits_per_raw_sample; + + // random_accessible_vol and video_object_type_indication have already + // been read by the caller decode_vol_header() + skip_bits(gb, 4); /* video_object_layer_verid */ + ctx->shape = get_bits(gb, 2); /* video_object_layer_shape */ + skip_bits(gb, 4); /* video_object_layer_shape_extension */ + skip_bits1(gb); /* progressive_sequence */ + if (ctx->shape != BIN_ONLY_SHAPE) { + ctx->rgb = get_bits1(gb); /* rgb_components */ + s->chroma_format = get_bits(gb, 2); /* chroma_format */ + if (!s->chroma_format) { + pr_err("illegal chroma format\n"); + return -1; + } + + bits_per_raw_sample = get_bits(gb, 4); /* bit_depth */ + if (bits_per_raw_sample == 10) { + if (ctx->rgb) { + ctx->pix_fmt = AV_PIX_FMT_GBRP10; + } else { + ctx->pix_fmt = s->chroma_format == CHROMA_422 ? AV_PIX_FMT_YUV422P10 : AV_PIX_FMT_YUV444P10; + } + } + else { + pr_err("MPEG-4 Studio profile bit-depth %u", bits_per_raw_sample); + return -1; + } + ctx->bits_per_raw_sample = bits_per_raw_sample; + } + if (ctx->shape == RECT_SHAPE) { + check_marker(gb, "before video_object_layer_width"); + width = get_bits(gb, 14); /* video_object_layer_width */ + check_marker(gb, "before video_object_layer_height"); + height = get_bits(gb, 14); /* video_object_layer_height */ + check_marker(gb, "after video_object_layer_height"); + + /* Do the same check as non-studio profile */ + if (width && height) { + if (s->width && s->height && + (s->width != width || s->height != height)) + s->context_reinit = 1; + s->width = width; + s->height = height; + } + } + s->aspect_ratio_info = get_bits(gb, 4); + if (s->aspect_ratio_info == FF_ASPECT_EXTENDED) { + ctx->sample_aspect_ratio.num = get_bits(gb, 8); // par_width + ctx->sample_aspect_ratio.den = get_bits(gb, 8); // par_height + } else { + ctx->sample_aspect_ratio = ff_h263_pixel_aspect[s->aspect_ratio_info]; + } + skip_bits(gb, 4); /* frame_rate_code */ + skip_bits(gb, 15); /* first_half_bit_rate */ + check_marker(gb, "after first_half_bit_rate"); + skip_bits(gb, 15); /* latter_half_bit_rate */ + check_marker(gb, "after latter_half_bit_rate"); + skip_bits(gb, 15); /* first_half_vbv_buffer_size */ + check_marker(gb, "after first_half_vbv_buffer_size"); + skip_bits(gb, 3); /* latter_half_vbv_buffer_size */ + skip_bits(gb, 11); /* first_half_vbv_buffer_size */ + check_marker(gb, "after first_half_vbv_buffer_size"); + skip_bits(gb, 15); /* latter_half_vbv_occupancy */ + check_marker(gb, "after latter_half_vbv_occupancy"); + s->low_delay = get_bits1(gb); + s->mpeg_quant = get_bits1(gb); /* mpeg2_stream */ + + next_start_code_studio(gb); + extension_and_user_data(s, gb, 2); + + return 0; +} + +static int decode_vol_header(struct mpeg4_dec_param *ctx, struct get_bits_context *gb) +{ + struct MpegEncContext *s = &ctx->m; + int width, height, vo_ver_id; + + /* vol header */ + skip_bits(gb, 1); /* random access */ + s->vo_type = get_bits(gb, 8); + + /* If we are in studio profile (per vo_type), check if its all consistent + * and if so continue pass control to decode_studio_vol_header(). + * elIf something is inconsistent, error out + * else continue with (non studio) vol header decpoding. + */ + if (s->vo_type == CORE_STUDIO_VO_TYPE || + s->vo_type == SIMPLE_STUDIO_VO_TYPE) { + if (ctx->profile != FF_PROFILE_UNKNOWN && ctx->profile != FF_PROFILE_MPEG4_SIMPLE_STUDIO) + return -1; + s->studio_profile = 1; + ctx->profile = FF_PROFILE_MPEG4_SIMPLE_STUDIO; + return decode_studio_vol_header(ctx, gb); + } else if (s->studio_profile) { + return -1; + } + + if (get_bits1(gb) != 0) { /* is_ol_id */ + vo_ver_id = get_bits(gb, 4); /* vo_ver_id */ + skip_bits(gb, 3); /* vo_priority */ + } else { + vo_ver_id = 1; + } + s->aspect_ratio_info = get_bits(gb, 4); + if (s->aspect_ratio_info == FF_ASPECT_EXTENDED) { + ctx->sample_aspect_ratio.num = get_bits(gb, 8); // par_width + ctx->sample_aspect_ratio.den = get_bits(gb, 8); // par_height + } else { + ctx->sample_aspect_ratio = ff_h263_pixel_aspect[s->aspect_ratio_info]; + } + + if ((ctx->vol_control_parameters = get_bits1(gb))) { /* vol control parameter */ + int chroma_format = get_bits(gb, 2); + if (chroma_format != CHROMA_420) + pr_err("illegal chroma format\n"); + + s->low_delay = get_bits1(gb); + if (get_bits1(gb)) { /* vbv parameters */ + get_bits(gb, 15); /* first_half_bitrate */ + check_marker(gb, "after first_half_bitrate"); + get_bits(gb, 15); /* latter_half_bitrate */ + check_marker(gb, "after latter_half_bitrate"); + get_bits(gb, 15); /* first_half_vbv_buffer_size */ + check_marker(gb, "after first_half_vbv_buffer_size"); + get_bits(gb, 3); /* latter_half_vbv_buffer_size */ + get_bits(gb, 11); /* first_half_vbv_occupancy */ + check_marker(gb, "after first_half_vbv_occupancy"); + get_bits(gb, 15); /* latter_half_vbv_occupancy */ + check_marker(gb, "after latter_half_vbv_occupancy"); + } + } else { + /* is setting low delay flag only once the smartest thing to do? + * low delay detection will not be overridden. */ + if (s->picture_number == 0) { + switch (s->vo_type) { + case SIMPLE_VO_TYPE: + case ADV_SIMPLE_VO_TYPE: + s->low_delay = 1; + break; + default: + s->low_delay = 0; + } + } + } + + ctx->shape = get_bits(gb, 2); /* vol shape */ + if (ctx->shape != RECT_SHAPE) + pr_err("only rectangular vol supported\n"); + if (ctx->shape == GRAY_SHAPE && vo_ver_id != 1) { + pr_err("Gray shape not supported\n"); + skip_bits(gb, 4); /* video_object_layer_shape_extension */ + } + + check_marker(gb, "before time_increment_resolution"); + + ctx->framerate.num = get_bits(gb, 16); + if (!ctx->framerate.num) { + pr_err("framerate==0\n"); + return -1; + } + + ctx->time_increment_bits = av_log2(ctx->framerate.num - 1) + 1; + if (ctx->time_increment_bits < 1) + ctx->time_increment_bits = 1; + + check_marker(gb, "before fixed_vop_rate"); + + if (get_bits1(gb) != 0) /* fixed_vop_rate */ + ctx->framerate.den = get_bits(gb, ctx->time_increment_bits); + else + ctx->framerate.den = 1; + + //ctx->time_base = av_inv_q(av_mul_q(ctx->framerate, (AVRational){ctx->ticks_per_frame, 1})); + + ctx->t_frame = 0; + + if (ctx->shape != BIN_ONLY_SHAPE) { + if (ctx->shape == RECT_SHAPE) { + check_marker(gb, "before width"); + width = get_bits(gb, 13); + check_marker(gb, "before height"); + height = get_bits(gb, 13); + check_marker(gb, "after height"); + if (width && height && /* they should be non zero but who knows */ + !(s->width && s->codec_tag == AV_RL32("MP4S"))) { + if (s->width && s->height && + (s->width != width || s->height != height)) + s->context_reinit = 1; + s->width = width; + s->height = height; + } + } + + s->progressive_sequence = + s->progressive_frame = get_bits1(gb) ^ 1; + s->interlaced_dct = 0; + if (!get_bits1(gb)) /* OBMC Disable */ + pr_info("MPEG-4 OBMC not supported (very likely buggy encoder)\n"); + if (vo_ver_id == 1) + ctx->vol_sprite_usage = get_bits1(gb); /* vol_sprite_usage */ + else + ctx->vol_sprite_usage = get_bits(gb, 2); /* vol_sprite_usage */ + + if (ctx->vol_sprite_usage == STATIC_SPRITE) + pr_err("Static Sprites not supported\n"); + if (ctx->vol_sprite_usage == STATIC_SPRITE || + ctx->vol_sprite_usage == GMC_SPRITE) { + if (ctx->vol_sprite_usage == STATIC_SPRITE) { + skip_bits(gb, 13); // sprite_width + check_marker(gb, "after sprite_width"); + skip_bits(gb, 13); // sprite_height + check_marker(gb, "after sprite_height"); + skip_bits(gb, 13); // sprite_left + check_marker(gb, "after sprite_left"); + skip_bits(gb, 13); // sprite_top + check_marker(gb, "after sprite_top"); + } + ctx->num_sprite_warping_points = get_bits(gb, 6); + if (ctx->num_sprite_warping_points > 3) { + pr_err("%d sprite_warping_points\n", + ctx->num_sprite_warping_points); + ctx->num_sprite_warping_points = 0; + return -1; + } + s->sprite_warping_accuracy = get_bits(gb, 2); + ctx->sprite_brightness_change = get_bits1(gb); + if (ctx->vol_sprite_usage == STATIC_SPRITE) + skip_bits1(gb); // low_latency_sprite + } + // FIXME sadct disable bit if verid!=1 && shape not rect + + if (get_bits1(gb) == 1) { /* not_8_bit */ + s->quant_precision = get_bits(gb, 4); /* quant_precision */ + if (get_bits(gb, 4) != 8) /* bits_per_pixel */ + pr_err("N-bit not supported\n"); + if (s->quant_precision != 5) + pr_err("quant precision %d\n", s->quant_precision); + if (s->quant_precision<3 || s->quant_precision>9) { + s->quant_precision = 5; + } + } else { + s->quant_precision = 5; + } + + // FIXME a bunch of grayscale shape things + + if ((s->mpeg_quant = get_bits1(gb))) { /* vol_quant_type */ + int i, v; + + //mpeg4_load_default_matrices(s); + + /* load custom intra matrix */ + if (get_bits1(gb)) { + int last = 0; + for (i = 0; i < 64; i++) { + //int j; + if (get_bits_left(gb) < 8) { + pr_err("insufficient data for custom matrix\n"); + return -1; + } + v = get_bits(gb, 8); + if (v == 0) + break; + + last = v; + //j = s->idsp.idct_permutation[ff_zigzag_direct[i]]; + //s->intra_matrix[j] = last; + //s->chroma_intra_matrix[j] = last; + } + + /* replicate last value */ + //for (; i < 64; i++) { + //int j = s->idsp.idct_permutation[ff_zigzag_direct[i]]; + //s->intra_matrix[j] = last; + //s->chroma_intra_matrix[j] = last; + //} + } + + /* load custom non intra matrix */ + if (get_bits1(gb)) { + int last = 0; + for (i = 0; i < 64; i++) { + //int j; + if (get_bits_left(gb) < 8) { + pr_err("insufficient data for custom matrix\n"); + return -1; + } + v = get_bits(gb, 8); + if (v == 0) + break; + + last = v; + //j = s->idsp.idct_permutation[ff_zigzag_direct[i]]; + //s->inter_matrix[j] = v; + //s->chroma_inter_matrix[j] = v; + } + + /* replicate last value */ + //for (; i < 64; i++) { + //int j = s->idsp.idct_permutation[ff_zigzag_direct[i]]; + //s->inter_matrix[j] = last; + //s->chroma_inter_matrix[j] = last; + //} + } + + // FIXME a bunch of grayscale shape things + } + + if (vo_ver_id != 1) + s->quarter_sample = get_bits1(gb); + else + s->quarter_sample = 0; + + if (get_bits_left(gb) < 4) { + pr_err("VOL Header truncated\n"); + return -1; + } + + if (!get_bits1(gb)) { + int pos = get_bits_count(gb); + int estimation_method = get_bits(gb, 2); + if (estimation_method < 2) { + if (!get_bits1(gb)) { + ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* opaque */ + ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* transparent */ + ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* intra_cae */ + ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* inter_cae */ + ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* no_update */ + ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* upsampling */ + } + if (!get_bits1(gb)) { + ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* intra_blocks */ + ctx->cplx_estimation_trash_p += 8 * get_bits1(gb); /* inter_blocks */ + ctx->cplx_estimation_trash_p += 8 * get_bits1(gb); /* inter4v_blocks */ + ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* not coded blocks */ + } + if (!check_marker(gb, "in complexity estimation part 1")) { + skip_bits_long(gb, pos - get_bits_count(gb)); + goto no_cplx_est; + } + if (!get_bits1(gb)) { + ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* dct_coeffs */ + ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* dct_lines */ + ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* vlc_syms */ + ctx->cplx_estimation_trash_i += 4 * get_bits1(gb); /* vlc_bits */ + } + if (!get_bits1(gb)) { + ctx->cplx_estimation_trash_p += 8 * get_bits1(gb); /* apm */ + ctx->cplx_estimation_trash_p += 8 * get_bits1(gb); /* npm */ + ctx->cplx_estimation_trash_b += 8 * get_bits1(gb); /* interpolate_mc_q */ + ctx->cplx_estimation_trash_p += 8 * get_bits1(gb); /* forwback_mc_q */ + ctx->cplx_estimation_trash_p += 8 * get_bits1(gb); /* halfpel2 */ + ctx->cplx_estimation_trash_p += 8 * get_bits1(gb); /* halfpel4 */ + } + if (!check_marker(gb, "in complexity estimation part 2")) { + skip_bits_long(gb, pos - get_bits_count(gb)); + goto no_cplx_est; + } + if (estimation_method == 1) { + ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* sadct */ + ctx->cplx_estimation_trash_p += 8 * get_bits1(gb); /* qpel */ + } + } else + pr_err("Invalid Complexity estimation method %d\n", + estimation_method); + } else { + +no_cplx_est: + ctx->cplx_estimation_trash_i = + ctx->cplx_estimation_trash_p = + ctx->cplx_estimation_trash_b = 0; + } + + ctx->resync_marker = !get_bits1(gb); /* resync_marker_disabled */ + + s->data_partitioning = get_bits1(gb); + if (s->data_partitioning) + ctx->rvlc = get_bits1(gb); + + if (vo_ver_id != 1) { + ctx->new_pred = get_bits1(gb); + if (ctx->new_pred) { + pr_err("new pred not supported\n"); + skip_bits(gb, 2); /* requested upstream message type */ + skip_bits1(gb); /* newpred segment type */ + } + if (get_bits1(gb)) // reduced_res_vop + pr_err("reduced resolution VOP not supported\n"); + } else { + ctx->new_pred = 0; + } + + ctx->scalability = get_bits1(gb); + + if (ctx->scalability) { + struct get_bits_context bak = *gb; + int h_sampling_factor_n; + int h_sampling_factor_m; + int v_sampling_factor_n; + int v_sampling_factor_m; + + skip_bits1(gb); // hierarchy_type + skip_bits(gb, 4); /* ref_layer_id */ + skip_bits1(gb); /* ref_layer_sampling_dir */ + h_sampling_factor_n = get_bits(gb, 5); + h_sampling_factor_m = get_bits(gb, 5); + v_sampling_factor_n = get_bits(gb, 5); + v_sampling_factor_m = get_bits(gb, 5); + ctx->enhancement_type = get_bits1(gb); + + if (h_sampling_factor_n == 0 || h_sampling_factor_m == 0 || + v_sampling_factor_n == 0 || v_sampling_factor_m == 0) { + /* illegal scalability header (VERY broken encoder), + * trying to workaround */ + ctx->scalability = 0; + *gb = bak; + } else + pr_err("scalability not supported\n"); + + // bin shape stuff FIXME + } + } + + if (1) { + pr_info("tb %d/%d, tincrbits:%d, qp_prec:%d, ps:%d, low_delay:%d %s%s%s%s\n", + ctx->framerate.den, ctx->framerate.num, + ctx->time_increment_bits, + s->quant_precision, + s->progressive_sequence, + s->low_delay, + ctx->scalability ? "scalability " :"" , s->quarter_sample ? "qpel " : "", + s->data_partitioning ? "partition " : "", ctx->rvlc ? "rvlc " : "" + ); + } + + return 0; +} + + +/** + * Decode the user data stuff in the header. + * Also initializes divx/xvid/lavc_version/build. + */ +static int decode_user_data(struct mpeg4_dec_param *ctx, struct get_bits_context *gb) +{ + struct MpegEncContext *s = &ctx->m; + char buf[256]; + int i; + int e; + int ver = 0, build = 0, ver2 = 0, ver3 = 0; + char last; + + for (i = 0; i < 255 && get_bits_count(gb) < gb->size_in_bits; i++) { + if (show_bits(gb, 23) == 0) + break; + buf[i] = get_bits(gb, 8); + } + buf[i] = 0; + + /* divx detection */ + e = sscanf(buf, "DivX%dBuild%d%c", &ver, &build, &last); + if (e < 2) + e = sscanf(buf, "DivX%db%d%c", &ver, &build, &last); + if (e >= 2) { + ctx->divx_version = ver; + ctx->divx_build = build; + s->divx_packed = e == 3 && last == 'p'; + } + + /* libavcodec detection */ + e = sscanf(buf, "FFmpe%*[^b]b%d", &build) + 3; + if (e != 4) + e = sscanf(buf, "FFmpeg v%d.%d.%d / libavcodec build: %d", &ver, &ver2, &ver3, &build); + if (e != 4) { + e = sscanf(buf, "Lavc%d.%d.%d", &ver, &ver2, &ver3) + 1; + if (e > 1) { + if (ver > 0xFFU || ver2 > 0xFFU || ver3 > 0xFFU) { + pr_info("Unknown Lavc version string encountered, %d.%d.%d; " + "clamping sub-version values to 8-bits.\n", + ver, ver2, ver3); + } + build = ((ver & 0xFF) << 16) + ((ver2 & 0xFF) << 8) + (ver3 & 0xFF); + } + } + if (e != 4) { + if (strcmp(buf, "ffmpeg") == 0) + ctx->lavc_build = 4600; + } + if (e == 4) + ctx->lavc_build = build; + + /* Xvid detection */ + e = sscanf(buf, "XviD%d", &build); + if (e == 1) + ctx->xvid_build = build; + + return 0; +} + + +static int mpeg4_decode_gop_header(struct MpegEncContext *s, struct get_bits_context *gb) +{ + int hours, minutes, seconds; + + if (!show_bits(gb, 23)) { + pr_err("GOP header invalid\n"); + return -1; + } + + hours = get_bits(gb, 5); + minutes = get_bits(gb, 6); + check_marker(gb, "in gop_header"); + seconds = get_bits(gb, 6); + + s->time_base = seconds + 60*(minutes + 60*hours); + + skip_bits1(gb); + skip_bits1(gb); + + return 0; +} + + +static int mpeg4_decode_profile_level(struct MpegEncContext *s, struct get_bits_context *gb, int *profile, int *level) +{ + + *profile = get_bits(gb, 4); + *level = get_bits(gb, 4); + + // for Simple profile, level 0 + if (*profile == 0 && *level == 8) { + *level = 0; + } + + return 0; +} + + +static int decode_studiovisualobject(struct mpeg4_dec_param *ctx, struct get_bits_context *gb) +{ + struct MpegEncContext *s = &ctx->m; + int visual_object_type; + + skip_bits(gb, 4); /* visual_object_verid */ + visual_object_type = get_bits(gb, 4); + if (visual_object_type != VOT_VIDEO_ID) { + pr_err("VO type %u", visual_object_type); + return -1; + } + + next_start_code_studio(gb); + extension_and_user_data(s, gb, 1); + + return 0; +} + + +static int mpeg4_decode_visual_object(struct MpegEncContext *s, struct get_bits_context *gb) +{ + int visual_object_type; + int is_visual_object_identifier = get_bits1(gb); + + if (is_visual_object_identifier) { + skip_bits(gb, 4+3); + } + visual_object_type = get_bits(gb, 4); + + if (visual_object_type == VOT_VIDEO_ID || + visual_object_type == VOT_STILL_TEXTURE_ID) { + int video_signal_type = get_bits1(gb); + if (video_signal_type) { + int video_range, color_description; + skip_bits(gb, 3); // video_format + video_range = get_bits1(gb); + color_description = get_bits1(gb); + + s->ctx->color_range = video_range ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; + + if (color_description) { + s->ctx->color_primaries = get_bits(gb, 8); + s->ctx->color_trc = get_bits(gb, 8); + s->ctx->colorspace = get_bits(gb, 8); + } + } + } + + return 0; +} + +static void decode_smpte_tc(struct mpeg4_dec_param *ctx, struct get_bits_context *gb) +{ + skip_bits(gb, 16); /* Time_code[63..48] */ + check_marker(gb, "after Time_code[63..48]"); + skip_bits(gb, 16); /* Time_code[47..32] */ + check_marker(gb, "after Time_code[47..32]"); + skip_bits(gb, 16); /* Time_code[31..16] */ + check_marker(gb, "after Time_code[31..16]"); + skip_bits(gb, 16); /* Time_code[15..0] */ + check_marker(gb, "after Time_code[15..0]"); + skip_bits(gb, 4); /* reserved_bits */ +} + +static void reset_studio_dc_predictors(struct MpegEncContext *s) +{ + /* Reset DC Predictors */ + s->last_dc[0] = + s->last_dc[1] = + s->last_dc[2] = 1 << (s->ctx->bits_per_raw_sample + s->dct_precision + s->intra_dc_precision - 1); +} + +/** + * Decode the next studio vop header. + * @return <0 if something went wrong + */ +static int decode_studio_vop_header(struct mpeg4_dec_param *ctx, struct get_bits_context *gb) +{ + struct MpegEncContext *s = &ctx->m; + + if (get_bits_left(gb) <= 32) + return 0; + + //s->decode_mb = mpeg4_decode_studio_mb; + + decode_smpte_tc(ctx, gb); + + skip_bits(gb, 10); /* temporal_reference */ + skip_bits(gb, 2); /* vop_structure */ + s->pict_type = get_bits(gb, 2) + AV_PICTURE_TYPE_I; /* vop_coding_type */ + if (get_bits1(gb)) { /* vop_coded */ + skip_bits1(gb); /* top_field_first */ + skip_bits1(gb); /* repeat_first_field */ + s->progressive_frame = get_bits1(gb) ^ 1; /* progressive_frame */ + } + + if (s->pict_type == AV_PICTURE_TYPE_I) { + if (get_bits1(gb)) + reset_studio_dc_predictors(s); + } + + if (ctx->shape != BIN_ONLY_SHAPE) { + s->alternate_scan = get_bits1(gb); + s->frame_pred_frame_dct = get_bits1(gb); + s->dct_precision = get_bits(gb, 2); + s->intra_dc_precision = get_bits(gb, 2); + s->q_scale_type = get_bits1(gb); + } + + //if (s->alternate_scan) { } + + //mpeg4_load_default_matrices(s); + + next_start_code_studio(gb); + extension_and_user_data(s, gb, 4); + + return 0; +} + +static int decode_new_pred(struct mpeg4_dec_param *ctx, struct get_bits_context *gb) +{ + int len = FFMIN(ctx->time_increment_bits + 3, 15); + + get_bits(gb, len); + if (get_bits1(gb)) + get_bits(gb, len); + check_marker(gb, "after new_pred"); + + return 0; +} + +static int decode_vop_header(struct mpeg4_dec_param *ctx, struct get_bits_context *gb) +{ + struct MpegEncContext *s = &ctx->m; + int time_incr, time_increment; + int64_t pts; + + s->mcsel = 0; + s->pict_type = get_bits(gb, 2) + AV_PICTURE_TYPE_I; /* pict type: I = 0 , P = 1 */ + if (s->pict_type == AV_PICTURE_TYPE_B && s->low_delay && + ctx->vol_control_parameters == 0) { + pr_err("low_delay flag set incorrectly, clearing it\n"); + s->low_delay = 0; + } + + s->partitioned_frame = s->data_partitioning && s->pict_type != AV_PICTURE_TYPE_B; + /*if (s->partitioned_frame) + s->decode_mb = mpeg4_decode_partitioned_mb; + else + s->decode_mb = mpeg4_decode_mb;*/ + + time_incr = 0; + while (get_bits1(gb) != 0) + time_incr++; + + check_marker(gb, "before time_increment"); + + if (ctx->time_increment_bits == 0 || + !(show_bits(gb, ctx->time_increment_bits + 1) & 1)) { + pr_info("time_increment_bits %d is invalid in relation to the current bitstream, this is likely caused by a missing VOL header\n", ctx->time_increment_bits); + + for (ctx->time_increment_bits = 1; + ctx->time_increment_bits < 16; + ctx->time_increment_bits++) { + if (s->pict_type == AV_PICTURE_TYPE_P || + (s->pict_type == AV_PICTURE_TYPE_S && + ctx->vol_sprite_usage == GMC_SPRITE)) { + if ((show_bits(gb, ctx->time_increment_bits + 6) & 0x37) == 0x30) + break; + } else if ((show_bits(gb, ctx->time_increment_bits + 5) & 0x1F) == 0x18) + break; + } + + pr_info("time_increment_bits set to %d bits, based on bitstream analysis\n", ctx->time_increment_bits); + if (ctx->framerate.num && 4*ctx->framerate.num < 1<<ctx->time_increment_bits) { + ctx->framerate.num = 1<<ctx->time_increment_bits; + //ctx->time_base = av_inv_q(av_mul_q(ctx->framerate, (AVRational){ctx->ticks_per_frame, 1})); + } + } + + if (IS_3IV1) + time_increment = get_bits1(gb); // FIXME investigate further + else + time_increment = get_bits(gb, ctx->time_increment_bits); + + if (s->pict_type != AV_PICTURE_TYPE_B) { + s->last_time_base = s->time_base; + s->time_base += time_incr; + s->time = s->time_base * (int64_t)ctx->framerate.num + time_increment; + //if (s->workaround_bugs & FF_BUG_UMP4) { } + s->pp_time = s->time - s->last_non_b_time; + s->last_non_b_time = s->time; + } else { + s->time = (s->last_time_base + time_incr) * (int64_t)ctx->framerate.num + time_increment; + s->pb_time = s->pp_time - (s->last_non_b_time - s->time); + if (s->pp_time <= s->pb_time || + s->pp_time <= s->pp_time - s->pb_time || + s->pp_time <= 0) { + /* messed up order, maybe after seeking? skipping current B-frame */ + return FRAME_SKIPPED; + } + //ff_mpeg4_init_direct_mv(s); + + if (ctx->t_frame == 0) + ctx->t_frame = s->pb_time; + if (ctx->t_frame == 0) + ctx->t_frame = 1; // 1/0 protection + s->pp_field_time = (ROUNDED_DIV(s->last_non_b_time, ctx->t_frame) - + ROUNDED_DIV(s->last_non_b_time - s->pp_time, ctx->t_frame)) * 2; + s->pb_field_time = (ROUNDED_DIV(s->time, ctx->t_frame) - + ROUNDED_DIV(s->last_non_b_time - s->pp_time, ctx->t_frame)) * 2; + if (s->pp_field_time <= s->pb_field_time || s->pb_field_time <= 1) { + s->pb_field_time = 2; + s->pp_field_time = 4; + if (!s->progressive_sequence) + return FRAME_SKIPPED; + } + } + + if (ctx->framerate.den) + pts = ROUNDED_DIV(s->time, ctx->framerate.den); + else + pts = AV_NOPTS_VALUE; + pr_info("MPEG4 PTS: %lld\n", pts); + + check_marker(gb, "before vop_coded"); + + /* vop coded */ + if (get_bits1(gb) != 1) { + if (1) + pr_err("vop not coded\n"); + return FRAME_SKIPPED; + } + if (ctx->new_pred) + decode_new_pred(ctx, gb); + + if (ctx->shape != BIN_ONLY_SHAPE && + (s->pict_type == AV_PICTURE_TYPE_P || + (s->pict_type == AV_PICTURE_TYPE_S && + ctx->vol_sprite_usage == GMC_SPRITE))) { + /* rounding type for motion estimation */ + s->no_rounding = get_bits1(gb); + } else { + s->no_rounding = 0; + } + // FIXME reduced res stuff + + if (ctx->shape != RECT_SHAPE) { + if (ctx->vol_sprite_usage != 1 || s->pict_type != AV_PICTURE_TYPE_I) { + skip_bits(gb, 13); /* width */ + check_marker(gb, "after width"); + skip_bits(gb, 13); /* height */ + check_marker(gb, "after height"); + skip_bits(gb, 13); /* hor_spat_ref */ + check_marker(gb, "after hor_spat_ref"); + skip_bits(gb, 13); /* ver_spat_ref */ + } + skip_bits1(gb); /* change_CR_disable */ + + if (get_bits1(gb) != 0) + skip_bits(gb, 8); /* constant_alpha_value */ + } + + // FIXME complexity estimation stuff + + if (ctx->shape != BIN_ONLY_SHAPE) { + skip_bits_long(gb, ctx->cplx_estimation_trash_i); + if (s->pict_type != AV_PICTURE_TYPE_I) + skip_bits_long(gb, ctx->cplx_estimation_trash_p); + if (s->pict_type == AV_PICTURE_TYPE_B) + skip_bits_long(gb, ctx->cplx_estimation_trash_b); + + if (get_bits_left(gb) < 3) { + pr_err("Header truncated\n"); + return -1; + } + ctx->intra_dc_threshold = ff_mpeg4_dc_threshold[get_bits(gb, 3)]; + if (!s->progressive_sequence) { + s->top_field_first = get_bits1(gb); + s->alternate_scan = get_bits1(gb); + } else + s->alternate_scan = 0; + } + + /*if (s->alternate_scan) { } */ + + if (s->pict_type == AV_PICTURE_TYPE_S) { + if((ctx->vol_sprite_usage == STATIC_SPRITE || + ctx->vol_sprite_usage == GMC_SPRITE)) { + //if (mpeg4_decode_sprite_trajectory(ctx, gb) < 0) + //return -1; + if (ctx->sprite_brightness_change) + pr_err("sprite_brightness_change not supported\n"); + if (ctx->vol_sprite_usage == STATIC_SPRITE) + pr_err("static sprite not supported\n"); + } else { + memset(s->sprite_offset, 0, sizeof(s->sprite_offset)); + memset(s->sprite_delta, 0, sizeof(s->sprite_delta)); + } + } + + if (ctx->shape != BIN_ONLY_SHAPE) { + s->chroma_qscale = s->qscale = get_bits(gb, s->quant_precision); + if (s->qscale == 0) { + pr_err("Error, header damaged or not MPEG-4 header (qscale=0)\n"); + return -1; // makes no sense to continue, as there is nothing left from the image then + } + + if (s->pict_type != AV_PICTURE_TYPE_I) { + s->f_code = get_bits(gb, 3); /* fcode_for */ + if (s->f_code == 0) { + pr_err("Error, header damaged or not MPEG-4 header (f_code=0)\n"); + s->f_code = 1; + return -1; // makes no sense to continue, as there is nothing left from the image then + } + } else + s->f_code = 1; + + if (s->pict_type == AV_PICTURE_TYPE_B) { + s->b_code = get_bits(gb, 3); + if (s->b_code == 0) { + pr_err("Error, header damaged or not MPEG4 header (b_code=0)\n"); + s->b_code=1; + return -1; // makes no sense to continue, as the MV decoding will break very quickly + } + } else + s->b_code = 1; + + if (1) { + pr_info("qp:%d fc:%d,%d %s size:%d pro:%d alt:%d top:%d %spel part:%d resync:%d w:%d a:%d rnd:%d vot:%d%s dc:%d ce:%d/%d/%d time:%ld tincr:%d\n", + s->qscale, s->f_code, s->b_code, + s->pict_type == AV_PICTURE_TYPE_I ? "I" : (s->pict_type == AV_PICTURE_TYPE_P ? "P" : (s->pict_type == AV_PICTURE_TYPE_B ? "B" : "S")), + gb->size_in_bits,s->progressive_sequence, s->alternate_scan, + s->top_field_first, s->quarter_sample ? "q" : "h", + s->data_partitioning, ctx->resync_marker, + ctx->num_sprite_warping_points, s->sprite_warping_accuracy, + 1 - s->no_rounding, s->vo_type, + ctx->vol_control_parameters ? " VOLC" : " ", ctx->intra_dc_threshold, + ctx->cplx_estimation_trash_i, ctx->cplx_estimation_trash_p, + ctx->cplx_estimation_trash_b, + s->time, + time_increment + ); + } + + if (!ctx->scalability) { + if (ctx->shape != RECT_SHAPE && s->pict_type != AV_PICTURE_TYPE_I) + skip_bits1(gb); // vop shape coding type + } else { + if (ctx->enhancement_type) { + int load_backward_shape = get_bits1(gb); + if (load_backward_shape) + pr_err("load backward shape isn't supported\n"); + } + skip_bits(gb, 2); // ref_select_code + } + } + /* detect buggy encoders which don't set the low_delay flag + * (divx4/xvid/opendivx). Note we cannot detect divx5 without B-frames + * easily (although it's buggy too) */ + if (s->vo_type == 0 && ctx->vol_control_parameters == 0 && + ctx->divx_version == -1 && s->picture_number == 0) { + pr_info("looks like this file was encoded with (divx4/(old)xvid/opendivx) -> forcing low_delay flag\n"); + s->low_delay = 1; + } + + s->picture_number++; // better than pic number==0 always ;) + + // FIXME add short header support + //s->y_dc_scale_table = ff_mpeg4_y_dc_scale_table; + //s->c_dc_scale_table = ff_mpeg4_c_dc_scale_table; + + return 0; +} + +/** + * Decode MPEG-4 headers. + * @return <0 if no VOP found (or a damaged one) + * FRAME_SKIPPED if a not coded VOP is found + * 0 if a VOP is found + */ +int ff_mpeg4_decode_picture_header(struct mpeg4_dec_param *ctx, struct get_bits_context *gb) +{ + struct MpegEncContext *s = &ctx->m; + + unsigned startcode, v; + int ret; + int vol = 0; + int bits_per_raw_sample = 0; + + s->ctx = ctx; + + /* search next start code */ + align_get_bits(gb); + + // If we have not switched to studio profile than we also did not switch bps + // that means something else (like a previous instance) outside set bps which + // would be inconsistant with the currect state, thus reset it + if (!s->studio_profile && bits_per_raw_sample != 8) + bits_per_raw_sample = 0; + + if (show_bits(gb, 24) == 0x575630) { + skip_bits(gb, 24); + if (get_bits(gb, 8) == 0xF0) + goto end; + } + + startcode = 0xff; + for (;;) { + if (get_bits_count(gb) >= gb->size_in_bits) { + if (gb->size_in_bits == 8) { + pr_info("frame skip %d\n", gb->size_in_bits); + return FRAME_SKIPPED; // divx bug + } else + return -1; // end of stream + } + + /* use the bits after the test */ + v = get_bits(gb, 8); + startcode = ((startcode << 8) | v) & 0xffffffff; + + if ((startcode & 0xFFFFFF00) != 0x100) + continue; // no startcode + + if (1) { //debug + pr_info("startcode: %3X \n", startcode); + if (startcode <= 0x11F) + pr_info("Video Object Start\n"); + else if (startcode <= 0x12F) + pr_info("Video Object Layer Start\n"); + else if (startcode <= 0x13F) + pr_info("Reserved\n"); + else if (startcode <= 0x15F) + pr_info("FGS bp start\n"); + else if (startcode <= 0x1AF) + pr_info("Reserved\n"); + else if (startcode == 0x1B0) + pr_info("Visual Object Seq Start\n"); + else if (startcode == 0x1B1) + pr_info("Visual Object Seq End\n"); + else if (startcode == 0x1B2) + pr_info("User Data\n"); + else if (startcode == 0x1B3) + pr_info("Group of VOP start\n"); + else if (startcode == 0x1B4) + pr_info("Video Session Error\n"); + else if (startcode == 0x1B5) + pr_info("Visual Object Start\n"); + else if (startcode == 0x1B6) + pr_info("Video Object Plane start\n"); + else if (startcode == 0x1B7) + pr_info("slice start\n"); + else if (startcode == 0x1B8) + pr_info("extension start\n"); + else if (startcode == 0x1B9) + pr_info("fgs start\n"); + else if (startcode == 0x1BA) + pr_info("FBA Object start\n"); + else if (startcode == 0x1BB) + pr_info("FBA Object Plane start\n"); + else if (startcode == 0x1BC) + pr_info("Mesh Object start\n"); + else if (startcode == 0x1BD) + pr_info("Mesh Object Plane start\n"); + else if (startcode == 0x1BE) + pr_info("Still Texture Object start\n"); + else if (startcode == 0x1BF) + pr_info("Texture Spatial Layer start\n"); + else if (startcode == 0x1C0) + pr_info("Texture SNR Layer start\n"); + else if (startcode == 0x1C1) + pr_info("Texture Tile start\n"); + else if (startcode == 0x1C2) + pr_info("Texture Shape Layer start\n"); + else if (startcode == 0x1C3) + pr_info("stuffing start\n"); + else if (startcode <= 0x1C5) + pr_info("reserved\n"); + else if (startcode <= 0x1FF) + pr_info("System start\n"); + } + + if (startcode >= 0x120 && startcode <= 0x12F) { + if (vol) { + pr_err("Ignoring multiple VOL headers\n"); + continue; + } + vol++; + if ((ret = decode_vol_header(ctx, gb)) < 0) + return ret; + } else if (startcode == USER_DATA_STARTCODE) { + decode_user_data(ctx, gb); + } else if (startcode == GOP_STARTCODE) { + mpeg4_decode_gop_header(s, gb); + } else if (startcode == VOS_STARTCODE) { + int profile, level; + mpeg4_decode_profile_level(s, gb, &profile, &level); + if (profile == FF_PROFILE_MPEG4_SIMPLE_STUDIO && + (level > 0 && level < 9)) { + s->studio_profile = 1; + next_start_code_studio(gb); + extension_and_user_data(s, gb, 0); + } else if (s->studio_profile) { + pr_err("Mixes studio and non studio profile\n"); + return -1; + } + ctx->profile = profile; + ctx->level = level; + } else if (startcode == VISUAL_OBJ_STARTCODE) { + if (s->studio_profile) { + if ((ret = decode_studiovisualobject(ctx, gb)) < 0) + return ret; + } else + mpeg4_decode_visual_object(s, gb); + } else if (startcode == VOP_STARTCODE) { + break; + } + + align_get_bits(gb); + startcode = 0xff; + } + +end: + if (s->studio_profile) { + if (!bits_per_raw_sample) { + pr_err("Missing VOL header\n"); + return -1; + } + return decode_studio_vop_header(ctx, gb); + } else + return decode_vop_header(ctx, gb); +} + +int mpeg4_decode_extradata_ps(u8 *buf, int size, struct mpeg4_param_sets *ps) +{ + int ret = 0; + struct get_bits_context gb; + + ps->head_parsed = false; + + init_get_bits8(&gb, buf, size); + + ret = ff_mpeg4_decode_picture_header(&ps->dec_ps, &gb); + if (ret < -1) { + pr_err("Failed to parse extradata\n"); + return ret; + } + + if (ps->dec_ps.m.width && ps->dec_ps.m.height) + ps->head_parsed = true; + + return 0; +} + diff --git a/drivers/amvdec_ports/decoder/aml_mpeg4_parser.h b/drivers/amvdec_ports/decoder/aml_mpeg4_parser.h new file mode 100644 index 0000000..543c631 --- a/dev/null +++ b/drivers/amvdec_ports/decoder/aml_mpeg4_parser.h @@ -0,0 +1,250 @@ +#ifndef AVCODEC_MPEG4VIDEO_H +#define AVCODEC_MPEG4VIDEO_H + +#include "../utils/pixfmt.h" +#include "../utils/common.h" + +//mpeg4 profile +#define FF_PROFILE_MPEG4_SIMPLE 0 +#define FF_PROFILE_MPEG4_SIMPLE_SCALABLE 1 +#define FF_PROFILE_MPEG4_CORE 2 +#define FF_PROFILE_MPEG4_MAIN 3 +#define FF_PROFILE_MPEG4_N_BIT 4 +#define FF_PROFILE_MPEG4_SCALABLE_TEXTURE 5 +#define FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION 6 +#define FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE 7 +#define FF_PROFILE_MPEG4_HYBRID 8 +#define FF_PROFILE_MPEG4_ADVANCED_REAL_TIME 9 +#define FF_PROFILE_MPEG4_CORE_SCALABLE 10 +#define FF_PROFILE_MPEG4_ADVANCED_CODING 11 +#define FF_PROFILE_MPEG4_ADVANCED_CORE 12 +#define FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE 13 +#define FF_PROFILE_MPEG4_SIMPLE_STUDIO 14 +#define FF_PROFILE_MPEG4_ADVANCED_SIMPLE 15 + +// shapes +#define RECT_SHAPE 0 +#define BIN_SHAPE 1 +#define BIN_ONLY_SHAPE 2 +#define GRAY_SHAPE 3 + +#define SIMPLE_VO_TYPE 1 +#define CORE_VO_TYPE 3 +#define MAIN_VO_TYPE 4 +#define NBIT_VO_TYPE 5 +#define ARTS_VO_TYPE 10 +#define ACE_VO_TYPE 12 +#define SIMPLE_STUDIO_VO_TYPE 14 +#define CORE_STUDIO_VO_TYPE 15 +#define ADV_SIMPLE_VO_TYPE 17 + +#define VOT_VIDEO_ID 1 +#define VOT_STILL_TEXTURE_ID 2 + +#define FF_PROFILE_UNKNOWN -99 +#define FF_PROFILE_RESERVED -100 + +// aspect_ratio_info +#define EXTENDED_PAR 15 + +//vol_sprite_usage / sprite_enable +#define STATIC_SPRITE 1 +#define GMC_SPRITE 2 + +#define MOTION_MARKER 0x1F001 +#define DC_MARKER 0x6B001 + +#define VOS_STARTCODE 0x1B0 +#define USER_DATA_STARTCODE 0x1B2 +#define GOP_STARTCODE 0x1B3 +#define VISUAL_OBJ_STARTCODE 0x1B5 +#define VOP_STARTCODE 0x1B6 +#define SLICE_STARTCODE 0x1B7 +#define EXT_STARTCODE 0x1B8 + +#define QUANT_MATRIX_EXT_ID 0x3 + +/* smaller packets likely don't contain a real frame */ +#define MAX_NVOP_SIZE 19 + +#define IS_3IV1 0 + +#define CHROMA_420 1 +#define CHROMA_422 2 +#define CHROMA_444 3 + +#define FF_ASPECT_EXTENDED 15 + +#define AV_NOPTS_VALUE (LONG_MIN) + +/** + * Return value for header parsers if frame is not coded. + * */ +#define FRAME_SKIPPED 100 + +enum AVPictureType { + AV_PICTURE_TYPE_NONE = 0, ///< Undefined + AV_PICTURE_TYPE_I, ///< Intra + AV_PICTURE_TYPE_P, ///< Predicted + AV_PICTURE_TYPE_B, ///< Bi-dir predicted + AV_PICTURE_TYPE_S, ///< S(GMC)-VOP MPEG-4 + AV_PICTURE_TYPE_SI, ///< Switching Intra + AV_PICTURE_TYPE_SP, ///< Switching Predicted + AV_PICTURE_TYPE_BI, ///< BI type +}; + +struct VLC { + int bits; + short (*table)[2]; ///< code, bits + int table_size, table_allocated; +}; + +/** + * MpegEncContext. + */ +struct MpegEncContext { + struct mpeg4_dec_param *ctx; + + /* the following parameters must be initialized before encoding */ + int width, height;///< picture size. must be a multiple of 16 + int codec_tag; ///< internal codec_tag upper case converted from avctx codec_tag + int picture_number; //FIXME remove, unclear definition + + /** matrix transmitted in the bitstream */ + u16 intra_matrix[64]; + u16 chroma_intra_matrix[64]; + u16 inter_matrix[64]; + u16 chroma_inter_matrix[64]; + + /* MPEG-4 specific */ + int studio_profile; + int time_base; ///< time in seconds of last I,P,S Frame + int quant_precision; + int quarter_sample; ///< 1->qpel, 0->half pel ME/MC + int aspect_ratio_info; //FIXME remove + int sprite_warping_accuracy; + int data_partitioning; ///< data partitioning flag from header + int low_delay; ///< no reordering needed / has no B-frames + int vo_type; + int mpeg_quant; + + /* divx specific, used to workaround (many) bugs in divx5 */ + int divx_packed; + + /* MPEG-2-specific - I wished not to have to support this mess. */ + int progressive_sequence; + + int progressive_frame; + int interlaced_dct; + + int h_edge_pos, v_edge_pos;///< horizontal / vertical position of the right/bottom edge (pixel replication) + const u8 *y_dc_scale_table; ///< qscale -> y_dc_scale table + const u8 *c_dc_scale_table; ///< qscale -> c_dc_scale table + int qscale; ///< QP + int chroma_qscale; ///< chroma QP + int pict_type; ///< AV_PICTURE_TYPE_I, AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, ... + int f_code; ///< forward MV resolution + int b_code; ///< backward MV resolution for B-frames (MPEG-4) + int no_rounding; /**< apply no rounding to motion compensation (MPEG-4, msmpeg4, ...) + for B-frames rounding mode is always 0 */ + int last_time_base; + long time; ///< time of current frame + long last_non_b_time; + u16 pp_time; ///< time distance between the last 2 p,s,i frames + u16 pb_time; ///< time distance between the last b and p,s,i frame + u16 pp_field_time; + u16 pb_field_time; ///< like above, just for interlaced + int real_sprite_warping_points; + int sprite_offset[2][2]; ///< sprite offset[isChroma][isMVY] + int sprite_delta[2][2]; ///< sprite_delta [isY][isMVY] + int mcsel; + int partitioned_frame; ///< is current frame partitioned + int top_field_first; + int alternate_scan; + int last_dc[3]; ///< last DC values for MPEG-1 + int dct_precision; + int intra_dc_precision; + int frame_pred_frame_dct; + int q_scale_type; + int context_reinit; + int chroma_format; +}; + +struct mpeg4_dec_param { + struct MpegEncContext m; + + /// number of bits to represent the fractional part of time + int time_increment_bits; + int shape; + int vol_sprite_usage; + int sprite_brightness_change; + int num_sprite_warping_points; + /// sprite trajectory points + u16 sprite_traj[4][2]; + /// sprite shift [isChroma] + int sprite_shift[2]; + + // reversible vlc + int rvlc; + /// could this stream contain resync markers + int resync_marker; + /// time distance of first I -> B, used for interlaced B-frames + int t_frame; + + int new_pred; + int enhancement_type; + int scalability; + int use_intra_dc_vlc; + + /// QP above which the ac VLC should be used for intra dc + int intra_dc_threshold; + + /* bug workarounds */ + int divx_version; + int divx_build; + int xvid_build; + int lavc_build; + + /// flag for having shown the warning about invalid Divx B-frames + int showed_packed_warning; + /** does the stream contain the low_delay flag, + * used to work around buggy encoders. */ + int vol_control_parameters; + int cplx_estimation_trash_i; + int cplx_estimation_trash_p; + int cplx_estimation_trash_b; + + struct VLC studio_intra_tab[12]; + struct VLC studio_luma_dc; + struct VLC studio_chroma_dc; + + int rgb; + + struct AVRational time_base; + int ticks_per_frame; + enum AVPixelFormat pix_fmt; + struct AVRational sample_aspect_ratio; + enum AVColorPrimaries color_primaries; + enum AVColorTransferCharacteristic color_trc; + enum AVColorSpace colorspace; + enum AVColorRange color_range; + enum AVChromaLocation chroma_sample_location; + int err_recognition; + int idct_algo; + int bits_per_raw_sample; + int profile; + int level; + struct AVRational framerate; + int flags; +}; + +struct mpeg4_param_sets { + bool head_parsed; + /* currently active parameter sets */ + struct mpeg4_dec_param dec_ps; +}; + +int mpeg4_decode_extradata_ps(u8 *buf, int size, struct mpeg4_param_sets *ps); + +#endif + diff --git a/drivers/amvdec_ports/decoder/aml_vp9_parser.c b/drivers/amvdec_ports/decoder/aml_vp9_parser.c new file mode 100644 index 0000000..2d82dfb --- a/dev/null +++ b/drivers/amvdec_ports/decoder/aml_vp9_parser.c @@ -0,0 +1,299 @@ +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/vmalloc.h> +#include <linux/mm.h> +#include <linux/string.h> + +#include "aml_vp9_parser.h" +#include "../utils/get_bits.h" +#include "../utils/put_bits.h" +#include "../utils/golomb.h" +#include "../utils/common.h" +#include "utils.h" + +#define VP9_SYNCCODE 0x498342 + +static int read_colorspace_details(struct VP9Context *s, int profile) +{ + static const enum AVColorSpace colorspaces[8] = { + AVCOL_SPC_UNSPECIFIED, AVCOL_SPC_BT470BG, AVCOL_SPC_BT709, AVCOL_SPC_SMPTE170M, + AVCOL_SPC_SMPTE240M, AVCOL_SPC_BT2020_NCL, AVCOL_SPC_RESERVED, AVCOL_SPC_RGB, + }; + + enum AVColorSpace colorspace; + int color_range; + int bits = profile <= 1 ? 0 : 1 + get_bits1(&s->gb); // 0:8, 1:10, 2:12 + + s->bpp_index = bits; + s->s.h.bpp = 8 + bits * 2; + s->bytesperpixel = (7 + s->s.h.bpp) >> 3; + colorspace = colorspaces[get_bits(&s->gb, 3)]; + if (colorspace == AVCOL_SPC_RGB) { // RGB = profile 1 + if (profile & 1) { + if (get_bits1(&s->gb)) { + pr_err("Reserved bit set in RGB\n"); + return -1; + } + } else { + pr_err("RGB not supported in profile %d\n", profile); + return -1; + } + } else { + static const enum AVPixelFormat pix_fmt_for_ss[3][2 /* v */][2 /* h */] = { + { { AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P }, + { AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV420P } }, + { { AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10 }, + { AV_PIX_FMT_YUV440P10, AV_PIX_FMT_YUV420P10 } }, + { { AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12 }, + { AV_PIX_FMT_YUV440P12, AV_PIX_FMT_YUV420P12 } }}; + color_range = get_bits1(&s->gb) ? 2 : 1; + if (profile & 1) { + s->ss_h = get_bits1(&s->gb); + s->ss_v = get_bits1(&s->gb); + s->pix_fmt = pix_fmt_for_ss[bits][s->ss_v][s->ss_h]; + if (s->pix_fmt == AV_PIX_FMT_YUV420P) { + pr_err("YUV 4:2:0 not supported in profile %d\n", profile); + return -1; + } else if (get_bits1(&s->gb)) { + pr_err("Profile %d color details reserved bit set\n", profile); + return -1; + } + } else { + s->ss_h = s->ss_v = 1; + s->pix_fmt = pix_fmt_for_ss[bits][1][1]; + } + } + + return 0; +} + +int decode_frame_header(const u8 *data, int size, struct VP9Context *s, int *ref) +{ + int ret, last_invisible, profile; + + /* general header */ + if ((ret = init_get_bits8(&s->gb, data, size)) < 0) { + pr_err("Failed to initialize bitstream reader\n"); + return ret; + } + + if (get_bits(&s->gb, 2) != 0x2) { // frame marker + pr_err("Invalid frame marker\n"); + return -1; + } + + profile = get_bits1(&s->gb); + profile |= get_bits1(&s->gb) << 1; + if (profile == 3) + profile += get_bits1(&s->gb); + + if (profile > 3) { + pr_err("Profile %d is not yet supported\n", profile); + return -1; + } + + s->s.h.profile = profile; + if (get_bits1(&s->gb)) { + *ref = get_bits(&s->gb, 3); + return 0; + } + + s->last_keyframe = s->s.h.keyframe; + s->s.h.keyframe = !get_bits1(&s->gb); + + last_invisible = s->s.h.invisible; + s->s.h.invisible = !get_bits1(&s->gb); + s->s.h.errorres = get_bits1(&s->gb); + s->s.h.use_last_frame_mvs = !s->s.h.errorres && !last_invisible; + + if (s->s.h.keyframe) { + if (get_bits_long(&s->gb, 24) != VP9_SYNCCODE) { // synccode + pr_err("Invalid sync code\n"); + return -1; + } + if ((ret = read_colorspace_details(s,profile)) < 0) + return ret; + // for profile 1, here follows the subsampling bits + s->s.h.refreshrefmask = 0xff; + s->width = get_bits(&s->gb, 16) + 1; + s->height = get_bits(&s->gb, 16) + 1; + if (get_bits1(&s->gb)) { // has scaling + s->render_width = get_bits(&s->gb, 16) + 1; + s->render_height = get_bits(&s->gb, 16) + 1; + } else { + s->render_width = s->width; + s->render_height = s->height; + } + /*pr_info("keyframe res: (%d x %d), render size: (%d x %d)\n", + s->width, s->height, s->render_width, s->render_height);*/ + } else { + s->s.h.intraonly = s->s.h.invisible ? get_bits1(&s->gb) : 0; + s->s.h.resetctx = s->s.h.errorres ? 0 : get_bits(&s->gb, 2); + if (s->s.h.intraonly) { + if (get_bits_long(&s->gb, 24) != VP9_SYNCCODE) { // synccode + pr_err("Invalid sync code\n"); + return -1; + } + if (profile >= 1) { + if ((ret = read_colorspace_details(s, profile)) < 0) + return ret; + } else { + s->ss_h = s->ss_v = 1; + s->s.h.bpp = 8; + s->bpp_index = 0; + s->bytesperpixel = 1; + s->pix_fmt = AV_PIX_FMT_YUV420P; + } + s->s.h.refreshrefmask = get_bits(&s->gb, 8); + s->width = get_bits(&s->gb, 16) + 1; + s->height = get_bits(&s->gb, 16) + 1; + if (get_bits1(&s->gb)) { // has scaling + s->render_width = get_bits(&s->gb, 16) + 1; + s->render_height = get_bits(&s->gb, 16) + 1; + } else { + s->render_width = s->width; + s->render_height = s->height; + } + pr_info("intra res: (%d x %d), render size: (%d x %d)\n", + s->width, s->height, s->render_width, s->render_height); + } else { + s->s.h.refreshrefmask = get_bits(&s->gb, 8); + s->s.h.refidx[0] = get_bits(&s->gb, 3); + s->s.h.signbias[0] = get_bits1(&s->gb) && !s->s.h.errorres; + s->s.h.refidx[1] = get_bits(&s->gb, 3); + s->s.h.signbias[1] = get_bits1(&s->gb) && !s->s.h.errorres; + s->s.h.refidx[2] = get_bits(&s->gb, 3); + s->s.h.signbias[2] = get_bits1(&s->gb) && !s->s.h.errorres; + + /*refresh_frame_flags; + for (i = 0; i < REFS_PER_FRAME; ++i) { + frame_refs[i]; + ref_frame_sign_biases[i]; + } + frame_size_from_refs(); + high_precision_mv; + interp_filter();*/ + + return -1; + } + } + + return 0; +} + +int vp9_superframe_split_filter(struct vp9_superframe_split *s) +{ + int i, j, ret, marker; + bool is_superframe = false; + int *prefix = (int *)s->data; + + if (!s->data) + return -1; + + #define AML_PREFIX ('V' << 24 | 'L' << 16 | 'M' << 8 | 'A') + if (prefix[3] == AML_PREFIX) { + s->prefix_size = 16; + /*pr_info("the frame data has beed added header\n");*/ + } + + marker = s->data[s->data_size - 1]; + if ((marker & 0xe0) == 0xc0) { + int length_size = 1 + ((marker >> 3) & 0x3); + int nb_frames = 1 + (marker & 0x7); + int idx_size = 2 + nb_frames * length_size; + + if (s->data_size >= idx_size && + s->data[s->data_size - idx_size] == marker) { + s64 total_size = 0; + int idx = s->data_size + 1 - idx_size; + + for (i = 0; i < nb_frames; i++) { + int frame_size = 0; + for (j = 0; j < length_size; j++) + frame_size |= s->data[idx++] << (j * 8); + + total_size += frame_size; + if (frame_size < 0 || + total_size > s->data_size - idx_size) { + pr_err( "Invalid frame size in a sframe: %d\n", + frame_size); + ret = -EINVAL; + goto fail; + } + s->sizes[i] = frame_size; + } + + s->nb_frames = nb_frames; + s->size = total_size; + s->next_frame = 0; + s->next_frame_offset = 0; + is_superframe = true; + } + }else { + s->nb_frames = 1; + s->sizes[0] = s->data_size; + s->size = s->data_size; + } + + /*pr_info("sframe: %d, frames: %d, IN: %x, OUT: %x\n", + is_superframe, s->nb_frames, + s->data_size, s->size);*/ + + /* parse uncompressed header. */ + if (is_superframe) { + /* bitstream profile. */ + /* frame type. (intra or inter) */ + /* colorspace descriptor */ + /* ... */ + + pr_info("the frame is a superframe.\n"); + } + + /*pr_err("in: %x, %d, out: %x, sizes %d,%d,%d,%d,%d,%d,%d,%d\n", + s->data_size, + s->nb_frames, + s->size, + s->sizes[0], + s->sizes[1], + s->sizes[2], + s->sizes[3], + s->sizes[4], + s->sizes[5], + s->sizes[6], + s->sizes[7]);*/ + + return 0; +fail: + return ret; +} + +int vp9_decode_extradata_ps(u8 *data, int size, struct vp9_param_sets *ps) +{ + int i, ref = -1, ret = 0; + struct vp9_superframe_split s = {0}; + + /*parse superframe.*/ + s.data = data; + s.data_size = size; + ret = vp9_superframe_split_filter(&s); + if (ret) { + pr_err("parse frames failed.\n"); + return ret; + } + + for (i = 0; i < s.nb_frames; i++) { + u32 len = s.sizes[i] - s.prefix_size; + u8 *buf = s.data + s.next_frame_offset + s.prefix_size; + + ret = decode_frame_header(buf, len, &ps->ctx, &ref); + if (!ret) { + ps->head_parsed = ref < 0 ? true : false; + return 0; + } + + s.next_frame_offset = len + s.prefix_size; + } + + return ret; +} + diff --git a/drivers/amvdec_ports/decoder/aml_vp9_parser.h b/drivers/amvdec_ports/decoder/aml_vp9_parser.h index 731b1a6..b9f4489 100755..100644 --- a/drivers/amvdec_ports/decoder/aml_vp9_parser.h +++ b/drivers/amvdec_ports/decoder/aml_vp9_parser.h @@ -15,165 +15,160 @@ * */ - #ifndef AML_VP9_PARSER_H #define AML_VP9_PARSER_H -enum BlockPartition { - PARTITION_NONE, // [ ] <-. - PARTITION_H, // [-] | - PARTITION_V, // [|] | - PARTITION_SPLIT, // [+] --' -}; +#include "../utils/pixfmt.h" +#include "../utils/get_bits.h" -enum InterPredMode { - NEARESTMV = 10, - NEARMV = 11, - ZEROMV = 12, - NEWMV = 13, -}; +#define MAX_SEGMENT 8 -enum CompPredMode { - PRED_SINGLEREF, - PRED_COMPREF, - PRED_SWITCHABLE, -}; +struct VP9BitstreamHeader { + // bitstream header + u8 profile; + u8 bpp; + u8 keyframe; + u8 invisible; + u8 errorres; + u8 intraonly; + u8 resetctx; + u8 refreshrefmask; + u8 highprecisionmvs; + u8 allowcompinter; + u8 refreshctx; + u8 parallelmode; + u8 framectxid; + u8 use_last_frame_mvs; + u8 refidx[3]; + u8 signbias[3]; + u8 fixcompref; + u8 varcompref[2]; + struct { + u8 level; + char sharpness; + } filter; + struct { + u8 enabled; + u8 updated; + char mode[2]; + char ref[4]; + } lf_delta; + u8 yac_qi; + char ydc_qdelta, uvdc_qdelta, uvac_qdelta; + u8 lossless; + struct { + u8 enabled; + u8 temporal; + u8 absolute_vals; + u8 update_map; + u8 prob[7]; + u8 pred_prob[3]; + struct { + u8 q_enabled; + u8 lf_enabled; + u8 ref_enabled; + u8 skip_enabled; + u8 ref_val; + int16_t q_val; + char lf_val; + int16_t qmul[2][2]; + u8 lflvl[4][2]; + } feat[MAX_SEGMENT]; + } segmentation; + struct { + u32 log2_tile_cols, log2_tile_rows; + u32 tile_cols, tile_rows; + } tiling; -enum BlockLevel { - BL_64X64, - BL_32X32, - BL_16X16, - BL_8X8, + int uncompressed_header_size; + int compressed_header_size; }; -enum BlockSize { - BS_64x64, - BS_64x32, - BS_32x64, - BS_32x32, - BS_32x16, - BS_16x32, - BS_16x16, - BS_16x8, - BS_8x16, - BS_8x8, - BS_8x4, - BS_4x8, - BS_4x4, - N_BS_SIZES, -}; +struct VP9SharedContext { + struct VP9BitstreamHeader h; -enum FilterMode { - MODE_NONE, - MODE_INTERLEAVE, - MODE_DEINTERLEAVE + //struct ThreadFrame refs[8]; +#define CUR_FRAME 0 +#define REF_FRAME_MVPAIR 1 +#define REF_FRAME_SEGMAP 2 + //struct VP9Frame frames[3]; }; -enum TxfmMode { - TX_4X4, - TX_8X8, - TX_16X16, - TX_32X32, - N_TXFM_SIZES, - TX_SWITCHABLE = N_TXFM_SIZES, - N_TXFM_MODES -}; +struct VP9Context { + struct VP9SharedContext s; + struct get_bits_context gb; + int pass, active_tile_cols; -enum TxfmType { - DCT_DCT, - DCT_ADST, - ADST_DCT, - ADST_ADST, - N_TXFM_TYPES -}; + u8 ss_h, ss_v; + u8 last_bpp, bpp_index, bytesperpixel; + u8 last_keyframe; + // sb_cols/rows, rows/cols and last_fmt are used for allocating all internal + // arrays, and are thus per-thread. w/h and gf_fmt are synced between threads + // and are therefore per-stream. pix_fmt represents the value in the header + // of the currently processed frame. + int width; + int height; -enum IntraPredMode { - VERT_PRED, - HOR_PRED, - DC_PRED, - DIAG_DOWN_LEFT_PRED, - DIAG_DOWN_RIGHT_PRED, - VERT_RIGHT_PRED, - HOR_DOWN_PRED, - VERT_LEFT_PRED, - HOR_UP_PRED, - TM_VP8_PRED, - LEFT_DC_PRED, - TOP_DC_PRED, - DC_128_PRED, - DC_127_PRED, - DC_129_PRED, - N_INTRA_PRED_MODES + int render_width; + int render_height; + + enum AVPixelFormat pix_fmt, last_fmt, gf_fmt; + u32 sb_cols, sb_rows, rows, cols; + + struct { + u8 lim_lut[64]; + u8 mblim_lut[64]; + } filter_lut; + struct { + u8 coef[4][2][2][6][6][3]; + } prob_ctx[4]; + struct { + u8 coef[4][2][2][6][6][11]; + } prob; + + // contextual (above) cache + u8 *above_partition_ctx; + u8 *above_mode_ctx; + // FIXME maybe merge some of the below in a flags field? + u8 *above_y_nnz_ctx; + u8 *above_uv_nnz_ctx[2]; + u8 *above_skip_ctx; // 1bit + u8 *above_txfm_ctx; // 2bit + u8 *above_segpred_ctx; // 1bit + u8 *above_intra_ctx; // 1bit + u8 *above_comp_ctx; // 1bit + u8 *above_ref_ctx; // 2bit + u8 *above_filter_ctx; + + // whole-frame cache + u8 *intra_pred_data[3]; + + // block reconstruction intermediates + int block_alloc_using_2pass; + uint16_t mvscale[3][2]; + u8 mvstep[3][2]; }; -struct VP9BitstreamHeader { - // bitstream header - u8 profile; - u8 bpp; - u8 keyframe; - u8 invisible; - u8 errorres; - u8 intraonly; - u8 resetctx; - u8 refreshrefmask; - u8 highprecisionmvs; - enum FilterMode filtermode; - u8 allowcompinter; - u8 refreshctx; - u8 parallelmode; - u8 framectxid; - u8 use_last_frame_mvs; - u8 refidx[3]; - u8 signbias[3]; - u8 fixcompref; - u8 varcompref[2]; - struct { - u8 level; - int8_t sharpness; - } filter; - struct { - u8 enabled; - u8 updated; - char mode[2]; - char ref[4]; - } lf_delta; - u8 yac_qi; - char ydc_qdelta, uvdc_qdelta, uvac_qdelta; - u8 lossless; -#define MAX_SEGMENT 8 - struct { - u8 enabled; - u8 temporal; - u8 absolute_vals; - u8 update_map; - u8 prob[7]; - u8 pred_prob[3]; - struct { - u8 q_enabled; - u8 lf_enabled; - u8 ref_enabled; - u8 skip_enabled; - u8 ref_val; - s16 q_val; - char lf_val; - s16 qmul[2][2]; - u8 lflvl[4][2]; - } feat[MAX_SEGMENT]; - } segmentation; - enum TxfmMode txfmmode; - enum CompPredMode comppredmode; - struct { - u32 log2_tile_cols, log2_tile_rows; - u32 tile_cols, tile_rows; - } tiling; - - int uncompressed_header_size; - int compressed_header_size; +struct vp9_superframe_split { + /*in data*/ + u8 *data; + u32 data_size; + + /*out data*/ + int nb_frames; + int size; + int next_frame; + u32 next_frame_offset; + int prefix_size; + int sizes[8]; }; -struct vp9_head_info_t { - bool parsed; - struct VP9BitstreamHeader info; +struct vp9_param_sets { + bool head_parsed; + struct VP9Context ctx; }; +int vp9_superframe_split_filter(struct vp9_superframe_split *s); +int vp9_decode_extradata_ps(u8 *data, int size, struct vp9_param_sets *ps); + #endif //AML_VP9_PARSER_H diff --git a/drivers/amvdec_ports/decoder/h264_parse.c b/drivers/amvdec_ports/decoder/h264_parse.c deleted file mode 100644 index 1c3b73d..0000000 --- a/drivers/amvdec_ports/decoder/h264_parse.c +++ b/dev/null @@ -1,389 +0,0 @@ -/* - * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.c - * - * Copyright (C) 2017 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. - * - */ - -#include <linux/kernel.h> -#include "h264_parse.h" -#include "h264_stream.h" - -static unsigned char h264_exp_golomb_bits[256] = { - 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, -}; - -static unsigned char ZZ_SCAN[16] = { - 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 -}; - -static unsigned char ZZ_SCAN8[64] = { - 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 -}; - -unsigned int h264_u(struct h264_stream_t *s, unsigned int n) -{ - //if (n % 8 == 0) { - // return h264_stream_read_bytes(s, n / 8); - //} - return h264_stream_read_bits(s, n); -} - -unsigned int h264_ue(struct h264_stream_t *s) -{ - unsigned int bits, read; - unsigned char coded; - - bits = 0; - while (true) { - if (h264_stream_bytes_remaining(s) < 1) { - read = h264_stream_peek_bits(s, s->bit_pos) << - (8 - s->bit_pos); - break; - } - - read = h264_stream_peek_bits(s, 8); - if (bits > 16) - break; - - if (read) - break; - - h264_stream_read_bits(s, 8); - bits += 8; - } - - coded = h264_exp_golomb_bits[read]; - h264_stream_read_bits(s, coded); - bits += coded; - return h264_stream_read_bits(s, bits + 1) - 1; -} - -int h264_se(struct h264_stream_t *s) -{ - unsigned int ret; - - ret = h264_ue(s); - if (!(ret & 0x1)) { - ret >>= 1; - return (int)(-ret); - } - - return (ret + 1) >> 1; -} - -void h264_f(struct h264_stream_t *s, unsigned int n, unsigned int pattern) -{ - unsigned int val = h264_u(s, n); - - if (val != pattern) { - pr_err("fixed-pattern doesn't match. expected: %x actual: %x\n", - pattern, (unsigned int)val); - return; - } -} - -void h264_rbsp_trailing_bits(struct h264_stream_t *s) -{ - h264_f(s, 1, 1); - h264_f(s, s->bit_pos, 0); -} - -// syntax for scaling list matrix values -void Scaling_List(int *scalingList, int sizeOfScalingList, - bool *UseDefaultScalingMatrix, struct h264_stream_t *s) -{ - int j, scanj; - int delta_scale, lastScale, nextScale; - - lastScale = 8; - nextScale = 8; - - for (j = 0; j < sizeOfScalingList; j++) { - scanj = (sizeOfScalingList == 16) ? ZZ_SCAN[j] : ZZ_SCAN8[j]; - - if (nextScale != 0) { - delta_scale = h264_ue(s); - nextScale = (lastScale + delta_scale + 256) % 256; - *UseDefaultScalingMatrix = - (bool) (scanj == 0 && nextScale == 0); - } - - scalingList[scanj] = (nextScale == 0) ? lastScale : nextScale; - lastScale = scalingList[scanj]; - } -} - -void h264_sps_parse(struct h264_stream_t *s, struct h264_SPS_t *sps) -{ - unsigned int i, n_ScalingList; - - sps->profile_idc = h264_u(s, 8); - - if ((sps->profile_idc != BASELINE) && - (sps->profile_idc != MAIN) && - (sps->profile_idc != EXTENDED) && - (sps->profile_idc != FREXT_HP) && - (sps->profile_idc != FREXT_Hi10P) && - (sps->profile_idc != FREXT_Hi422) && - (sps->profile_idc != FREXT_Hi444) && - (sps->profile_idc != FREXT_CAVLC444) - && (sps->profile_idc != MVC_HIGH) - && (sps->profile_idc != STEREO_HIGH)) { - pr_err("Invalid Profile IDC (%d) encountered.\n", - sps->profile_idc); - return; - } - - sps->constrained_set0_flag = h264_u(s, 1); - sps->constrained_set1_flag = h264_u(s, 1); - sps->constrained_set2_flag = h264_u(s, 1); - h264_u(s, 5); // reserved_zero_5bits - sps->level_idc = h264_u(s, 8); - sps->seq_parameter_set_id = h264_ue(s); - - // Fidelity Range Extensions stuff - sps->chroma_format_idc = 1; - sps->bit_depth_luma_minus8 = 0; - sps->bit_depth_chroma_minus8 = 0; - sps->lossless_qpprime_flag = 0; - sps->separate_colour_plane_flag = 0; - - if ((sps->profile_idc == FREXT_HP) || - (sps->profile_idc == FREXT_Hi10P) || - (sps->profile_idc == FREXT_Hi422) || - (sps->profile_idc == FREXT_Hi444) || - (sps->profile_idc == FREXT_CAVLC444)) { - sps->chroma_format_idc = h264_ue(s); - - if (sps->chroma_format_idc == YUV444) - sps->separate_colour_plane_flag = h264_u(s, 1); - - sps->bit_depth_luma_minus8 = h264_ue(s); - sps->bit_depth_chroma_minus8 = h264_ue(s); - //checking; - if ((sps->bit_depth_luma_minus8 + 8 > sizeof(unsigned short) * 8) || - (sps->bit_depth_chroma_minus8 + 8 > sizeof(unsigned short) * 8)) { - pr_err("Source picture has higher bit depth than imgpel data type.\n"); - pr_err("Please recompile with larger data type for imgpel.\n"); - } - - sps->lossless_qpprime_flag = h264_u(s, 1); - sps->seq_scaling_matrix_present_flag = h264_u(s, 1); - if (sps->seq_scaling_matrix_present_flag) { - n_ScalingList = (sps->chroma_format_idc != YUV444) ? 8 : 12; - for (i = 0; i < n_ScalingList; i++) { - sps->seq_scaling_list_present_flag[i] = h264_u(s, 1); - if (sps->seq_scaling_list_present_flag[i]) { - if (i < 6) - Scaling_List(sps->ScalingList4x4[i], 16, - &sps->UseDefaultScalingMatrix4x4Flag[i], s); - else - Scaling_List(sps->ScalingList8x8[i - 6], - 64, &sps->UseDefaultScalingMatrix8x8Flag[i - 6], s); - } - } - } - } - - sps->log2_max_frame_num_minus4 = h264_ue(s); - sps->pic_order_cnt_type = h264_ue(s); - if (sps->pic_order_cnt_type == 0) { - sps->log2_max_pic_order_cnt_lsb_minus4 = h264_ue(s); - } else if (sps->pic_order_cnt_type == 1) { - sps->delta_pic_order_always_zero_flag = h264_se(s); - sps->offset_for_non_ref_pic = h264_se(s); - sps->offset_for_top_to_bottom_field = h264_se(s); - sps->num_ref_frames_in_poc_cycle = h264_se(s); - for (i = 0; i < sps->num_ref_frames_in_poc_cycle; ++i) - sps->offset_for_ref_frame[i] = h264_se(s); - } - - sps->num_ref_frames = h264_ue(s); - sps->gaps_in_frame_num_value_allowed_flag = h264_u(s, 1); - sps->pic_width_in_mbs_minus1 = h264_ue(s); - sps->pic_height_in_map_units_minus1 = h264_ue(s); - sps->frame_mbs_only_flag = h264_u(s, 1); - if (!sps->frame_mbs_only_flag) - sps->mb_adaptive_frame_field_flag = h264_u(s, 1); - - sps->direct_8x8_inference_flag = h264_u(s, 1); - sps->frame_cropping_flag = h264_u(s, 1); - if (sps->frame_cropping_flag) { - sps->frame_crop_left_offset = h264_ue(s); - sps->frame_crop_right_offset = h264_ue(s); - sps->frame_crop_top_offset = h264_ue(s); - sps->frame_crop_bottom_offset = h264_ue(s); - } - - sps->vui_parameters_present_flag = h264_u(s, 1); - //if (sps->vui_parameters_present_flag) { - // sps->vui_parameters = h264_vui_parameters(s); - //} - h264_rbsp_trailing_bits(s); -} - -void h264_pps_parse(struct h264_stream_t *s, struct h264_PPS_t *pps) -{ - pps->pic_parameter_set_id = h264_ue(s); - pps->seq_parameter_set_id = h264_ue(s); - pps->entropy_coding_mode_flag = h264_u(s, 1); - pps->pic_order_present_flag = h264_u(s, 1); - pps->num_slice_groups_minus1 = h264_ue(s); - if (pps->num_slice_groups_minus1 > 0) { - pps->slice_group_map_type = h264_ue(s); - if (pps->slice_group_map_type == 0) { - pps->run_length_minus1 = h264_ue(s); - } else if (pps->slice_group_map_type == 2) { - pps->top_left = h264_ue(s); - pps->bottom_right = h264_ue(s); - } else if (pps->slice_group_map_type == 3 || - pps->slice_group_map_type == 4 || - pps->slice_group_map_type == 5) { - pps->slice_group_change_direction_flag = h264_u(s, 1); - pps->slice_group_change_rate_minus1 = h264_ue(s); - } else if (pps->slice_group_map_type == 6) { - pps->pic_size_in_map_units_minus1 = h264_ue(s); - pps->slice_group_id = h264_ue(s); - } - } - pps->num_ref_idx_l0_active_minus1 = h264_ue(s); - pps->num_ref_idx_l1_active_minus1 = h264_ue(s); - pps->weighted_pred_flag = h264_u(s, 1); - pps->weighted_bipred_idc = h264_u(s, 2); - pps->pic_init_qp_minus26 = h264_se(s); - pps->pic_init_qs_minus26 = h264_se(s); - pps->chroma_qp_index_offset = h264_se(s); - pps->deblocking_filter_control_present_flag = h264_u(s, 1); - pps->constrained_intra_pred_flag = h264_u(s, 1); - pps->redundant_pic_cnt_present_flag = h264_u(s, 1); - h264_rbsp_trailing_bits(s); -} - -void h264_sps_info(struct h264_SPS_t *sps) -{ - int i; - - pr_info("sequence_parameter_set {\n"); - pr_info(" profile_idc: %d\n", sps->profile_idc); - pr_info(" constraint_set0_flag: %d\n", sps->constrained_set0_flag); - pr_info(" constraint_set1_flag: %d\n", sps->constrained_set1_flag); - pr_info(" constraint_set2_flag: %d\n", sps->constrained_set2_flag); - pr_info(" level_idc: %d\n", sps->level_idc); - pr_info(" seq_parameter_set_id: %d\n", sps->seq_parameter_set_id); - - pr_info(" log2_max_frame_num_minus4: %d\n", - sps->log2_max_frame_num_minus4); - pr_info(" pic_order_cnt_type: %d\n", sps->pic_order_cnt_type); - if (sps->pic_order_cnt_type == 0) { - pr_info(" log2_max_pic_order_cnt_lsb_minus4: %d\n", - sps->log2_max_pic_order_cnt_lsb_minus4); - } else if (sps->pic_order_cnt_type == 1) { - pr_info(" delta_pic_order_always_zero_flag: %d\n", - sps->delta_pic_order_always_zero_flag); - pr_info(" offset_for_non_ref_pic: %d\n", - sps->offset_for_non_ref_pic); - pr_info(" offset_for_top_to_bottom_field: %d\n", - sps->offset_for_top_to_bottom_field); - pr_info(" num_ref_frames_in_pic_order_cnt_cycle: %d\n", - sps->num_ref_frames_in_poc_cycle); - for (i = 0; i < sps->num_ref_frames_in_poc_cycle; ++i) { - pr_info(" offset_for_ref_frame[%d]: %d\n", i, - sps->offset_for_ref_frame[i]); - } - } - pr_info(" num_ref_frames: %d\n", sps->num_ref_frames); - pr_info(" gaps_in_frame_num_value_allowed_flag: %d\n", - sps->gaps_in_frame_num_value_allowed_flag); - pr_info(" pic_width_in_mbs_minus1: %d\n", - sps->pic_width_in_mbs_minus1); - pr_info(" pic_height_in_map_units_minus1: %d\n", - sps->pic_height_in_map_units_minus1); - pr_info(" frame_mbs_only_flag: %d\n", - sps->frame_mbs_only_flag); - pr_info(" mb_adaptive_frame_field_flag: %d\n", - sps->mb_adaptive_frame_field_flag); - pr_info(" direct_8x8_inference_flag: %d\n", - sps->direct_8x8_inference_flag); - pr_info(" frame_cropping_flag: %d\n", - sps->frame_cropping_flag); - if (sps->frame_cropping_flag) { - pr_info(" frame_crop_left_offset: %d\n", - sps->frame_crop_left_offset); - pr_info(" frame_crop_right_offset: %d\n", - sps->frame_crop_right_offset); - pr_info(" frame_crop_top_offset: %d\n", - sps->frame_crop_top_offset); - pr_info(" frame_crop_bottom_offset: %d\n", - sps->frame_crop_bottom_offset); - } - pr_info(" vui_parameters_present_flag: %d\n", - sps->vui_parameters_present_flag); - //if (sps->vui_parameters_present_flag) { - // h264_print_vui_parameters(sps->vui_parameters); - //} - - pr_info(" }\n"); -} - -void h264_pps_info(struct h264_PPS_t *pps) -{ - pr_info("pic_parameter_set {\n"); - pr_info(" pic_parameter_set_id: %d\n", - pps->pic_parameter_set_id); - pr_info(" seq_parameter_set_id: %d\n", - pps->seq_parameter_set_id); - pr_info(" entropy_coding_mode_flag: %d\n", - pps->entropy_coding_mode_flag); - pr_info(" pic_order_present_flag: %d\n", - pps->pic_order_present_flag); - pr_info(" num_slice_groups_minus1: %d\n", - pps->num_slice_groups_minus1); - // FIXME: Code for slice groups is missing here. - pr_info(" num_ref_idx_l0_active_minus1: %d\n", - pps->num_ref_idx_l0_active_minus1); - pr_info(" num_ref_idx_l1_active_minus1: %d\n", - pps->num_ref_idx_l1_active_minus1); - pr_info(" weighted_pred_flag: %d\n", pps->weighted_pred_flag); - pr_info(" weighted_bipred_idc: %d\n", pps->weighted_bipred_idc); - pr_info(" pic_init_qp_minus26: %d\n", pps->pic_init_qp_minus26); - pr_info(" pic_init_qs_minus26: %d\n", pps->pic_init_qs_minus26); - pr_info(" chroma_qp_index_offset: %d\n", - pps->chroma_qp_index_offset); - pr_info(" deblocking_filter_control_present_flag: %d\n", - pps->deblocking_filter_control_present_flag); - pr_info(" constrained_intra_pred_flag: %d\n", - pps->constrained_intra_pred_flag); - pr_info(" redundant_pic_cnt_present_flag: %d\n", - pps->redundant_pic_cnt_present_flag); - pr_info(" }\n"); -} - diff --git a/drivers/amvdec_ports/decoder/h264_parse.h b/drivers/amvdec_ports/decoder/h264_parse.h deleted file mode 100644 index e54e4d3..0000000 --- a/drivers/amvdec_ports/decoder/h264_parse.h +++ b/dev/null @@ -1,141 +0,0 @@ -/* - * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.h - * - * Copyright (C) 2017 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 _H264_PARSE_H -#define _H264_PARSE_H - -#include "h264_stream.h" - -enum color_model { - CM_UNKNOWN = -1, - CM_YUV = 0, - CM_RGB = 1, - CM_XYZ = 2 -}; - -enum color_format { - CF_UNKNOWN = -1, //!< Unknown color format - YUV400 = 0, //!< Monochrome - YUV420 = 1, //!< 4:2:0 - YUV422 = 2, //!< 4:2:2 - YUV444 = 3 //!< 4:4:4 -}; - -enum pixel_format { - PF_UNKNOWN = -1, //!< Unknown color ordering - UYVY = 0, //!< UYVY - YUY2 = 1, //!< YUY2 - YUYV = 1, //!< YUYV - YVYU = 2, //!< YVYU - BGR = 3, //!< BGR - V210 = 4 //!< Video Clarity 422 format (10 bits) -}; - -//AVC Profile IDC definitions -enum profile_idc{ - NO_PROFILE = 0, //!< disable profile checking for experimental coding (enables FRExt, but disables MV) - FREXT_CAVLC444 = 44, //!< YUV 4:4:4/14 "CAVLC 4:4:4" - BASELINE = 66, //!< YUV 4:2:0/8 "Baseline" - MAIN = 77, //!< YUV 4:2:0/8 "Main" - EXTENDED = 88, //!< YUV 4:2:0/8 "Extended" - FREXT_HP = 100, //!< YUV 4:2:0/8 "High" - FREXT_Hi10P = 110, //!< YUV 4:2:0/10 "High 10" - FREXT_Hi422 = 122, //!< YUV 4:2:2/10 "High 4:2:2" - FREXT_Hi444 = 244, //!< YUV 4:4:4/14 "High 4:4:4" - MVC_HIGH = 118, //!< YUV 4:2:0/8 "Multiview High" - STEREO_HIGH = 128 //!< YUV 4:2:0/8 "Stereo High" -}; - -/* sequence parameter set */ -struct h264_SPS_t { - bool vailid; - unsigned int profile_idc; - bool constrained_set0_flag; - bool constrained_set1_flag; - bool constrained_set2_flag; - bool constrained_set3_flag; - unsigned int level_idc; - unsigned int seq_parameter_set_id; - unsigned int chroma_format_idc; - bool seq_scaling_matrix_present_flag; - int seq_scaling_list_present_flag[12]; - int ScalingList4x4[6][16]; - int ScalingList8x8[6][64]; - bool UseDefaultScalingMatrix4x4Flag[6]; - bool UseDefaultScalingMatrix8x8Flag[6]; - unsigned int bit_depth_luma_minus8; - unsigned int bit_depth_chroma_minus8; - unsigned int log2_max_frame_num_minus4; - unsigned int pic_order_cnt_type; - unsigned int log2_max_pic_order_cnt_lsb_minus4; - bool delta_pic_order_always_zero_flag; - int offset_for_non_ref_pic; - int offset_for_top_to_bottom_field; - unsigned int num_ref_frames_in_poc_cycle; - int offset_for_ref_frame[255]; - int num_ref_frames; - bool gaps_in_frame_num_value_allowed_flag; - unsigned int pic_width_in_mbs_minus1; - unsigned int pic_height_in_map_units_minus1; - bool frame_mbs_only_flag; - bool mb_adaptive_frame_field_flag; - bool direct_8x8_inference_flag; - bool frame_cropping_flag; - unsigned int frame_crop_left_offset; - unsigned int frame_crop_right_offset; - unsigned int frame_crop_top_offset; - unsigned int frame_crop_bottom_offset; - bool vui_parameters_present_flag; - //h264_vui_parameters_t *vui_parameters; - unsigned separate_colour_plane_flag; - int lossless_qpprime_flag; -}; - -/* pic parameter set */ -struct h264_PPS_t { - int pic_parameter_set_id; - int seq_parameter_set_id; - int entropy_coding_mode_flag; - int pic_order_present_flag; - int num_slice_groups_minus1; - int slice_group_map_type; - int run_length_minus1; - int top_left; - int bottom_right; - int slice_group_change_direction_flag; - int slice_group_change_rate_minus1; - int pic_size_in_map_units_minus1; - int slice_group_id; - int num_ref_idx_l0_active_minus1; - int num_ref_idx_l1_active_minus1; - int weighted_pred_flag; - int weighted_bipred_idc; - int pic_init_qp_minus26; - int pic_init_qs_minus26; - int chroma_qp_index_offset; - int deblocking_filter_control_present_flag; - int constrained_intra_pred_flag; - int redundant_pic_cnt_present_flag; -}; - -void h264_sps_parse(struct h264_stream_t *s, struct h264_SPS_t *sps); -void h264_pps_parse(struct h264_stream_t *s, struct h264_PPS_t *pps); - -void h264_sps_info(struct h264_SPS_t *sps); -void h264_pps_info(struct h264_PPS_t *pps); - -#endif //_H264_PARSE_H diff --git a/drivers/amvdec_ports/decoder/h264_stream.c b/drivers/amvdec_ports/decoder/h264_stream.c deleted file mode 100644 index 3061568..0000000 --- a/drivers/amvdec_ports/decoder/h264_stream.c +++ b/dev/null @@ -1,111 +0,0 @@ -/* - * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.c - * - * Copyright (C) 2017 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. - * - */ - -#include <linux/mm.h> -#include <linux/slab.h> -#include "h264_stream.h" - -void h264_stream_set(struct h264_stream_t *s, unsigned char *data, int size) -{ - s->data = data; - s->size = size; - s->bit_pos = 7; - s->byte_pos = 0; -} - -unsigned int h264_stream_read_bits(struct h264_stream_t *s, unsigned int n) -{ - unsigned int ret = 0; - unsigned char b = 0; - int i; - - if (n == 0) - return 0; - - for (i = 0; i < n; ++i) { - if (h264_stream_bits_remaining(s) == 0) - ret <<= n - i - 1; - - b = s->data[s->byte_pos]; - if (n - i <= 32) - ret = ret << 1 | BITAT(b, s->bit_pos); - - if (s->bit_pos == 0) { - s->bit_pos = 7; - s->byte_pos++; - } else - s->bit_pos--; - } - - return ret; -} - -unsigned int h264_stream_peek_bits(struct h264_stream_t *s, unsigned int n) -{ - int prev_bit_pos = s->bit_pos; - int prev_byte_pos = s->byte_pos; - unsigned int ret = h264_stream_read_bits(s, n); - - s->bit_pos = prev_bit_pos; - s->byte_pos = prev_byte_pos; - - return ret; -} - -unsigned int h264_stream_read_bytes(struct h264_stream_t *s, unsigned int n) -{ - unsigned int ret = 0; - int i; - - if (n == 0) - return 0; - - for (i = 0; i < n; ++i) { - if (h264_stream_bytes_remaining(s) == 0) { - ret <<= (n - i - 1) * 8; - break; - } - - if (n - i <= 4) - ret = ret << 8 | s->data[s->byte_pos]; - - s->byte_pos++; - } - - return ret; -} - -unsigned int h264_stream_peek_bytes(struct h264_stream_t *s, unsigned int n) -{ - int prev_byte_pos = s->byte_pos; - unsigned int ret = h264_stream_read_bytes(s, n); - - s->byte_pos = prev_byte_pos; - - return ret; -} - -int h264_stream_bits_remaining(struct h264_stream_t *s) -{ - return (s->size - s->byte_pos) * 8 + s->bit_pos; -} - -int h264_stream_bytes_remaining(struct h264_stream_t *s) -{ - return s->size - s->byte_pos; -} - diff --git a/drivers/amvdec_ports/decoder/h264_stream.h b/drivers/amvdec_ports/decoder/h264_stream.h deleted file mode 100644 index d6d2eac..0000000 --- a/drivers/amvdec_ports/decoder/h264_stream.h +++ b/dev/null @@ -1,39 +0,0 @@ -/* - * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.h - * - * Copyright (C) 2017 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 _H264_STREAM_H -#define _H264_STREAM_H - -#include "utils.h" - -struct h264_stream_t { - unsigned char *data; - unsigned int size; - int bit_pos; - int byte_pos; -}; - -void h264_stream_set(struct h264_stream_t *s, unsigned char *data, int size); -unsigned int h264_stream_read_bits(struct h264_stream_t *s, unsigned int n); -unsigned int h264_stream_peek_bits(struct h264_stream_t *s, unsigned int n); -unsigned int h264_stream_read_bytes(struct h264_stream_t *s, unsigned int n); -unsigned int h264_stream_peek_bytes(struct h264_stream_t *s, unsigned int n); -int h264_stream_bits_remaining(struct h264_stream_t *s); -int h264_stream_bytes_remaining(struct h264_stream_t *s); - -#endif //_H264_STREAM_H - diff --git a/drivers/amvdec_ports/decoder/vdec_h264_if.c b/drivers/amvdec_ports/decoder/vdec_h264_if.c index efa9fc7..02848b8 100644 --- a/drivers/amvdec_ports/decoder/vdec_h264_if.c +++ b/drivers/amvdec_ports/decoder/vdec_h264_if.c @@ -22,16 +22,16 @@ #include <linux/timer.h> #include <linux/delay.h> #include <linux/kernel.h> +#include <uapi/linux/swab.h> + #include "../vdec_drv_if.h" #include "../aml_vcodec_util.h" #include "../aml_vcodec_dec.h" -//#include "../aml_vcodec_intr.h" #include "../aml_vcodec_adapt.h" #include "../vdec_drv_base.h" #include "../aml_vcodec_vfm.h" -#include "h264_stream.h" -#include "h264_parse.h" -#include <uapi/linux/swab.h> +#include "aml_h264_parser.h" +#include "../utils/common.h" /* h264 NALU type */ #define NAL_NON_IDR_SLICE 0x01 @@ -39,8 +39,9 @@ #define NAL_H264_SEI 0x06 #define NAL_H264_SPS 0x07 #define NAL_H264_PPS 0x08 +#define NAL_H264_AUD 0x09 -#define NAL_TYPE(value) ((value) & 0x1F) +#define AVC_NAL_TYPE(value) ((value) & 0x1F) #define BUF_PREDICTION_SZ (64 * 1024)//(32 * 1024) @@ -52,7 +53,7 @@ #define H264_MAX_FB_NUM 17 #define HDR_PARSING_BUF_SZ 1024 -#define HEADER_BUFFER_SIZE (32 * 1024) +#define HEADER_BUFFER_SIZE (128 * 1024) /** * struct h264_fb - h264 decode frame buffer information @@ -113,11 +114,6 @@ struct vdec_h264_dec_info { * by VPU. * AP-W/R : AP is writer/reader on this item * VPU-W/R: VPU is write/reader on this item - * @hdr_buf : Header parsing buffer (AP-W, VPU-R) - * @pred_buf_dma : HW working predication buffer dma address (AP-W, VPU-R) - * @mv_buf_dma : HW working motion vector buffer dma address (AP-W, VPU-R) - * @list_free : free frame buffer ring list (AP-W/R, VPU-W) - * @list_disp : display frame buffer ring list (AP-R, VPU-W) * @dec : decode information (AP-R, VPU-W) * @pic : picture information (AP-R, VPU-W) * @crop : crop information (AP-R, VPU-W) @@ -129,10 +125,6 @@ struct vdec_h264_vsi { int pps_size; int sei_size; int head_offset; - uint64_t pred_buf_dma; - uint64_t mv_buf_dma[H264_MAX_FB_NUM]; - struct h264_ring_fb_list list_free; - struct h264_ring_fb_list list_disp; struct vdec_h264_dec_info dec; struct vdec_pic_info pic; struct vdec_pic_info cur_pic; @@ -155,10 +147,10 @@ struct vdec_h264_inst { struct aml_vcodec_ctx *ctx; struct aml_vcodec_mem pred_buf; struct aml_vcodec_mem mv_buf[H264_MAX_FB_NUM]; - //struct vdec_vpu_inst vpu; struct aml_vdec_adapt vdec; struct vdec_h264_vsi *vsi; struct vcodec_vfm_s vfm; + struct completion comp; }; #if 0 @@ -241,18 +233,6 @@ static void get_dpb_size(struct vdec_h264_inst *inst, unsigned int *dpb_sz) aml_vcodec_debug(inst, "sz=%d", *dpb_sz); } -static int find_start_code(unsigned char *data, unsigned int data_sz) -{ - if (data_sz > 3 && data[0] == 0 && data[1] == 0 && data[2] == 1) - return 3; - - if (data_sz > 4 && data[0] == 0 && data[1] == 0 && data[2] == 0 && - data[3] == 1) - return 4; - - return -1; -} - static void skip_aud_data(u8 **data, u32 *size) { int i; @@ -275,7 +255,7 @@ static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) inst->ctx = ctx; - inst->vdec.format = VFORMAT_H264; + inst->vdec.video_type = VFORMAT_H264; inst->vdec.dev = ctx->dev->vpu_plat_dev; inst->vdec.filp = ctx->dev->filp; inst->vdec.ctx = ctx; @@ -318,6 +298,8 @@ static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) inst->vsi->pic.c_bs_sz = 0; inst->vsi->pic.c_len_sz = (1920 * 1088 / 2); + init_completion(&inst->comp); + aml_vcodec_debug(inst, "H264 Instance >> %p", inst); ctx->ada_ctx = &inst->vdec; @@ -336,11 +318,11 @@ error_free_inst: return ret; } -static int refer_buffer_num(int level_idc, int poc_cnt, +#if 0 +static int refer_buffer_num(int level_idc, int max_poc_cnt, int mb_width, int mb_height) { - int max_ref_num = 27; - int size, size_margin = 6; + int size; int pic_size = mb_width * mb_height * 384; switch (level_idc) { @@ -399,51 +381,28 @@ static int refer_buffer_num(int level_idc, int poc_cnt, size /= pic_size; size = size + 1; /* need more buffers */ - if (poc_cnt > size) - size = poc_cnt; - - size = size + size_margin; - if (size > max_ref_num) - size = max_ref_num; + if (size > max_poc_cnt) + size = max_poc_cnt; return size; } +#endif static void fill_vdec_params(struct vdec_h264_inst *inst, struct h264_SPS_t *sps) { struct vdec_pic_info *pic = &inst->vsi->pic; struct vdec_h264_dec_info *dec = &inst->vsi->dec; struct v4l2_rect *rect = &inst->vsi->crop; - unsigned int mb_w, mb_h, width, height; - unsigned int crop_unit_x = 0, crop_unit_y = 0; - unsigned int poc_cnt = 0; - - mb_w = sps->pic_width_in_mbs_minus1 + 1; - mb_h = sps->pic_height_in_map_units_minus1 + 1; - - width = mb_w << 4; // 16 - height = (2 - sps->frame_mbs_only_flag) * (mb_h << 4); - - if (sps->frame_cropping_flag) { - if (0 == sps->chroma_format_idc) {// monochrome - crop_unit_x = 1; - crop_unit_y = 2 - sps->frame_mbs_only_flag; - } else if (1 == sps->chroma_format_idc) {// 4:2:0 - crop_unit_x = 2; - crop_unit_y = 2 * (2 - sps->frame_mbs_only_flag); - } else if (2 == sps->chroma_format_idc) {// 4:2:2 - crop_unit_x = 2; - crop_unit_y = 2 - sps->frame_mbs_only_flag; - } else {// 3 == sps.chroma_format_idc // 4:4:4 - crop_unit_x = 1; - crop_unit_y = 2 - sps->frame_mbs_only_flag; - } - } + u32 mb_w, mb_h, width, height; - width -= crop_unit_x * (sps->frame_crop_left_offset + - sps->frame_crop_right_offset); - height -= crop_unit_y * (sps->frame_crop_top_offset + - sps->frame_crop_bottom_offset); + mb_w = sps->mb_width; + mb_h = sps->mb_height; + + width = mb_w << 4; + height = mb_h << 4; + + width -= (sps->crop_left + sps->crop_right); + height -= (sps->crop_top + sps->crop_bottom); /* fill visible area size that be used for EGL. */ pic->visible_width = width; @@ -462,19 +421,16 @@ static void fill_vdec_params(struct vdec_h264_inst *inst, struct h264_SPS_t *sps pic->c_len_sz = pic->y_len_sz >> 1; /* calc DPB size */ - poc_cnt = sps->pic_order_cnt_type; - if (!poc_cnt) - poc_cnt = (sps->log2_max_pic_order_cnt_lsb_minus4 + 4) << 1; - - dec->dpb_sz = refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h); + dec->dpb_sz = sps->ref_frame_count; aml_vcodec_debug(inst, "[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n", inst->ctx->id, pic->coded_width, pic->coded_height, pic->visible_width, pic->visible_height, dec->dpb_sz); } -static void search_from_st(u8 *buf, u32 size, int *pos, bool *is_combine) +static bool check_frame_combine(u8 *buf, u32 size, int *pos) { + bool combine = false; int i = 0, j = 0, cnt = 0; u8 *p = buf; @@ -482,7 +438,7 @@ static void search_from_st(u8 *buf, u32 size, int *pos, bool *is_combine) j = find_start_code(p, 7); if (j > 0) { if (++cnt > 1) { - *is_combine = true; + combine = true; break; } @@ -494,22 +450,40 @@ static void search_from_st(u8 *buf, u32 size, int *pos, bool *is_combine) } //pr_info("nal pos: %d, is_combine: %d\n",*pos, *is_combine); + return combine; +} + +static int stream_parse_by_ucode(struct vdec_h264_inst *inst, u8 *buf, u32 size) +{ + int ret = 0; + struct aml_vdec_adapt *vdec = &inst->vdec; + + ret = vdec_vframe_write(vdec, buf, size, 0); + if (ret < 0) { + pr_err("write frame data failed. err: %d\n", ret); + return ret; + } + + /* wait ucode parse ending. */ + wait_for_completion_timeout(&inst->comp, + msecs_to_jiffies(1000)); + + return inst->vsi->dec.dpb_sz ? 0 : -1; } static int stream_parse(struct vdec_h264_inst *inst, u8 *buf, u32 size) { - struct h264_stream_t s; - struct h264_SPS_t *sps; - unsigned int nal_type; + int ret = 0; + struct h264_param_sets *ps; + u32 nal_type; int nal_idx = 0; - int real_data_pos, real_data_size; bool is_combine = false; - search_from_st(buf, size, &nal_idx, &is_combine); + is_combine = check_frame_combine(buf, size, &nal_idx); if (nal_idx < 0) return -1; - nal_type = NAL_TYPE(buf[nal_idx]); + nal_type = AVC_NAL_TYPE(buf[nal_idx]); if (nal_type != NAL_H264_SPS) return -1; @@ -517,23 +491,24 @@ static int stream_parse(struct vdec_h264_inst *inst, u8 *buf, u32 size) inst->vsi->is_combine = is_combine; inst->vsi->nalu_pos = nal_idx; - /* start code plus nal type. */ - real_data_pos = nal_idx + 1; - real_data_size = size - real_data_pos; - - sps = kzalloc(sizeof(struct h264_SPS_t), GFP_KERNEL); - if (sps == NULL) + ps = kzalloc(sizeof(struct h264_param_sets), GFP_KERNEL); + if (ps == NULL) return -ENOMEM; - h264_stream_set(&s, &buf[real_data_pos], real_data_size); - h264_sps_parse(&s, sps); - //h264_sps_info(sps); + ret = h264_decode_extradata_ps(buf, size, ps); + if (ret) { + pr_err("parse extra data failed. err: %d\n", ret); + goto out; + } - fill_vdec_params(inst, sps); + if (ps->sps_parsed) + fill_vdec_params(inst, &ps->sps); - kfree(sps); + ret = ps->sps_parsed ? 0 : -1; +out: + kfree(ps); - return 0; + return ret; } static int vdec_h264_probe(unsigned long h_vdec, @@ -542,7 +517,7 @@ static int vdec_h264_probe(unsigned long h_vdec, struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec; struct stream_info *st; - u8 *buf = (u8 *)bs->va; + u8 *buf = (u8 *)bs->vaddr; u32 size = bs->size; int ret = 0; @@ -556,7 +531,11 @@ static int vdec_h264_probe(unsigned long h_vdec, } skip_aud_data(&buf, &size); - ret = stream_parse(inst, buf, size); + + if (inst->ctx->param_sets_from_ucode) + ret = stream_parse_by_ucode(inst, buf, size); + else + ret = stream_parse(inst, buf, size); inst->vsi->cur_pic = inst->vsi->pic; @@ -565,10 +544,9 @@ static int vdec_h264_probe(unsigned long h_vdec, static void vdec_h264_deinit(unsigned long h_vdec) { + ulong flags; struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec; - - if (!inst) - return; + struct aml_vcodec_ctx *ctx = inst->ctx; aml_vcodec_debug_enter(inst); @@ -578,6 +556,7 @@ static void vdec_h264_deinit(unsigned long h_vdec) //dump_deinit(); + spin_lock_irqsave(&ctx->slock, flags); if (inst->vsi && inst->vsi->header_buf) kfree(inst->vsi->header_buf); @@ -585,20 +564,20 @@ static void vdec_h264_deinit(unsigned long h_vdec) kfree(inst->vsi); kfree(inst); + + ctx->drv_handle = 0; + spin_unlock_irqrestore(&ctx->slock, flags); } -static int vdec_h264_get_fb(struct vdec_h264_inst *inst, struct vdec_fb **out) +static int vdec_h264_get_fb(struct vdec_h264_inst *inst, struct vdec_v4l2_buffer **out) { return get_fb_from_queue(inst->ctx, out); } -static void vdec_h264_get_vf(struct vdec_h264_inst *inst, struct vdec_fb **out) +static void vdec_h264_get_vf(struct vdec_h264_inst *inst, struct vdec_v4l2_buffer **out) { struct vframe_s *vf = NULL; - struct vdec_fb *fb = NULL; - - aml_vcodec_debug(inst, "%s() [%d], vfm: %p", - __func__, __LINE__, &inst->vfm); + struct vdec_v4l2_buffer *fb = NULL; vf = peek_video_frame(&inst->vfm); if (!vf) { @@ -616,28 +595,18 @@ static void vdec_h264_get_vf(struct vdec_h264_inst *inst, struct vdec_fb **out) atomic_set(&vf->use_cnt, 1); - aml_vcodec_debug(inst, "%s() [%d], vf: %p, v4l_mem_handle: %lx, idx: %d\n", - __func__, __LINE__, vf, vf->v4l_mem_handle, vf->index); - - fb = (struct vdec_fb *)vf->v4l_mem_handle; + fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle; fb->vf_handle = (unsigned long)vf; fb->status = FB_ST_DISPLAY; *out = fb; //pr_info("%s, %d\n", __func__, fb->base_y.bytes_used); - //dump_write(fb->base_y.va, fb->base_y.bytes_used); - //dump_write(fb->base_c.va, fb->base_c.bytes_used); + //dump_write(fb->base_y.vaddr, fb->base_y.bytes_used); + //dump_write(fb->base_c.vaddr, fb->base_c.bytes_used); /* convert yuv format. */ - //swap_uv(fb->base_c.va, fb->base_c.size); - - aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu", - __func__, __LINE__, fb->base_y.va, - (unsigned int)virt_to_phys(fb->base_y.va), fb->base_y.size); - aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu", - __func__, __LINE__, fb->base_c.va, - (unsigned int)virt_to_phys(fb->base_c.va), fb->base_c.size); + //swap_uv(fb->base_c.vaddr, fb->base_c.size); } static int vdec_write_nalu(struct vdec_h264_inst *inst, @@ -653,8 +622,8 @@ static int vdec_write_nalu(struct vdec_h264_inst *inst, if (nalu_pos < 0) goto err; - nal_type = NAL_TYPE(buf[nalu_pos]); - aml_vcodec_debug(inst, "NALU type: %d, size: %u", nal_type, size); + nal_type = AVC_NAL_TYPE(buf[nalu_pos]); + //aml_vcodec_debug(inst, "NALU type: %d, size: %u", nal_type, size); if (nal_type == NAL_H264_SPS && !is_combine) { if (inst->vsi->head_offset + size > HEADER_BUFFER_SIZE) { @@ -686,9 +655,6 @@ static int vdec_write_nalu(struct vdec_h264_inst *inst, ret = size; } else if (inst->vsi->head_offset == 0) { ret = vdec_vframe_write(vdec, buf, size, ts); - - aml_vcodec_debug(inst, "buf: %p, buf size: %u, write to: %d", - buf, size, ret); } else { char *write_buf = vmalloc(inst->vsi->head_offset + size); if (!write_buf) { @@ -702,9 +668,6 @@ static int vdec_write_nalu(struct vdec_h264_inst *inst, ret = vdec_vframe_write(vdec, write_buf, inst->vsi->head_offset + size, ts); - aml_vcodec_debug(inst, "buf: %p, buf size: %u, write to: %d", - write_buf, inst->vsi->head_offset + size, ret); - memset(inst->vsi->header_buf, 0, HEADER_BUFFER_SIZE); inst->vsi->head_offset = 0; inst->vsi->sps_size = 0; @@ -720,14 +683,46 @@ err: return ret; } +static bool monitor_res_change(struct vdec_h264_inst *inst, u8 *buf, u32 size) +{ + int ret = 0, i = 0, j = 0; + u8 *p = buf; + int len = size; + u32 type; + + for (i = 4; i < size; i++) { + j = find_start_code(p, len); + if (j > 0) { + len = size - (p - buf); + type = AVC_NAL_TYPE(p[j]); + if (type != NAL_H264_AUD && + (type > NAL_H264_PPS || type < NAL_H264_SEI)) + break; + + if (type == NAL_H264_SPS) { + ret = stream_parse(inst, p, len); + if (!ret && (inst->vsi->cur_pic.coded_width != + inst->vsi->pic.coded_width || + inst->vsi->cur_pic.coded_height != + inst->vsi->pic.coded_height)) { + inst->vsi->cur_pic = inst->vsi->pic; + return true; + } + } + p += j; + } + p++; + } + + return false; +} + static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, - unsigned long int timestamp, bool *res_chg) + u64 timestamp, bool *res_chg) { struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec; struct aml_vdec_adapt *vdec = &inst->vdec; struct stream_info *st; - int nalu_pos; - u32 nal_type; u8 *buf; u32 size; int ret = -1; @@ -736,7 +731,7 @@ static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, if (bs == NULL) return -1; - buf = (u8 *)bs->va; + buf = (u8 *)bs->vaddr; size = bs->size; st = (struct stream_info *)buf; @@ -749,28 +744,10 @@ static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, else if (inst->ctx->is_stream_mode) ret = vdec_vbuf_write(vdec, buf, size); else { - /*checked whether the resolution chagnes.*/ - u8 *p = buf; - u32 l = size; - - skip_aud_data(&p, &l); - - nalu_pos = find_start_code(p, l); - if (nalu_pos < 0) - return -1; - - nal_type = NAL_TYPE(p[nalu_pos]); - if (nal_type == NAL_H264_SPS) { - stream_parse(inst, p, l); - if (inst->vsi->cur_pic.coded_width != - inst->vsi->pic.coded_width || - inst->vsi->cur_pic.coded_height != - inst->vsi->pic.coded_height) { - inst->vsi->cur_pic = inst->vsi->pic; - *res_chg = true; - return 0; - } - } + /*checked whether the resolution changes.*/ + if ((*res_chg = monitor_res_change(inst, buf, size))) + return 0; + ret = vdec_write_nalu(inst, buf, size, timestamp); } @@ -817,12 +794,80 @@ static int vdec_h264_get_param(unsigned long h_vdec, return ret; } +static void set_param_write_sync(struct vdec_h264_inst *inst) +{ + complete(&inst->comp); +} + +static void set_param_pic_info(struct vdec_h264_inst *inst, + struct aml_vdec_pic_infos *info) +{ + struct vdec_pic_info *pic = &inst->vsi->pic; + struct vdec_h264_dec_info *dec = &inst->vsi->dec; + struct v4l2_rect *rect = &inst->vsi->crop; + + /* fill visible area size that be used for EGL. */ + pic->visible_width = info->visible_width; + pic->visible_height = info->visible_height; + + /* calc visible ares. */ + rect->left = 0; + rect->top = 0; + rect->width = pic->visible_width; + rect->height = pic->visible_height; + + /* config canvas size that be used for decoder. */ + pic->coded_width = info->coded_width; + pic->coded_height = info->coded_height; + pic->y_len_sz = pic->coded_width * pic->coded_height; + pic->c_len_sz = pic->y_len_sz >> 1; + + dec->dpb_sz = info->dpb_size; + + /*wake up*/ + complete(&inst->comp); + + pr_info("Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d\n", + info->visible_width, info->visible_height, + info->coded_width, info->coded_height, + info->dpb_size); +} + +static int vdec_h264_set_param(unsigned long h_vdec, + enum vdec_set_param_type type, void *in) +{ + int ret = 0; + struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec; + + if (!inst) { + pr_err("the h264 inst of dec is invalid.\n"); + return -1; + } + + switch (type) { + case SET_PARAM_WRITE_FRAME_SYNC: + set_param_write_sync(inst); + break; + + case SET_PARAM_PIC_INFO: + set_param_pic_info(inst, in); + break; + + default: + aml_vcodec_err(inst, "invalid set parameter type=%d", type); + ret = -EINVAL; + } + + return ret; +} + static struct vdec_common_if vdec_h264_if = { - vdec_h264_init, - vdec_h264_probe, - vdec_h264_decode, - vdec_h264_get_param, - vdec_h264_deinit, + .init = vdec_h264_init, + .probe = vdec_h264_probe, + .decode = vdec_h264_decode, + .get_param = vdec_h264_get_param, + .set_param = vdec_h264_set_param, + .deinit = vdec_h264_deinit, }; struct vdec_common_if *get_h264_dec_comm_if(void); diff --git a/drivers/amvdec_ports/decoder/vdec_hevc_if.c b/drivers/amvdec_ports/decoder/vdec_hevc_if.c index 0870da7..59ce85f 100644 --- a/drivers/amvdec_ports/decoder/vdec_hevc_if.c +++ b/drivers/amvdec_ports/decoder/vdec_hevc_if.c @@ -31,7 +31,7 @@ #include "../aml_vcodec_vfm.h" #include "aml_hevc_parser.h" -#define NAL_TYPE(value) ((value) & 0x1F) +#define HEVC_NAL_TYPE(value) ((value >> 1) & 0x3F) #define HEADER_BUFFER_SIZE (32 * 1024) /** @@ -93,10 +93,11 @@ struct vdec_hevc_vsi { int head_offset; struct vdec_hevc_dec_info dec; struct vdec_pic_info pic; + struct vdec_pic_info cur_pic; struct v4l2_rect crop; bool is_combine; int nalu_pos; - struct HEVCParamSets ps; + struct h265_param_sets ps; }; /** @@ -111,59 +112,9 @@ struct vdec_hevc_inst { struct aml_vdec_adapt vdec; struct vdec_hevc_vsi *vsi; struct vcodec_vfm_s vfm; + struct completion comp; }; -#if 0 -#define DUMP_FILE_NAME "/data/dump/dump.tmp" -static struct file *filp; -static loff_t file_pos; - -void dump_write(const char __user *buf, size_t count) -{ - mm_segment_t old_fs; - - if (!filp) - return; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - - if (count != vfs_write(filp, buf, count, &file_pos)) - pr_err("Failed to write file\n"); - - set_fs(old_fs); -} - -void dump_init(void) -{ - filp = filp_open(DUMP_FILE_NAME, O_CREAT | O_RDWR, 0644); - if (IS_ERR(filp)) { - pr_err("open dump file failed\n"); - filp = NULL; - } -} - -void dump_deinit(void) -{ - if (filp) { - filp_close(filp, current->files); - filp = NULL; - file_pos = 0; - } -} - -void swap_uv(void *uv, int size) -{ - int i; - __u16 *p = uv; - - size /= 2; - - for (i = 0; i < size; i++, p++) - *p = __swab16(*p); -} -#endif - static void get_pic_info(struct vdec_hevc_inst *inst, struct vdec_pic_info *pic) { @@ -189,22 +140,10 @@ static void get_crop_info(struct vdec_hevc_inst *inst, struct v4l2_rect *cr) static void get_dpb_size(struct vdec_hevc_inst *inst, unsigned int *dpb_sz) { - *dpb_sz = 20;//inst->vsi->dec.dpb_sz; + *dpb_sz = inst->vsi->dec.dpb_sz; aml_vcodec_debug(inst, "sz=%d", *dpb_sz); } -static int find_start_code(unsigned char *data, unsigned int data_sz) -{ - if (data_sz > 3 && data[0] == 0 && data[1] == 0 && data[2] == 1) - return 3; - - if (data_sz > 4 && data[0] == 0 && data[1] == 0 && data[2] == 0 && - data[3] == 1) - return 4; - - return -1; -} - static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) { struct vdec_hevc_inst *inst = NULL; @@ -216,7 +155,7 @@ static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) inst->ctx = ctx; - inst->vdec.format = VFORMAT_HEVC; + inst->vdec.video_type = VFORMAT_HEVC; inst->vdec.dev = ctx->dev->vpu_plat_dev; inst->vdec.filp = ctx->dev->filp; inst->vdec.ctx = ctx; @@ -262,6 +201,8 @@ static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) inst->vsi->pic.c_bs_sz = 0; inst->vsi->pic.c_len_sz = (1920 * 1088 / 2); + init_completion(&inst->comp); + aml_vcodec_debug(inst, "hevc Instance >> %p", inst); ctx->ada_ctx = &inst->vdec; @@ -280,31 +221,48 @@ error_free_inst: return ret; } -#if 0 -static int refer_buffer_num(int level_idc, int poc_cnt, - int mb_width, int mb_height) + +static int refer_buffer_num(struct h265_SPS_t *sps) { - return 20; + int used_buf_num = 0; + int sps_pic_buf_diff = 0; + + if ((!sps->temporal_layer[0].num_reorder_pics) && + (sps->temporal_layer[0].max_dec_pic_buffering)) { + /* the range of sps_num_reorder_pics_0 is in + [0, sps_max_dec_pic_buffering_minus1_0] */ + used_buf_num = sps->temporal_layer[0].max_dec_pic_buffering; + } else + used_buf_num = sps->temporal_layer[0].num_reorder_pics; + + sps_pic_buf_diff = sps->temporal_layer[0].max_dec_pic_buffering - + sps->temporal_layer[0].num_reorder_pics + 1; + + if (sps_pic_buf_diff >= 4) + used_buf_num += 1; + + /*need one more for multi instance, as + apply_ref_pic_set() has no chanch to run to + to clear referenced flag in some case */ + used_buf_num++; + + /* for eos add more buffer to flush.*/ + used_buf_num++; + + return used_buf_num; } -#endif -//static void fill_vdec_params(struct vdec_hevc_inst *inst, struct hevc_SPS_t *sps) -static void fill_vdec_params(struct vdec_hevc_inst *inst) +static void fill_vdec_params(struct vdec_hevc_inst *inst, struct h265_SPS_t *sps) { struct vdec_pic_info *pic = &inst->vsi->pic; struct vdec_hevc_dec_info *dec = &inst->vsi->dec; struct v4l2_rect *rect = &inst->vsi->crop; - unsigned int mb_w = 0, mb_h = 0, width, height; - //unsigned int crop_unit_x = 0, crop_unit_y = 0; - //unsigned int poc_cnt = 0; - - /* calc width & height. */ - width = 1920; - height = 1080; /* fill visible area size that be used for EGL. */ - pic->visible_width = width; - pic->visible_height = height; + pic->visible_width = sps->width - (sps->output_window.left_offset + + sps->output_window.right_offset); + pic->visible_height = sps->height - (sps->output_window.top_offset + + sps->output_window.bottom_offset); /* calc visible ares. */ rect->left = 0; @@ -313,123 +271,61 @@ static void fill_vdec_params(struct vdec_hevc_inst *inst) rect->height = pic->visible_height; /* config canvas size that be used for decoder. */ - pic->coded_width = ALIGN(mb_w, 4) << 4; - pic->coded_height = ALIGN(mb_h, 4) << 4; - - pic->coded_width = 1920; - pic->coded_height = 1088;//temp + pic->coded_width = ALIGN(sps->width, 32); + pic->coded_height = ALIGN(sps->height, 32); pic->y_len_sz = pic->coded_width * pic->coded_height; pic->c_len_sz = pic->y_len_sz >> 1; /* calc DPB size */ - dec->dpb_sz = 20;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h); + dec->dpb_sz = refer_buffer_num(sps); pr_info("[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n", inst->ctx->id, pic->coded_width, pic->coded_height, pic->visible_width, pic->visible_height, dec->dpb_sz); } -static int hevc_parse_nal_header(u32 val) +static int stream_parse_by_ucode(struct vdec_hevc_inst *inst, u8 *buf, u32 size) { - if (val & 0x80) { - pr_err("the nal data is invalid.\n"); - return -1; - } + int ret = 0; + struct aml_vdec_adapt *vdec = &inst->vdec; - return (val & 0x7f) >> 1; -} + ret = vdec_vframe_write(vdec, buf, size, 0); + if (ret < 0) { + pr_err("write frame data failed. err: %d\n", ret); + return ret; + } -static void hevc_parse(struct HEVCParamSets *ps, u8 *buf, u32 size) -{ - //int ret = -1; - int i = 0, j = 0, cnt = 0; - int pos, nal_size, nal_type; - u8 *p = buf; + /* wait ucode parse ending. */ + wait_for_completion_timeout(&inst->comp, + msecs_to_jiffies(1000)); - for (i = 4; i < size; i++) { - j = find_start_code(p, i); - if (j > 0) { - pos = p - buf + j; - nal_size = size - pos; - nal_type = hevc_parse_nal_header(buf[pos]); - - switch (nal_type) { - case HEVC_NAL_VPS: - //ret = hevc_parse_nal_vps(&ps->vps, p, nal_size); - //if (!ret) - //ps->vps_parsed = true; - pr_err("------%s,%d nal type: %u\n",__func__, __LINE__,nal_type); - break; - case HEVC_NAL_SPS: - //ret = hevc_parse_nal_sps(&ps->sps, p, nal_size); - //if (!ret) - ps->sps_parsed = true; - pr_err("------%s,%d nal type: %u\n",__func__, __LINE__,nal_type); - break; - case HEVC_NAL_PPS: - //ret = hevc_parse_nal_pps(&ps->pps, p, nal_size); - //if (!ret) - //ps->sps_parsed = true; - pr_err("------%s,%d nal type: %u\n",__func__, __LINE__,nal_type); - break; - case HEVC_NAL_SEI_PREFIX: - case HEVC_NAL_SEI_SUFFIX: - //ret = hevc_parse_nal_sei(&ps->sei, p, nal_size); - //if (!ret) - //ps->sei_parsed = true; - pr_err("------%s,%d nal type: %u\n",__func__, __LINE__,nal_type); - break; - default: - pr_info("ignoring NAL type %d in extradata\n", nal_type); - break; - } - - cnt++; - p += j; - i = pos; - } - p++; - } + return inst->vsi->dec.dpb_sz ? 0 : -1; } static int stream_parse(struct vdec_hevc_inst *inst, u8 *buf, u32 size) { - //struct hevc_stream_t s; - //struct hevc_SPS_t *sps; - //unsigned int nal_type; - int nal_idx = 0; - int real_data_pos, real_data_size; - bool is_combine = false; - - hevc_parse(&inst->vsi->ps, buf, size); - - if (!inst->vsi->ps.sps_parsed) - return -1; - - /* if the st compose from csd + slice that is the combine data. */ - inst->vsi->is_combine = is_combine; - inst->vsi->nalu_pos = nal_idx; - - /* start code plus nal type. */ - real_data_pos = nal_idx + 1; - real_data_size = size - real_data_pos; + int ret = 0; + struct h265_param_sets *ps = NULL; - //sps = kzalloc(sizeof(struct hevc_SPS_t), GFP_KERNEL); - //if (sps == NULL) - //return -ENOMEM; + ps = kzalloc(sizeof(struct h265_param_sets), GFP_KERNEL); + if (ps == NULL) + return -ENOMEM; - /* the extra data would be parsed. */ - //hevc_stream_set(&s, &buf[real_data_pos], real_data_size); - //hevc_sps_parse(&s, sps); - //hevc_sps_info(sps); + ret = h265_decode_extradata_ps(buf, size, ps); + if (ret) { + pr_err("parse extra data failed. err: %d\n", ret); + goto out; + } - //fill_vdec_params(inst, sps); - fill_vdec_params(inst); + if (ps->sps_parsed) + fill_vdec_params(inst, &ps->sps); - //kfree(sps); + ret = ps->sps_parsed ? 0 : -1; +out: + kfree(ps); - return 0; + return ret; } static int vdec_hevc_probe(unsigned long h_vdec, @@ -438,7 +334,7 @@ static int vdec_hevc_probe(unsigned long h_vdec, struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec; struct stream_info *st; - u8 *buf = (u8 *)bs->va; + u8 *buf = (u8 *)bs->vaddr; u32 size = bs->size; int ret = 0; @@ -448,18 +344,23 @@ static int vdec_hevc_probe(unsigned long h_vdec, if (st->magic == NORe || st->magic == NORn) ret = stream_parse(inst, st->data, st->length); - else - ret = stream_parse(inst, buf, size); + else { + if (inst->ctx->param_sets_from_ucode) + ret = stream_parse_by_ucode(inst, buf, size); + else + ret = stream_parse(inst, buf, size); + } + + inst->vsi->cur_pic = inst->vsi->pic; return ret; } static void vdec_hevc_deinit(unsigned long h_vdec) { + ulong flags; struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec; - - if (!inst) - return; + struct aml_vcodec_ctx *ctx = inst->ctx; aml_vcodec_debug_enter(inst); @@ -469,6 +370,7 @@ static void vdec_hevc_deinit(unsigned long h_vdec) //dump_deinit(); + spin_lock_irqsave(&ctx->slock, flags); if (inst->vsi && inst->vsi->header_buf) kfree(inst->vsi->header_buf); @@ -476,20 +378,20 @@ static void vdec_hevc_deinit(unsigned long h_vdec) kfree(inst->vsi); kfree(inst); + + ctx->drv_handle = 0; + spin_unlock_irqrestore(&ctx->slock, flags); } -static int vdec_hevc_get_fb(struct vdec_hevc_inst *inst, struct vdec_fb **out) +static int vdec_hevc_get_fb(struct vdec_hevc_inst *inst, struct vdec_v4l2_buffer **out) { return get_fb_from_queue(inst->ctx, out); } -static void vdec_hevc_get_vf(struct vdec_hevc_inst *inst, struct vdec_fb **out) +static void vdec_hevc_get_vf(struct vdec_hevc_inst *inst, struct vdec_v4l2_buffer **out) { struct vframe_s *vf = NULL; - struct vdec_fb *fb = NULL; - - aml_vcodec_debug(inst, "%s() [%d], vfm: %p", - __func__, __LINE__, &inst->vfm); + struct vdec_v4l2_buffer *fb = NULL; vf = peek_video_frame(&inst->vfm); if (!vf) { @@ -507,114 +409,80 @@ static void vdec_hevc_get_vf(struct vdec_hevc_inst *inst, struct vdec_fb **out) atomic_set(&vf->use_cnt, 1); - aml_vcodec_debug(inst, "%s() [%d], vf: %p, v4l_mem_handle: %lx, idx: %d\n", - __func__, __LINE__, vf, vf->v4l_mem_handle, vf->index); - - fb = (struct vdec_fb *)vf->v4l_mem_handle; + fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle; fb->vf_handle = (unsigned long)vf; fb->status = FB_ST_DISPLAY; *out = fb; //pr_info("%s, %d\n", __func__, fb->base_y.bytes_used); - //dump_write(fb->base_y.va, fb->base_y.bytes_used); - //dump_write(fb->base_c.va, fb->base_c.bytes_used); + //dump_write(fb->base_y.vaddr, fb->base_y.bytes_used); + //dump_write(fb->base_c.vaddr, fb->base_c.bytes_used); /* convert yuv format. */ - //swap_uv(fb->base_c.va, fb->base_c.size); - - aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu", - __func__, __LINE__, fb->base_y.va, - (unsigned int)virt_to_phys(fb->base_y.va), fb->base_y.size); - aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu", - __func__, __LINE__, fb->base_c.va, - (unsigned int)virt_to_phys(fb->base_c.va), fb->base_c.size); + //swap_uv(fb->base_c.vaddr, fb->base_c.size); } static int vdec_write_nalu(struct vdec_hevc_inst *inst, u8 *buf, u32 size, u64 ts) { - int ret = 0, err = 0; + int ret = 0; struct aml_vdec_adapt *vdec = &inst->vdec; - bool is_combine = true;//inst->vsi->is_combine; - int nalu_pos; - u32 nal_type; - - nalu_pos = find_start_code(buf, size); - if (nalu_pos < 0) - goto err; - - nal_type = hevc_parse_nal_header(buf[nalu_pos]); - aml_vcodec_debug(inst, "NALU type: %d, size: %u\n", nal_type, size); - - if (nal_type == HEVC_NAL_SPS && !is_combine) { - if (inst->vsi->head_offset + size > HEADER_BUFFER_SIZE) { - ret = -EILSEQ; - goto err; - } - inst->vsi->sps_size = size; - memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, size); - inst->vsi->head_offset += inst->vsi->sps_size; - } else if (nal_type == HEVC_NAL_PPS && !is_combine) { - //buf_sz -= nal_start_idx; - if (inst->vsi->head_offset + size > HEADER_BUFFER_SIZE) { - ret = -EILSEQ; - goto err; - } - inst->vsi->pps_size = size; - memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, size); - inst->vsi->head_offset += inst->vsi->pps_size; - } else if (nal_type == HEVC_NAL_SEI_PREFIX && !is_combine) { - if (inst->vsi->head_offset + size > HEADER_BUFFER_SIZE) { - ret = -EILSEQ; - goto err; - } - inst->vsi->sei_size = size; - memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, size); - inst->vsi->head_offset += inst->vsi->sei_size; - } else { - char *write_buf = vmalloc(inst->vsi->head_offset + size); - memcpy(write_buf, inst->vsi->header_buf, inst->vsi->head_offset); - memcpy(write_buf + inst->vsi->head_offset, buf, size); + ret = vdec_vframe_write(vdec, buf, size, ts); - ret = vdec_vframe_write(vdec, write_buf, - inst->vsi->head_offset + size, ts); + return ret; +} - aml_vcodec_debug(inst, "buf: %p, buf size: %u, write to: %d", - write_buf, inst->vsi->head_offset + size, ret); +static bool monitor_res_change(struct vdec_hevc_inst *inst, u8 *buf, u32 size) +{ + int ret = 0, i = 0, j = 0; + u8 *p = buf; + int len = size; + u32 type; - memset(inst->vsi->header_buf, 0, HEADER_BUFFER_SIZE); - inst->vsi->head_offset = 0; - inst->vsi->sps_size = 0; - inst->vsi->pps_size = 0; - inst->vsi->sei_size = 0; + for (i = 4; i < size; i++) { + j = find_start_code(p, len); + if (j > 0) { + len = size - (p - buf); + type = HEVC_NAL_TYPE(p[j]); + if (type != HEVC_NAL_AUD && + (type > HEVC_NAL_PPS || type < HEVC_NAL_VPS)) + break; - vfree(write_buf); + if (type == HEVC_NAL_SPS) { + ret = stream_parse(inst, p, len); + if (!ret && (inst->vsi->cur_pic.coded_width != + inst->vsi->pic.coded_width || + inst->vsi->cur_pic.coded_height != + inst->vsi->pic.coded_height)) { + inst->vsi->cur_pic = inst->vsi->pic; + return true; + } + } + p += j; + } + p++; } - return 0; -err: - aml_vcodec_err(inst, "%s err(%d)", __func__, err); - - return err; + return false; } static int vdec_hevc_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, - unsigned long int timestamp, bool *res_chg) + u64 timestamp, bool *res_chg) { struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec; struct aml_vdec_adapt *vdec = &inst->vdec; struct stream_info *st; u8 *buf; u32 size; - int ret = 0; + int ret = -1; /* bs NULL means flush decoder */ if (bs == NULL) - return 0; + return -1; - buf = (u8 *)bs->va; + buf = (u8 *)bs->vaddr; size = bs->size; st = (struct stream_info *)buf; @@ -626,8 +494,13 @@ static int vdec_hevc_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, ret = vdec_write_nalu(inst, st->data, st->length, timestamp); else if (inst->ctx->is_stream_mode) ret = vdec_vbuf_write(vdec, buf, size); - else + else { + /*checked whether the resolution changes.*/ + if ((*res_chg = monitor_res_change(inst, buf, size))) + return 0; + ret = vdec_write_nalu(inst, buf, size, timestamp); + } return ret; } @@ -672,12 +545,80 @@ static int vdec_hevc_get_param(unsigned long h_vdec, return ret; } +static void set_param_write_sync(struct vdec_hevc_inst *inst) +{ + complete(&inst->comp); +} + +static void set_param_pic_info(struct vdec_hevc_inst *inst, + struct aml_vdec_pic_infos *info) +{ + struct vdec_pic_info *pic = &inst->vsi->pic; + struct vdec_hevc_dec_info *dec = &inst->vsi->dec; + struct v4l2_rect *rect = &inst->vsi->crop; + + /* fill visible area size that be used for EGL. */ + pic->visible_width = info->visible_width; + pic->visible_height = info->visible_height; + + /* calc visible ares. */ + rect->left = 0; + rect->top = 0; + rect->width = pic->visible_width; + rect->height = pic->visible_height; + + /* config canvas size that be used for decoder. */ + pic->coded_width = ALIGN(info->coded_width, 64); + pic->coded_height = ALIGN(info->coded_height, 64); + pic->y_len_sz = pic->coded_width * pic->coded_height; + pic->c_len_sz = pic->y_len_sz >> 1; + + dec->dpb_sz = info->dpb_size; + + /*wake up*/ + complete(&inst->comp); + + pr_info("Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d\n", + pic->visible_width, pic->visible_height, + pic->coded_width, pic->coded_height, + dec->dpb_sz); +} + +static int vdec_hevc_set_param(unsigned long h_vdec, + enum vdec_set_param_type type, void *in) +{ + int ret = 0; + struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec; + + if (!inst) { + pr_err("the hevc inst of dec is invalid.\n"); + return -1; + } + + switch (type) { + case SET_PARAM_WRITE_FRAME_SYNC: + set_param_write_sync(inst); + break; + + case SET_PARAM_PIC_INFO: + set_param_pic_info(inst, in); + break; + + default: + aml_vcodec_err(inst, "invalid set parameter type=%d", type); + ret = -EINVAL; + } + + return ret; +} + static struct vdec_common_if vdec_hevc_if = { - vdec_hevc_init, - vdec_hevc_probe, - vdec_hevc_decode, - vdec_hevc_get_param, - vdec_hevc_deinit, + .init = vdec_hevc_init, + .probe = vdec_hevc_probe, + .decode = vdec_hevc_decode, + .get_param = vdec_hevc_get_param, + .set_param = vdec_hevc_set_param, + .deinit = vdec_hevc_deinit, }; struct vdec_common_if *get_hevc_dec_comm_if(void); diff --git a/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c new file mode 100644 index 0000000..8bc5faa --- a/dev/null +++ b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c @@ -0,0 +1,498 @@ +/* +* Copyright (C) 2017 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/timer.h> +#include <linux/delay.h> +#include <linux/kernel.h> +#include <uapi/linux/swab.h> +#include "../vdec_drv_if.h" +#include "../aml_vcodec_util.h" +#include "../aml_vcodec_dec.h" +#include "../aml_vcodec_adapt.h" +#include "../vdec_drv_base.h" +#include "../aml_vcodec_vfm.h" +#include "aml_mjpeg_parser.h" + +#define NAL_TYPE(value) ((value) & 0x1F) +#define HEADER_BUFFER_SIZE (32 * 1024) + +/** + * struct mjpeg_fb - mjpeg decode frame buffer information + * @vdec_fb_va : virtual address of struct vdec_fb + * @y_fb_dma : dma address of Y frame buffer (luma) + * @c_fb_dma : dma address of C frame buffer (chroma) + * @poc : picture order count of frame buffer + * @reserved : for 8 bytes alignment + */ +struct mjpeg_fb { + uint64_t vdec_fb_va; + uint64_t y_fb_dma; + uint64_t c_fb_dma; + int32_t poc; + uint32_t reserved; +}; + +/** + * struct vdec_mjpeg_dec_info - decode information + * @dpb_sz : decoding picture buffer size + * @resolution_changed : resoltion change happen + * @reserved : for 8 bytes alignment + * @bs_dma : Input bit-stream buffer dma address + * @y_fb_dma : Y frame buffer dma address + * @c_fb_dma : C frame buffer dma address + * @vdec_fb_va : VDEC frame buffer struct virtual address + */ +struct vdec_mjpeg_dec_info { + uint32_t dpb_sz; + uint32_t resolution_changed; + uint32_t reserved; + uint64_t bs_dma; + uint64_t y_fb_dma; + uint64_t c_fb_dma; + uint64_t vdec_fb_va; +}; + +/** + * struct vdec_mjpeg_vsi - shared memory for decode information exchange + * between VPU and Host. + * The memory is allocated by VPU then mapping to Host + * in vpu_dec_init() and freed in vpu_dec_deinit() + * by VPU. + * AP-W/R : AP is writer/reader on this item + * VPU-W/R: VPU is write/reader on this item + * @hdr_buf : Header parsing buffer (AP-W, VPU-R) + * @list_free : free frame buffer ring list (AP-W/R, VPU-W) + * @list_disp : display frame buffer ring list (AP-R, VPU-W) + * @dec : decode information (AP-R, VPU-W) + * @pic : picture information (AP-R, VPU-W) + * @crop : crop information (AP-R, VPU-W) + */ +struct vdec_mjpeg_vsi { + char *header_buf; + int sps_size; + int pps_size; + int sei_size; + int head_offset; + struct vdec_mjpeg_dec_info dec; + struct vdec_pic_info pic; + struct v4l2_rect crop; + bool is_combine; + int nalu_pos; + //struct mjpeg_param_sets ps; +}; + +/** + * struct vdec_mjpeg_inst - mjpeg decoder instance + * @num_nalu : how many nalus be decoded + * @ctx : point to aml_vcodec_ctx + * @vsi : VPU shared information + */ +struct vdec_mjpeg_inst { + unsigned int num_nalu; + struct aml_vcodec_ctx *ctx; + struct aml_vdec_adapt vdec; + struct vdec_mjpeg_vsi *vsi; + struct vcodec_vfm_s vfm; +}; + +static void get_pic_info(struct vdec_mjpeg_inst *inst, + struct vdec_pic_info *pic) +{ + *pic = inst->vsi->pic; + + aml_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)", + pic->visible_width, pic->visible_height, + pic->coded_width, pic->coded_height); + aml_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz, + pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz); +} + +static void get_crop_info(struct vdec_mjpeg_inst *inst, struct v4l2_rect *cr) +{ + cr->left = inst->vsi->crop.left; + cr->top = inst->vsi->crop.top; + cr->width = inst->vsi->crop.width; + cr->height = inst->vsi->crop.height; + + aml_vcodec_debug(inst, "l=%d, t=%d, w=%d, h=%d", + cr->left, cr->top, cr->width, cr->height); +} + +static void get_dpb_size(struct vdec_mjpeg_inst *inst, unsigned int *dpb_sz) +{ + *dpb_sz = 20;//inst->vsi->dec.dpb_sz; + aml_vcodec_debug(inst, "sz=%d", *dpb_sz); +} + +static int vdec_mjpeg_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) +{ + struct vdec_mjpeg_inst *inst = NULL; + int ret = -1; + + inst = kzalloc(sizeof(*inst), GFP_KERNEL); + if (!inst) + return -ENOMEM; + + inst->ctx = ctx; + + inst->vdec.video_type = VFORMAT_MJPEG; + inst->vdec.dev = ctx->dev->vpu_plat_dev; + inst->vdec.filp = ctx->dev->filp; + inst->vdec.ctx = ctx; + + /* set play mode.*/ + if (ctx->is_drm_mode) + inst->vdec.port.flag |= PORT_FLAG_DRM; + + /* to eable mjpeg hw.*/ + inst->vdec.port.type = PORT_TYPE_VIDEO; + + /* init vfm */ + inst->vfm.ctx = ctx; + inst->vfm.ada_ctx = &inst->vdec; + vcodec_vfm_init(&inst->vfm); + + ret = video_decoder_init(&inst->vdec); + if (ret) { + aml_vcodec_err(inst, "vdec_mjpeg init err=%d", ret); + goto error_free_inst; + } + + /* probe info from the stream */ + inst->vsi = kzalloc(sizeof(struct vdec_mjpeg_vsi), GFP_KERNEL); + if (!inst->vsi) { + ret = -ENOMEM; + goto error_free_inst; + } + + /* alloc the header buffer to be used cache sps or spp etc.*/ + inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL); + if (!inst->vsi) { + ret = -ENOMEM; + goto error_free_vsi; + } + + inst->vsi->pic.visible_width = 1920; + inst->vsi->pic.visible_height = 1080; + inst->vsi->pic.coded_width = 1920; + inst->vsi->pic.coded_height = 1088; + inst->vsi->pic.y_bs_sz = 0; + inst->vsi->pic.y_len_sz = (1920 * 1088); + inst->vsi->pic.c_bs_sz = 0; + inst->vsi->pic.c_len_sz = (1920 * 1088 / 2); + + aml_vcodec_debug(inst, "mjpeg Instance >> %p", inst); + + ctx->ada_ctx = &inst->vdec; + *h_vdec = (unsigned long)inst; + + //dump_init(); + + return 0; + +error_free_vsi: + kfree(inst->vsi); +error_free_inst: + kfree(inst); + *h_vdec = 0; + + return ret; +} + +#if 0 +static int refer_buffer_num(int level_idc, int poc_cnt, + int mb_width, int mb_height) +{ + return 20; +} +#endif + +static void fill_vdec_params(struct vdec_mjpeg_inst *inst, + struct MJpegDecodeContext *ps) +{ + struct vdec_pic_info *pic = &inst->vsi->pic; + struct vdec_mjpeg_dec_info *dec = &inst->vsi->dec; + struct v4l2_rect *rect = &inst->vsi->crop; + + /* fill visible area size that be used for EGL. */ + pic->visible_width = ps->width; + pic->visible_height = ps->height; + + /* calc visible ares. */ + rect->left = 0; + rect->top = 0; + rect->width = pic->visible_width; + rect->height = pic->visible_height; + + /* config canvas size that be used for decoder. */ + pic->coded_width = ALIGN(ps->width, 64); + pic->coded_height = ALIGN(ps->height, 64); + + pic->y_len_sz = pic->coded_width * pic->coded_height; + pic->c_len_sz = pic->y_len_sz >> 1; + + /* calc DPB size */ + dec->dpb_sz = 9;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h); + + pr_info("[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n", + inst->ctx->id, pic->coded_width, pic->coded_height, + pic->visible_width, pic->visible_height, dec->dpb_sz); +} + +static int stream_parse(struct vdec_mjpeg_inst *inst, u8 *buf, u32 size) +{ + int ret = 0; + struct mjpeg_param_sets *ps = NULL; + + ps = kzalloc(sizeof(struct mjpeg_param_sets), GFP_KERNEL); + if (ps == NULL) + return -ENOMEM; + + ret = mjpeg_decode_extradata_ps(buf, size, ps); + if (ret) { + pr_err("parse extra data failed. err: %d\n", ret); + goto out; + } + + if (ps->head_parsed) + fill_vdec_params(inst, &ps->dec_ps); + + ret = ps->head_parsed ? 0 : -1; +out: + kfree(ps); + + return ret; +} + +static int vdec_mjpeg_probe(unsigned long h_vdec, + struct aml_vcodec_mem *bs, void *out) +{ + struct vdec_mjpeg_inst *inst = + (struct vdec_mjpeg_inst *)h_vdec; + struct stream_info *st; + u8 *buf = (u8 *)bs->vaddr; + u32 size = bs->size; + int ret = 0; + + st = (struct stream_info *)buf; + if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn)) + return 0; + + if (st->magic == NORe || st->magic == NORn) + ret = stream_parse(inst, st->data, st->length); + else + ret = stream_parse(inst, buf, size); + + return ret; +} + +static void vdec_mjpeg_deinit(unsigned long h_vdec) +{ + struct vdec_mjpeg_inst *inst = (struct vdec_mjpeg_inst *)h_vdec; + + if (!inst) + return; + + aml_vcodec_debug_enter(inst); + + video_decoder_release(&inst->vdec); + + vcodec_vfm_release(&inst->vfm); + + //dump_deinit(); + + if (inst->vsi && inst->vsi->header_buf) + kfree(inst->vsi->header_buf); + + if (inst->vsi) + kfree(inst->vsi); + + kfree(inst); +} + +static int vdec_mjpeg_get_fb(struct vdec_mjpeg_inst *inst, struct vdec_v4l2_buffer **out) +{ + return get_fb_from_queue(inst->ctx, out); +} + +static void vdec_mjpeg_get_vf(struct vdec_mjpeg_inst *inst, struct vdec_v4l2_buffer **out) +{ + struct vframe_s *vf = NULL; + struct vdec_v4l2_buffer *fb = NULL; + + vf = peek_video_frame(&inst->vfm); + if (!vf) { + aml_vcodec_debug(inst, "there is no vframe."); + *out = NULL; + return; + } + + vf = get_video_frame(&inst->vfm); + if (!vf) { + aml_vcodec_debug(inst, "the vframe is avalid."); + *out = NULL; + return; + } + + atomic_set(&vf->use_cnt, 1); + + fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle; + fb->vf_handle = (unsigned long)vf; + fb->status = FB_ST_DISPLAY; + + *out = fb; + + //pr_info("%s, %d\n", __func__, fb->base_y.bytes_used); + //dump_write(fb->base_y.va, fb->base_y.bytes_used); + //dump_write(fb->base_c.va, fb->base_c.bytes_used); + + /* convert yuv format. */ + //swap_uv(fb->base_c.va, fb->base_c.size); +} + +static int vdec_write_nalu(struct vdec_mjpeg_inst *inst, + u8 *buf, u32 size, u64 ts) +{ + int ret = 0; + struct aml_vdec_adapt *vdec = &inst->vdec; + + ret = vdec_vframe_write(vdec, buf, size, ts); + + return ret; +} + +static int vdec_mjpeg_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, + u64 timestamp, bool *res_chg) +{ + struct vdec_mjpeg_inst *inst = (struct vdec_mjpeg_inst *)h_vdec; + struct aml_vdec_adapt *vdec = &inst->vdec; + struct stream_info *st; + u8 *buf; + u32 size; + int ret = 0; + + /* bs NULL means flush decoder */ + if (bs == NULL) + return 0; + + buf = (u8 *)bs->vaddr; + size = bs->size; + st = (struct stream_info *)buf; + + if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn)) + ret = vdec_vbuf_write(vdec, st->m.buf, sizeof(st->m.drm)); + else if (st->magic == NORe) + ret = vdec_vbuf_write(vdec, st->data, st->length); + else if (st->magic == NORn) + ret = vdec_write_nalu(inst, st->data, st->length, timestamp); + else if (inst->ctx->is_stream_mode) + ret = vdec_vbuf_write(vdec, buf, size); + else + ret = vdec_write_nalu(inst, buf, size, timestamp); + + return ret; +} + +static int vdec_mjpeg_get_param(unsigned long h_vdec, + enum vdec_get_param_type type, void *out) +{ + int ret = 0; + struct vdec_mjpeg_inst *inst = (struct vdec_mjpeg_inst *)h_vdec; + + if (!inst) { + pr_err("the mjpeg inst of dec is invalid.\n"); + return -1; + } + + switch (type) { + case GET_PARAM_DISP_FRAME_BUFFER: + vdec_mjpeg_get_vf(inst, out); + break; + + case GET_PARAM_FREE_FRAME_BUFFER: + ret = vdec_mjpeg_get_fb(inst, out); + break; + + case GET_PARAM_PIC_INFO: + get_pic_info(inst, out); + break; + + case GET_PARAM_DPB_SIZE: + get_dpb_size(inst, out); + break; + + case GET_PARAM_CROP_INFO: + get_crop_info(inst, out); + break; + + default: + aml_vcodec_err(inst, "invalid get parameter type=%d", type); + ret = -EINVAL; + } + + return ret; +} + +static void set_param_pic_info(struct vdec_mjpeg_inst *inst, + struct aml_vdec_pic_infos *info) +{ + pr_info("---%s, %d\n", __func__, __LINE__); +} + +static int vdec_mjpeg_set_param(unsigned long h_vdec, + enum vdec_set_param_type type, void *in) +{ + int ret = 0; + struct vdec_mjpeg_inst *inst = (struct vdec_mjpeg_inst *)h_vdec; + + if (!inst) { + pr_err("the mjpeg inst of dec is invalid.\n"); + return -1; + } + + switch (type) { + case SET_PARAM_PIC_INFO: + set_param_pic_info(inst, in); + break; + + default: + aml_vcodec_err(inst, "invalid set parameter type=%d", type); + ret = -EINVAL; + } + + return ret; +} + +static struct vdec_common_if vdec_mjpeg_if = { + .init = vdec_mjpeg_init, + .probe = vdec_mjpeg_probe, + .decode = vdec_mjpeg_decode, + .get_param = vdec_mjpeg_get_param, + .set_param = vdec_mjpeg_set_param, + .deinit = vdec_mjpeg_deinit, +}; + +struct vdec_common_if *get_mjpeg_dec_comm_if(void); + +struct vdec_common_if *get_mjpeg_dec_comm_if(void) +{ + return &vdec_mjpeg_if; +} diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c new file mode 100644 index 0000000..cdde95b --- a/dev/null +++ b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c @@ -0,0 +1,490 @@ +/* +* Copyright (C) 2017 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/timer.h> +#include <linux/delay.h> +#include <linux/kernel.h> +#include <uapi/linux/swab.h> +#include "../vdec_drv_if.h" +#include "../aml_vcodec_util.h" +#include "../aml_vcodec_dec.h" +#include "../aml_vcodec_adapt.h" +#include "../vdec_drv_base.h" +#include "../aml_vcodec_vfm.h" +#include "aml_mpeg12_parser.h" + +#define NAL_TYPE(value) ((value) & 0x1F) +#define HEADER_BUFFER_SIZE (32 * 1024) + +/** + * struct mpeg12_fb - mpeg12 decode frame buffer information + * @vdec_fb_va : virtual address of struct vdec_fb + * @y_fb_dma : dma address of Y frame buffer (luma) + * @c_fb_dma : dma address of C frame buffer (chroma) + * @poc : picture order count of frame buffer + * @reserved : for 8 bytes alignment + */ +struct mpeg12_fb { + uint64_t vdec_fb_va; + uint64_t y_fb_dma; + uint64_t c_fb_dma; + int32_t poc; + uint32_t reserved; +}; + +/** + * struct vdec_mpeg12_dec_info - decode information + * @dpb_sz : decoding picture buffer size + * @resolution_changed : resoltion change happen + * @reserved : for 8 bytes alignment + * @bs_dma : Input bit-stream buffer dma address + * @y_fb_dma : Y frame buffer dma address + * @c_fb_dma : C frame buffer dma address + * @vdec_fb_va : VDEC frame buffer struct virtual address + */ +struct vdec_mpeg12_dec_info { + uint32_t dpb_sz; + uint32_t resolution_changed; + uint32_t reserved; + uint64_t bs_dma; + uint64_t y_fb_dma; + uint64_t c_fb_dma; + uint64_t vdec_fb_va; +}; + +/** + * struct vdec_mpeg12_vsi - shared memory for decode information exchange + * between VPU and Host. + * The memory is allocated by VPU then mapping to Host + * in vpu_dec_init() and freed in vpu_dec_deinit() + * by VPU. + * AP-W/R : AP is writer/reader on this item + * VPU-W/R: VPU is write/reader on this item + * @hdr_buf : Header parsing buffer (AP-W, VPU-R) + * @list_free : free frame buffer ring list (AP-W/R, VPU-W) + * @list_disp : display frame buffer ring list (AP-R, VPU-W) + * @dec : decode information (AP-R, VPU-W) + * @pic : picture information (AP-R, VPU-W) + * @crop : crop information (AP-R, VPU-W) + */ +struct vdec_mpeg12_vsi { + char *header_buf; + int sps_size; + int pps_size; + int sei_size; + int head_offset; + struct vdec_mpeg12_dec_info dec; + struct vdec_pic_info pic; + struct v4l2_rect crop; + bool is_combine; + int nalu_pos; + //struct mpeg12_param_sets ps; +}; + +/** + * struct vdec_mpeg12_inst - mpeg12 decoder instance + * @num_nalu : how many nalus be decoded + * @ctx : point to aml_vcodec_ctx + * @vsi : VPU shared information + */ +struct vdec_mpeg12_inst { + unsigned int num_nalu; + struct aml_vcodec_ctx *ctx; + struct aml_vdec_adapt vdec; + struct vdec_mpeg12_vsi *vsi; + struct vcodec_vfm_s vfm; +}; + +static void get_pic_info(struct vdec_mpeg12_inst *inst, + struct vdec_pic_info *pic) +{ + *pic = inst->vsi->pic; + + aml_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)", + pic->visible_width, pic->visible_height, + pic->coded_width, pic->coded_height); + aml_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz, + pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz); +} + +static void get_crop_info(struct vdec_mpeg12_inst *inst, struct v4l2_rect *cr) +{ + cr->left = inst->vsi->crop.left; + cr->top = inst->vsi->crop.top; + cr->width = inst->vsi->crop.width; + cr->height = inst->vsi->crop.height; + + aml_vcodec_debug(inst, "l=%d, t=%d, w=%d, h=%d", + cr->left, cr->top, cr->width, cr->height); +} + +static void get_dpb_size(struct vdec_mpeg12_inst *inst, unsigned int *dpb_sz) +{ + *dpb_sz = inst->vsi->dec.dpb_sz; + aml_vcodec_debug(inst, "sz=%d", *dpb_sz); +} + +static int vdec_mpeg12_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) +{ + struct vdec_mpeg12_inst *inst = NULL; + int ret = -1; + + inst = kzalloc(sizeof(*inst), GFP_KERNEL); + if (!inst) + return -ENOMEM; + + inst->ctx = ctx; + + inst->vdec.video_type = VFORMAT_MPEG12; + inst->vdec.dev = ctx->dev->vpu_plat_dev; + inst->vdec.filp = ctx->dev->filp; + inst->vdec.ctx = ctx; + + /* set play mode.*/ + if (ctx->is_drm_mode) + inst->vdec.port.flag |= PORT_FLAG_DRM; + + /* to eable mpeg12 hw.*/ + inst->vdec.port.type = PORT_TYPE_VIDEO; + + /* init vfm */ + inst->vfm.ctx = ctx; + inst->vfm.ada_ctx = &inst->vdec; + vcodec_vfm_init(&inst->vfm); + + ret = video_decoder_init(&inst->vdec); + if (ret) { + aml_vcodec_err(inst, "vdec_mpeg12 init err=%d", ret); + goto error_free_inst; + } + + /* probe info from the stream */ + inst->vsi = kzalloc(sizeof(struct vdec_mpeg12_vsi), GFP_KERNEL); + if (!inst->vsi) { + ret = -ENOMEM; + goto error_free_inst; + } + + /* alloc the header buffer to be used cache sps or spp etc.*/ + inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL); + if (!inst->vsi) { + ret = -ENOMEM; + goto error_free_vsi; + } + + inst->vsi->pic.visible_width = 1920; + inst->vsi->pic.visible_height = 1080; + inst->vsi->pic.coded_width = 1920; + inst->vsi->pic.coded_height = 1088; + inst->vsi->pic.y_bs_sz = 0; + inst->vsi->pic.y_len_sz = (1920 * 1088); + inst->vsi->pic.c_bs_sz = 0; + inst->vsi->pic.c_len_sz = (1920 * 1088 / 2); + + aml_vcodec_debug(inst, "mpeg12 Instance >> %p", inst); + + ctx->ada_ctx = &inst->vdec; + *h_vdec = (unsigned long)inst; + + //dump_init(); + + return 0; + +error_free_vsi: + kfree(inst->vsi); +error_free_inst: + kfree(inst); + *h_vdec = 0; + + return ret; +} + +static void fill_vdec_params(struct vdec_mpeg12_inst *inst, + struct MpvParseContext *dec_ps) +{ + struct vdec_pic_info *pic = &inst->vsi->pic; + struct vdec_mpeg12_dec_info *dec = &inst->vsi->dec; + struct v4l2_rect *rect = &inst->vsi->crop; + + /* fill visible area size that be used for EGL. */ + pic->visible_width = dec_ps->width; + pic->visible_height = dec_ps->height; + + /* calc visible ares. */ + rect->left = 0; + rect->top = 0; + rect->width = pic->visible_width; + rect->height = pic->visible_height; + + /* config canvas size that be used for decoder. */ + pic->coded_width = ALIGN(dec_ps->coded_width, 64); + pic->coded_height = ALIGN(dec_ps->coded_height, 64);; + + pic->y_len_sz = pic->coded_width * pic->coded_height; + pic->c_len_sz = pic->y_len_sz >> 1; + + /* calc DPB size */ + dec->dpb_sz = 9;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h); + + pr_info("[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n", + inst->ctx->id, pic->coded_width, pic->coded_height, + pic->visible_width, pic->visible_height, dec->dpb_sz); +} + +static int stream_parse(struct vdec_mpeg12_inst *inst, u8 *buf, u32 size) +{ + int ret = 0; + struct mpeg12_param_sets *ps = NULL; + + ps = kzalloc(sizeof(struct mpeg12_param_sets), GFP_KERNEL); + if (ps == NULL) + return -ENOMEM; + + ret = mpeg12_decode_extradata_ps(buf, size, ps); + if (ret) { + pr_err("parse extra data failed. err: %d\n", ret); + goto out; + } + + if (ps->head_parsed) + fill_vdec_params(inst, &ps->dec_ps); + + ret = ps->head_parsed ? 0 : -1; +out: + kfree(ps); + + return ret; +} + +static int vdec_mpeg12_probe(unsigned long h_vdec, + struct aml_vcodec_mem *bs, void *out) +{ + struct vdec_mpeg12_inst *inst = + (struct vdec_mpeg12_inst *)h_vdec; + struct stream_info *st; + u8 *buf = (u8 *)bs->vaddr; + u32 size = bs->size; + int ret = 0; + + st = (struct stream_info *)buf; + if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn)) + return 0; + + if (st->magic == NORe || st->magic == NORn) + ret = stream_parse(inst, st->data, st->length); + else + ret = stream_parse(inst, buf, size); + + return ret; +} + +static void vdec_mpeg12_deinit(unsigned long h_vdec) +{ + struct vdec_mpeg12_inst *inst = (struct vdec_mpeg12_inst *)h_vdec; + + if (!inst) + return; + + aml_vcodec_debug_enter(inst); + + video_decoder_release(&inst->vdec); + + vcodec_vfm_release(&inst->vfm); + + //dump_deinit(); + + if (inst->vsi && inst->vsi->header_buf) + kfree(inst->vsi->header_buf); + + if (inst->vsi) + kfree(inst->vsi); + + kfree(inst); +} + +static int vdec_mpeg12_get_fb(struct vdec_mpeg12_inst *inst, struct vdec_v4l2_buffer **out) +{ + return get_fb_from_queue(inst->ctx, out); +} + +static void vdec_mpeg12_get_vf(struct vdec_mpeg12_inst *inst, struct vdec_v4l2_buffer **out) +{ + struct vframe_s *vf = NULL; + struct vdec_v4l2_buffer *fb = NULL; + + vf = peek_video_frame(&inst->vfm); + if (!vf) { + aml_vcodec_debug(inst, "there is no vframe."); + *out = NULL; + return; + } + + vf = get_video_frame(&inst->vfm); + if (!vf) { + aml_vcodec_debug(inst, "the vframe is avalid."); + *out = NULL; + return; + } + + atomic_set(&vf->use_cnt, 1); + + fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle; + fb->vf_handle = (unsigned long)vf; + fb->status = FB_ST_DISPLAY; + + *out = fb; + + //pr_info("%s, %d\n", __func__, fb->base_y.bytes_used); + //dump_write(fb->base_y.va, fb->base_y.bytes_used); + //dump_write(fb->base_c.va, fb->base_c.bytes_used); + + /* convert yuv format. */ + //swap_uv(fb->base_c.va, fb->base_c.size); +} + +static int vdec_write_nalu(struct vdec_mpeg12_inst *inst, + u8 *buf, u32 size, u64 ts) +{ + int ret = 0; + struct aml_vdec_adapt *vdec = &inst->vdec; + + ret = vdec_vframe_write(vdec, buf, size, ts); + + return ret; +} + +static int vdec_mpeg12_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, + u64 timestamp, bool *res_chg) +{ + struct vdec_mpeg12_inst *inst = (struct vdec_mpeg12_inst *)h_vdec; + struct aml_vdec_adapt *vdec = &inst->vdec; + struct stream_info *st; + u8 *buf; + u32 size; + int ret = 0; + + /* bs NULL means flush decoder */ + if (bs == NULL) + return 0; + + buf = (u8 *)bs->vaddr; + size = bs->size; + st = (struct stream_info *)buf; + + if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn)) + ret = vdec_vbuf_write(vdec, st->m.buf, sizeof(st->m.drm)); + else if (st->magic == NORe) + ret = vdec_vbuf_write(vdec, st->data, st->length); + else if (st->magic == NORn) + ret = vdec_write_nalu(inst, st->data, st->length, timestamp); + else if (inst->ctx->is_stream_mode) + ret = vdec_vbuf_write(vdec, buf, size); + else + ret = vdec_write_nalu(inst, buf, size, timestamp); + + return ret; +} + +static int vdec_mpeg12_get_param(unsigned long h_vdec, + enum vdec_get_param_type type, void *out) +{ + int ret = 0; + struct vdec_mpeg12_inst *inst = (struct vdec_mpeg12_inst *)h_vdec; + + if (!inst) { + pr_err("the mpeg12 inst of dec is invalid.\n"); + return -1; + } + + switch (type) { + case GET_PARAM_DISP_FRAME_BUFFER: + vdec_mpeg12_get_vf(inst, out); + break; + + case GET_PARAM_FREE_FRAME_BUFFER: + ret = vdec_mpeg12_get_fb(inst, out); + break; + + case GET_PARAM_PIC_INFO: + get_pic_info(inst, out); + break; + + case GET_PARAM_DPB_SIZE: + get_dpb_size(inst, out); + break; + + case GET_PARAM_CROP_INFO: + get_crop_info(inst, out); + break; + + default: + aml_vcodec_err(inst, "invalid get parameter type=%d", type); + ret = -EINVAL; + } + + return ret; +} + +static void set_param_pic_info(struct vdec_mpeg12_inst *inst, + struct aml_vdec_pic_infos *info) +{ + pr_info("---%s, %d\n", __func__, __LINE__); +} + +static int vdec_mpeg12_set_param(unsigned long h_vdec, + enum vdec_set_param_type type, void *in) +{ + int ret = 0; + struct vdec_mpeg12_inst *inst = (struct vdec_mpeg12_inst *)h_vdec; + + if (!inst) { + pr_err("the mpeg12 inst of dec is invalid.\n"); + return -1; + } + + switch (type) { + case SET_PARAM_PIC_INFO: + set_param_pic_info(inst, in); + break; + + default: + aml_vcodec_err(inst, "invalid set parameter type=%d", type); + ret = -EINVAL; + } + + return ret; +} + +static struct vdec_common_if vdec_mpeg12_if = { + .init = vdec_mpeg12_init, + .probe = vdec_mpeg12_probe, + .decode = vdec_mpeg12_decode, + .get_param = vdec_mpeg12_get_param, + .set_param = vdec_mpeg12_set_param, + .deinit = vdec_mpeg12_deinit, +}; + +struct vdec_common_if *get_mpeg12_dec_comm_if(void); + +struct vdec_common_if *get_mpeg12_dec_comm_if(void) +{ + return &vdec_mpeg12_if; +} diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c new file mode 100644 index 0000000..7a40a4a --- a/dev/null +++ b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c @@ -0,0 +1,499 @@ +/* +* Copyright (C) 2017 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/timer.h> +#include <linux/delay.h> +#include <linux/kernel.h> +#include <uapi/linux/swab.h> +#include "../vdec_drv_if.h" +#include "../aml_vcodec_util.h" +#include "../aml_vcodec_dec.h" +#include "../aml_vcodec_adapt.h" +#include "../vdec_drv_base.h" +#include "../aml_vcodec_vfm.h" +#include "aml_mpeg4_parser.h" + +#define NAL_TYPE(value) ((value) & 0x1F) +#define HEADER_BUFFER_SIZE (32 * 1024) + +/** + * struct mpeg4_fb - mpeg4 decode frame buffer information + * @vdec_fb_va : virtual address of struct vdec_fb + * @y_fb_dma : dma address of Y frame buffer (luma) + * @c_fb_dma : dma address of C frame buffer (chroma) + * @poc : picture order count of frame buffer + * @reserved : for 8 bytes alignment + */ +struct mpeg4_fb { + uint64_t vdec_fb_va; + uint64_t y_fb_dma; + uint64_t c_fb_dma; + int32_t poc; + uint32_t reserved; +}; + +/** + * struct vdec_mpeg4_dec_info - decode information + * @dpb_sz : decoding picture buffer size + * @resolution_changed : resoltion change happen + * @reserved : for 8 bytes alignment + * @bs_dma : Input bit-stream buffer dma address + * @y_fb_dma : Y frame buffer dma address + * @c_fb_dma : C frame buffer dma address + * @vdec_fb_va : VDEC frame buffer struct virtual address + */ +struct vdec_mpeg4_dec_info { + uint32_t dpb_sz; + uint32_t resolution_changed; + uint32_t reserved; + uint64_t bs_dma; + uint64_t y_fb_dma; + uint64_t c_fb_dma; + uint64_t vdec_fb_va; +}; + +/** + * struct vdec_mpeg4_vsi - shared memory for decode information exchange + * between VPU and Host. + * The memory is allocated by VPU then mapping to Host + * in vpu_dec_init() and freed in vpu_dec_deinit() + * by VPU. + * AP-W/R : AP is writer/reader on this item + * VPU-W/R: VPU is write/reader on this item + * @hdr_buf : Header parsing buffer (AP-W, VPU-R) + * @list_free : free frame buffer ring list (AP-W/R, VPU-W) + * @list_disp : display frame buffer ring list (AP-R, VPU-W) + * @dec : decode information (AP-R, VPU-W) + * @pic : picture information (AP-R, VPU-W) + * @crop : crop information (AP-R, VPU-W) + */ +struct vdec_mpeg4_vsi { + char *header_buf; + int sps_size; + int pps_size; + int sei_size; + int head_offset; + struct vdec_mpeg4_dec_info dec; + struct vdec_pic_info pic; + struct v4l2_rect crop; + bool is_combine; + int nalu_pos; + //struct mpeg4ParamSets ps; +}; + +/** + * struct vdec_mpeg4_inst - mpeg4 decoder instance + * @num_nalu : how many nalus be decoded + * @ctx : point to aml_vcodec_ctx + * @vsi : VPU shared information + */ +struct vdec_mpeg4_inst { + unsigned int num_nalu; + struct aml_vcodec_ctx *ctx; + struct aml_vdec_adapt vdec; + struct vdec_mpeg4_vsi *vsi; + struct vcodec_vfm_s vfm; +}; + +static void get_pic_info(struct vdec_mpeg4_inst *inst, + struct vdec_pic_info *pic) +{ + *pic = inst->vsi->pic; + + aml_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)", + pic->visible_width, pic->visible_height, + pic->coded_width, pic->coded_height); + aml_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz, + pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz); +} + +static void get_crop_info(struct vdec_mpeg4_inst *inst, struct v4l2_rect *cr) +{ + cr->left = inst->vsi->crop.left; + cr->top = inst->vsi->crop.top; + cr->width = inst->vsi->crop.width; + cr->height = inst->vsi->crop.height; + + aml_vcodec_debug(inst, "l=%d, t=%d, w=%d, h=%d", + cr->left, cr->top, cr->width, cr->height); +} + +static void get_dpb_size(struct vdec_mpeg4_inst *inst, unsigned int *dpb_sz) +{ + *dpb_sz = 9;//inst->vsi->dec.dpb_sz; + aml_vcodec_debug(inst, "sz=%d", *dpb_sz); +} + +static int vdec_mpeg4_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) +{ + struct vdec_mpeg4_inst *inst = NULL; + int ret = -1; + + inst = kzalloc(sizeof(*inst), GFP_KERNEL); + if (!inst) + return -ENOMEM; + + inst->ctx = ctx; + + inst->vdec.video_type = VFORMAT_MPEG4; + inst->vdec.format = VIDEO_DEC_FORMAT_MPEG4_5; + inst->vdec.dev = ctx->dev->vpu_plat_dev; + inst->vdec.filp = ctx->dev->filp; + inst->vdec.ctx = ctx; + + /* set play mode.*/ + if (ctx->is_drm_mode) + inst->vdec.port.flag |= PORT_FLAG_DRM; + + /* to eable mpeg4 hw.*/ + inst->vdec.port.type = PORT_TYPE_VIDEO; + + /* init vfm */ + inst->vfm.ctx = ctx; + inst->vfm.ada_ctx = &inst->vdec; + vcodec_vfm_init(&inst->vfm); + + ret = video_decoder_init(&inst->vdec); + if (ret) { + aml_vcodec_err(inst, "vdec_mpeg4 init err=%d", ret); + goto error_free_inst; + } + + /* probe info from the stream */ + inst->vsi = kzalloc(sizeof(struct vdec_mpeg4_vsi), GFP_KERNEL); + if (!inst->vsi) { + ret = -ENOMEM; + goto error_free_inst; + } + + /* alloc the header buffer to be used cache sps or spp etc.*/ + inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL); + if (!inst->vsi) { + ret = -ENOMEM; + goto error_free_vsi; + } + + inst->vsi->pic.visible_width = 1920; + inst->vsi->pic.visible_height = 1080; + inst->vsi->pic.coded_width = 1920; + inst->vsi->pic.coded_height = 1088; + inst->vsi->pic.y_bs_sz = 0; + inst->vsi->pic.y_len_sz = (1920 * 1088); + inst->vsi->pic.c_bs_sz = 0; + inst->vsi->pic.c_len_sz = (1920 * 1088 / 2); + + aml_vcodec_debug(inst, "mpeg4 Instance >> %p", inst); + + ctx->ada_ctx = &inst->vdec; + *h_vdec = (unsigned long)inst; + + //dump_init(); + + return 0; + +error_free_vsi: + kfree(inst->vsi); +error_free_inst: + kfree(inst); + *h_vdec = 0; + + return ret; +} + +#if 0 +static int refer_buffer_num(int level_idc, int poc_cnt, + int mb_width, int mb_height) +{ + return 20; +} +#endif + +static void fill_vdec_params(struct vdec_mpeg4_inst *inst, + struct mpeg4_dec_param *dec_ps) +{ + struct vdec_pic_info *pic = &inst->vsi->pic; + struct vdec_mpeg4_dec_info *dec = &inst->vsi->dec; + struct v4l2_rect *rect = &inst->vsi->crop; + + /* fill visible area size that be used for EGL. */ + pic->visible_width = dec_ps->m.width; + pic->visible_height = dec_ps->m.height; + + /* calc visible ares. */ + rect->left = 0; + rect->top = 0; + rect->width = pic->visible_width; + rect->height = pic->visible_height; + + /* config canvas size that be used for decoder. */ + pic->coded_width = ALIGN(dec_ps->m.width, 64); + pic->coded_height = ALIGN(dec_ps->m.height, 64); + + pic->y_len_sz = pic->coded_width * pic->coded_height; + pic->c_len_sz = pic->y_len_sz >> 1; + + /* calc DPB size */ + dec->dpb_sz = 9;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h); + + pr_info("[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n", + inst->ctx->id, pic->coded_width, pic->coded_height, + pic->visible_width, pic->visible_height, dec->dpb_sz); +} + +static int stream_parse(struct vdec_mpeg4_inst *inst, u8 *buf, u32 size) +{ + int ret = 0; + struct mpeg4_param_sets *ps = NULL; + + ps = kzalloc(sizeof(struct mpeg4_param_sets), GFP_KERNEL); + if (ps == NULL) + return -ENOMEM; + + ret = mpeg4_decode_extradata_ps(buf, size, ps); + if (ret) { + pr_err("parse extra data failed. err: %d\n", ret); + goto out; + } + + if (ps->head_parsed) + fill_vdec_params(inst, &ps->dec_ps); + + ret = ps->head_parsed ? 0 : -1; +out: + kfree(ps); + + return ret; +} + +static int vdec_mpeg4_probe(unsigned long h_vdec, + struct aml_vcodec_mem *bs, void *out) +{ + struct vdec_mpeg4_inst *inst = + (struct vdec_mpeg4_inst *)h_vdec; + struct stream_info *st; + u8 *buf = (u8 *)bs->vaddr; + u32 size = bs->size; + int ret = 0; + + st = (struct stream_info *)buf; + if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn)) + return 0; + + if (st->magic == NORe || st->magic == NORn) + ret = stream_parse(inst, st->data, st->length); + else + ret = stream_parse(inst, buf, size); + + return ret; +} + +static void vdec_mpeg4_deinit(unsigned long h_vdec) +{ + struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec; + + if (!inst) + return; + + aml_vcodec_debug_enter(inst); + + video_decoder_release(&inst->vdec); + + vcodec_vfm_release(&inst->vfm); + + //dump_deinit(); + + if (inst->vsi && inst->vsi->header_buf) + kfree(inst->vsi->header_buf); + + if (inst->vsi) + kfree(inst->vsi); + + kfree(inst); +} + +static int vdec_mpeg4_get_fb(struct vdec_mpeg4_inst *inst, struct vdec_v4l2_buffer **out) +{ + return get_fb_from_queue(inst->ctx, out); +} + +static void vdec_mpeg4_get_vf(struct vdec_mpeg4_inst *inst, struct vdec_v4l2_buffer **out) +{ + struct vframe_s *vf = NULL; + struct vdec_v4l2_buffer *fb = NULL; + + vf = peek_video_frame(&inst->vfm); + if (!vf) { + aml_vcodec_debug(inst, "there is no vframe."); + *out = NULL; + return; + } + + vf = get_video_frame(&inst->vfm); + if (!vf) { + aml_vcodec_debug(inst, "the vframe is avalid."); + *out = NULL; + return; + } + + atomic_set(&vf->use_cnt, 1); + + fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle; + fb->vf_handle = (unsigned long)vf; + fb->status = FB_ST_DISPLAY; + + *out = fb; + + //pr_info("%s, %d\n", __func__, fb->base_y.bytes_used); + //dump_write(fb->base_y.va, fb->base_y.bytes_used); + //dump_write(fb->base_c.va, fb->base_c.bytes_used); + + /* convert yuv format. */ + //swap_uv(fb->base_c.va, fb->base_c.size); +} + +static int vdec_write_nalu(struct vdec_mpeg4_inst *inst, + u8 *buf, u32 size, u64 ts) +{ + int ret = 0; + struct aml_vdec_adapt *vdec = &inst->vdec; + + ret = vdec_vframe_write(vdec, buf, size, ts); + + return ret; +} + +static int vdec_mpeg4_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, + u64 timestamp, bool *res_chg) +{ + struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec; + struct aml_vdec_adapt *vdec = &inst->vdec; + struct stream_info *st; + u8 *buf; + u32 size; + int ret = 0; + + /* bs NULL means flush decoder */ + if (bs == NULL) + return 0; + + buf = (u8 *)bs->vaddr; + size = bs->size; + st = (struct stream_info *)buf; + + if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn)) + ret = vdec_vbuf_write(vdec, st->m.buf, sizeof(st->m.drm)); + else if (st->magic == NORe) + ret = vdec_vbuf_write(vdec, st->data, st->length); + else if (st->magic == NORn) + ret = vdec_write_nalu(inst, st->data, st->length, timestamp); + else if (inst->ctx->is_stream_mode) + ret = vdec_vbuf_write(vdec, buf, size); + else + ret = vdec_write_nalu(inst, buf, size, timestamp); + + return ret; +} + +static int vdec_mpeg4_get_param(unsigned long h_vdec, + enum vdec_get_param_type type, void *out) +{ + int ret = 0; + struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec; + + if (!inst) { + pr_err("the mpeg4 inst of dec is invalid.\n"); + return -1; + } + + switch (type) { + case GET_PARAM_DISP_FRAME_BUFFER: + vdec_mpeg4_get_vf(inst, out); + break; + + case GET_PARAM_FREE_FRAME_BUFFER: + ret = vdec_mpeg4_get_fb(inst, out); + break; + + case GET_PARAM_PIC_INFO: + get_pic_info(inst, out); + break; + + case GET_PARAM_DPB_SIZE: + get_dpb_size(inst, out); + break; + + case GET_PARAM_CROP_INFO: + get_crop_info(inst, out); + break; + + default: + aml_vcodec_err(inst, "invalid get parameter type=%d", type); + ret = -EINVAL; + } + + return ret; +} + +static void set_param_pic_info(struct vdec_mpeg4_inst *inst, + struct aml_vdec_pic_infos *info) +{ + pr_info("---%s, %d\n", __func__, __LINE__); +} + +static int vdec_mpeg4_set_param(unsigned long h_vdec, + enum vdec_set_param_type type, void *in) +{ + int ret = 0; + struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec; + + if (!inst) { + pr_err("the mpeg4 inst of dec is invalid.\n"); + return -1; + } + + switch (type) { + case SET_PARAM_PIC_INFO: + set_param_pic_info(inst, in); + break; + + default: + aml_vcodec_err(inst, "invalid set parameter type=%d", type); + ret = -EINVAL; + } + + return ret; +} + +static struct vdec_common_if vdec_mpeg4_if = { + .init = vdec_mpeg4_init, + .probe = vdec_mpeg4_probe, + .decode = vdec_mpeg4_decode, + .get_param = vdec_mpeg4_get_param, + .set_param = vdec_mpeg4_set_param, + .deinit = vdec_mpeg4_deinit, +}; + +struct vdec_common_if *get_mpeg4_dec_comm_if(void); + +struct vdec_common_if *get_mpeg4_dec_comm_if(void) +{ + return &vdec_mpeg4_if; +} diff --git a/drivers/amvdec_ports/decoder/vdec_vp9_if.c b/drivers/amvdec_ports/decoder/vdec_vp9_if.c index 757be84..5b3bbab 100644 --- a/drivers/amvdec_ports/decoder/vdec_vp9_if.c +++ b/drivers/amvdec_ports/decoder/vdec_vp9_if.c @@ -36,7 +36,9 @@ #define NAL_TYPE(value) ((value) & 0x1F) #define HEADER_BUFFER_SIZE (32 * 1024) +#define SYNC_CODE (0x498342) +extern int vp9_need_prefix; bool need_trigger; int dump_cnt = 0; @@ -99,10 +101,11 @@ struct vdec_vp9_vsi { int head_offset; struct vdec_vp9_dec_info dec; struct vdec_pic_info pic; + struct vdec_pic_info cur_pic; struct v4l2_rect crop; bool is_combine; int nalu_pos; - struct vp9_head_info_t head; + struct vp9_param_sets ps; }; /** @@ -117,71 +120,11 @@ struct vdec_vp9_inst { struct aml_vdec_adapt vdec; struct vdec_vp9_vsi *vsi; struct vcodec_vfm_s vfm; + struct completion comp; }; -struct vp9_superframe_split { - /*in data*/ - u8 *data; - u32 data_size; - - /*out data*/ - int nb_frames; - int size; - int next_frame; - u32 next_frame_offset; - int sizes[8]; -}; - -#if 1 -#define DUMP_FILE_NAME "/data/dump/dump.tmp" -static struct file *filp; -static loff_t file_pos; - -void dump_write(const char __user *buf, size_t count) -{ - mm_segment_t old_fs; - - if (!filp) - return; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - - if (count != vfs_write(filp, buf, count, &file_pos)) - pr_err("Failed to write file\n"); - - set_fs(old_fs); -} - -void dump_init(void) -{ - filp = filp_open(DUMP_FILE_NAME, O_CREAT | O_RDWR, 0644); - if (IS_ERR(filp)) { - pr_err("open dump file failed\n"); - filp = NULL; - } -} - -void dump_deinit(void) -{ - if (filp) { - filp_close(filp, current->files); - filp = NULL; - file_pos = 0; - } -} - -void swap_uv(void *uv, int size) -{ - int i; - __u16 *p = uv; - - size /= 2; - - for (i = 0; i < size; i++, p++) - *p = __swab16(*p); -} -#endif +static int vdec_write_nalu(struct vdec_vp9_inst *inst, + u8 *buf, u32 size, u64 ts); static void get_pic_info(struct vdec_vp9_inst *inst, struct vdec_pic_info *pic) @@ -208,7 +151,7 @@ static void get_crop_info(struct vdec_vp9_inst *inst, struct v4l2_rect *cr) static void get_dpb_size(struct vdec_vp9_inst *inst, unsigned int *dpb_sz) { - *dpb_sz = 20;//inst->vsi->dec.dpb_sz; + *dpb_sz = inst->vsi->dec.dpb_sz; aml_vcodec_debug(inst, "sz=%d", *dpb_sz); } @@ -223,7 +166,7 @@ static int vdec_vp9_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) inst->ctx = ctx; - inst->vdec.format = VFORMAT_VP9; + inst->vdec.video_type = VFORMAT_VP9; inst->vdec.dev = ctx->dev->vpu_plat_dev; inst->vdec.filp = ctx->dev->filp; inst->vdec.ctx = ctx; @@ -263,6 +206,8 @@ static int vdec_vp9_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) inst->vsi->pic.c_bs_sz = 0; inst->vsi->pic.c_len_sz = (1920 * 1088 / 2); + init_completion(&inst->comp); + aml_vcodec_debug(inst, "vp9 Instance >> %p", inst); ctx->ada_ctx = &inst->vdec; @@ -275,7 +220,7 @@ static int vdec_vp9_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) goto error_free_inst; } - dump_init(); + //dump_init(); return 0; @@ -296,22 +241,16 @@ static int refer_buffer_num(int level_idc, int poc_cnt, } #endif -static void fill_vdec_params(struct vdec_vp9_inst *inst) +static void fill_vdec_params(struct vdec_vp9_inst *inst, + struct VP9Context *vp9_ctx) { struct vdec_pic_info *pic = &inst->vsi->pic; struct vdec_vp9_dec_info *dec = &inst->vsi->dec; struct v4l2_rect *rect = &inst->vsi->crop; - unsigned int mb_w = 0, mb_h = 0, width, height; - //unsigned int crop_unit_x = 0, crop_unit_y = 0; - //unsigned int poc_cnt = 0; - - /* calc width & height. */ - width = 1920; - height = 1080; /* fill visible area size that be used for EGL. */ - pic->visible_width = width; - pic->visible_height = height; + pic->visible_width = vp9_ctx->render_width; + pic->visible_height = vp9_ctx->render_height; /* calc visible ares. */ rect->left = 0; @@ -320,82 +259,60 @@ static void fill_vdec_params(struct vdec_vp9_inst *inst) rect->height = pic->visible_height; /* config canvas size that be used for decoder. */ - pic->coded_width = ALIGN(mb_w, 4) << 4; - pic->coded_height = ALIGN(mb_h, 4) << 4; - - pic->coded_width = 1920; - pic->coded_height = 1088;//temp + pic->coded_width = ALIGN(vp9_ctx->width, 32); + pic->coded_height = ALIGN(vp9_ctx->height, 32); pic->y_len_sz = pic->coded_width * pic->coded_height; pic->c_len_sz = pic->y_len_sz >> 1; /* calc DPB size */ - dec->dpb_sz = 20;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h); + dec->dpb_sz = 5;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h); - pr_info("[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n", + aml_vcodec_debug(inst, "[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n", inst->ctx->id, pic->coded_width, pic->coded_height, pic->visible_width, pic->visible_height, dec->dpb_sz); } -#if 0 -static int vp9_parse_nal_header(u32 val) +static int stream_parse_by_ucode(struct vdec_vp9_inst *inst, u8 *buf, u32 size) { - if (val & 0x80) { - pr_err("the nal data is invalid.\n"); - return -1; - } - - return (val & 0x7f) >> 1; -} -#endif + int ret = 0; -static void vp9_parse(struct vp9_head_info_t *head, u8 *buf, u32 size) -{ - //int ret = -1; - //u8 *p = buf; + ret = vdec_write_nalu(inst, buf, size, 0); + if (ret < 0) { + pr_err("write frame data failed. err: %d\n", ret); + return ret; + } - head->parsed = true; + /* wait ucode parse ending. */ + wait_for_completion_timeout(&inst->comp, + msecs_to_jiffies(1000)); - return; + return inst->vsi->dec.dpb_sz ? 0 : -1; } static int stream_parse(struct vdec_vp9_inst *inst, u8 *buf, u32 size) { - //struct vp9_stream_t s; - //struct vp9_SPS_t *sps; - //unsigned int nal_type; - int nal_idx = 0; - int real_data_pos, real_data_size; - bool is_combine = false; - - vp9_parse(&inst->vsi->head, buf, size); - - if (!inst->vsi->head.parsed) - return -1; - - /* if the st compose from csd + slice that is the combine data. */ - inst->vsi->is_combine = is_combine; - inst->vsi->nalu_pos = nal_idx; - - /* start code plus nal type. */ - real_data_pos = nal_idx + 1; - real_data_size = size - real_data_pos; + int ret = 0; + struct vp9_param_sets *ps = NULL; - //sps = kzalloc(sizeof(struct vp9_SPS_t), GFP_KERNEL); - //if (sps == NULL) - //return -ENOMEM; + ps = kzalloc(sizeof(struct vp9_param_sets), GFP_KERNEL); + if (ps == NULL) + return -ENOMEM; - /* the extra data would be parsed. */ - //vp9_stream_set(&s, &buf[real_data_pos], real_data_size); - //vp9_sps_parse(&s, sps); - //vp9_sps_info(sps); + ret = vp9_decode_extradata_ps(buf, size, ps); + if (ret) { + pr_err("parse extra data failed. err: %d\n", ret); + goto out; + } - //fill_vdec_params(inst, sps); - fill_vdec_params(inst); + if (ps->head_parsed) + fill_vdec_params(inst, &ps->ctx); - //kfree(sps); + ret = ps->head_parsed ? 0 : -1; +out: + kfree(ps); - return 0; + return ret; } static int vdec_vp9_probe(unsigned long h_vdec, @@ -404,7 +321,7 @@ static int vdec_vp9_probe(unsigned long h_vdec, struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec; struct stream_info *st; - u8 *buf = (u8 *)bs->va; + u8 *buf = (u8 *)bs->vaddr; u32 size = bs->size; int ret = 0; @@ -414,18 +331,23 @@ static int vdec_vp9_probe(unsigned long h_vdec, if (st->magic == NORe || st->magic == NORn) ret = stream_parse(inst, st->data, st->length); - else - ret = stream_parse(inst, buf, size); + else { + if (inst->ctx->param_sets_from_ucode) + ret = stream_parse_by_ucode(inst, buf, size); + else + ret = stream_parse(inst, buf, size); + } + + inst->vsi->cur_pic = inst->vsi->pic; return ret; } static void vdec_vp9_deinit(unsigned long h_vdec) { + ulong flags; struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec; - - if (!inst) - return; + struct aml_vcodec_ctx *ctx = inst->ctx; aml_vcodec_debug_enter(inst); @@ -433,8 +355,9 @@ static void vdec_vp9_deinit(unsigned long h_vdec) vcodec_vfm_release(&inst->vfm); - dump_deinit(); + //dump_deinit(); + spin_lock_irqsave(&ctx->slock, flags); if (inst->vsi && inst->vsi->header_buf) kfree(inst->vsi->header_buf); @@ -442,22 +365,23 @@ static void vdec_vp9_deinit(unsigned long h_vdec) kfree(inst->vsi); kfree(inst); + + ctx->drv_handle = 0; + spin_unlock_irqrestore(&ctx->slock, flags); + need_trigger = false; dump_cnt = 0; } -static int vdec_vp9_get_fb(struct vdec_vp9_inst *inst, struct vdec_fb **out) +static int vdec_vp9_get_fb(struct vdec_vp9_inst *inst, struct vdec_v4l2_buffer **out) { return get_fb_from_queue(inst->ctx, out); } -static void vdec_vp9_get_vf(struct vdec_vp9_inst *inst, struct vdec_fb **out) +static void vdec_vp9_get_vf(struct vdec_vp9_inst *inst, struct vdec_v4l2_buffer **out) { struct vframe_s *vf = NULL; - struct vdec_fb *fb = NULL; - - aml_vcodec_debug(inst, "%s() [%d], vfm: %p", - __func__, __LINE__, &inst->vfm); + struct vdec_v4l2_buffer *fb = NULL; vf = peek_video_frame(&inst->vfm); if (!vf) { @@ -475,107 +399,18 @@ static void vdec_vp9_get_vf(struct vdec_vp9_inst *inst, struct vdec_fb **out) atomic_set(&vf->use_cnt, 1); - aml_vcodec_debug(inst, "%s() [%d], vf: %p, v4l_mem_handle: %lx, idx: %d\n", - __func__, __LINE__, vf, vf->v4l_mem_handle, vf->index); - - fb = (struct vdec_fb *)vf->v4l_mem_handle; + fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle; fb->vf_handle = (unsigned long)vf; fb->status = FB_ST_DISPLAY; *out = fb; //pr_info("%s, %d\n", __func__, fb->base_y.bytes_used); - //dump_write(fb->base_y.va, fb->base_y.bytes_used); - //dump_write(fb->base_c.va, fb->base_c.bytes_used); + //dump_write(fb->base_y.vaddr, fb->base_y.bytes_used); + //dump_write(fb->base_c.vaddr, fb->base_c.bytes_used); /* convert yuv format. */ - //swap_uv(fb->base_c.va, fb->base_c.size); - - aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu", - __func__, __LINE__, fb->base_y.va, - (unsigned int)virt_to_phys(fb->base_y.va), fb->base_y.size); - aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu", - __func__, __LINE__, fb->base_c.va, - (unsigned int)virt_to_phys(fb->base_c.va), fb->base_c.size); -} - -static int vp9_superframe_split_filter(struct vp9_superframe_split *s) -{ - int i, j, ret, marker; - bool is_superframe = false; - - if (!s->data) - return -1; - - marker = s->data[s->data_size - 1]; - if ((marker & 0xe0) == 0xc0) { - int length_size = 1 + ((marker >> 3) & 0x3); - int nb_frames = 1 + (marker & 0x7); - int idx_size = 2 + nb_frames * length_size; - - if (s->data_size >= idx_size && - s->data[s->data_size - idx_size] == marker) { - s64 total_size = 0; - int idx = s->data_size + 1 - idx_size; - - for (i = 0; i < nb_frames; i++) { - int frame_size = 0; - for (j = 0; j < length_size; j++) - frame_size |= s->data[idx++] << (j * 8); - - total_size += frame_size; - if (frame_size < 0 || - total_size > s->data_size - idx_size) { - pr_err( "Invalid frame size in a sframe: %d\n", - frame_size); - ret = -EINVAL; - goto fail; - } - s->sizes[i] = frame_size; - } - - s->nb_frames = nb_frames; - s->size = total_size; - s->next_frame = 0; - s->next_frame_offset = 0; - is_superframe = true; - } - }else { - s->nb_frames = 1; - s->sizes[0] = s->data_size; - s->size = s->data_size; - } - - /*pr_info("sframe: %d, frames: %d, IN: %x, OUT: %x\n", - is_superframe, s->nb_frames, - s->data_size, s->size);*/ - - /* parse uncompressed header. */ - if (is_superframe) { - /* bitstream profile. */ - /* frame type. (intra or inter) */ - /* colorspace descriptor */ - /* ... */ - - pr_info("the frame is a superframe.\n"); - } - - /*pr_err("in: %x, %d, out: %x, sizes %d,%d,%d,%d,%d,%d,%d,%d\n", - s->data_size, - s->nb_frames, - s->size, - s->sizes[0], - s->sizes[1], - s->sizes[2], - s->sizes[3], - s->sizes[4], - s->sizes[5], - s->sizes[6], - s->sizes[7]);*/ - - return 0; -fail: - return ret; + //swap_uv(fb->base_c.vaddr, fb->base_c.size); } static void add_prefix_data(struct vp9_superframe_split *s, @@ -604,7 +439,7 @@ static void add_prefix_data(struct vp9_superframe_split *s, prefix = p + PREFIX_SIZE * (i - 1); /*add amlogic frame headers.*/ - frame_size += 4; + frame_size += 16; prefix[0] = (frame_size >> 24) & 0xff; prefix[1] = (frame_size >> 16) & 0xff; prefix[2] = (frame_size >> 8 ) & 0xff; @@ -621,7 +456,7 @@ static void add_prefix_data(struct vp9_superframe_split *s, prefix[13] = 'M'; prefix[14] = 'L'; prefix[15] = 'V'; - frame_size -= 4; + frame_size -= 16; } *out = p; @@ -651,6 +486,7 @@ static int vdec_write_nalu(struct vdec_vp9_inst *inst, struct vp9_superframe_split s; u8 *data = NULL; u32 length = 0; + bool need_prefix = vp9_need_prefix; memset(&s, 0, sizeof(s)); @@ -660,43 +496,65 @@ static int vdec_write_nalu(struct vdec_vp9_inst *inst, need_trigger = true; } - /*parse superframe.*/ - s.data = buf; - s.data_size = size; - ret = vp9_superframe_split_filter(&s); - if (ret) { - pr_err("parse frames failed.\n"); - return ret; - } - - /*add headers.*/ - add_prefix_data(&s, &data, &length); + if (need_prefix) { + /*parse superframe.*/ + s.data = buf; + s.data_size = size; + ret = vp9_superframe_split_filter(&s); + if (ret) { + pr_err("parse frames failed.\n"); + return ret; + } - ret = vdec_vframe_write(vdec, data, length, ts); + /*add headers.*/ + add_prefix_data(&s, &data, &length); + ret = vdec_vframe_write(vdec, data, length, ts); + vfree(data); + } else { + ret = vdec_vframe_write(vdec, buf, size, ts); + } - aml_vcodec_debug(inst, "buf: %p, buf size: %u, write to: %d", - data, length, ret); + return ret; +} - vfree(data); +static bool monitor_res_change(struct vdec_vp9_inst *inst, u8 *buf, u32 size) +{ + int ret = -1; + u8 *p = buf; + int len = size; + u32 synccode = vp9_need_prefix ? + ((p[1] << 16) | (p[2] << 8) | p[3]) : + ((p[17] << 16) | (p[18] << 8) | p[19]); + + if (synccode == SYNC_CODE) { + ret = stream_parse(inst, p, len); + if (!ret && (inst->vsi->cur_pic.coded_width != + inst->vsi->pic.coded_width || + inst->vsi->cur_pic.coded_height != + inst->vsi->pic.coded_height)) { + inst->vsi->cur_pic = inst->vsi->pic; + return true; + } + } - return 0; + return false; } static int vdec_vp9_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, - unsigned long int timestamp, bool *res_chg) + u64 timestamp, bool *res_chg) { struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec; struct aml_vdec_adapt *vdec = &inst->vdec; struct stream_info *st; u8 *buf; u32 size; - int ret = 0; + int ret = -1; /* bs NULL means flush decoder */ if (bs == NULL) - return 0; + return -1; - buf = (u8 *)bs->va; + buf = (u8 *)bs->vaddr; size = bs->size; st = (struct stream_info *)buf; @@ -708,8 +566,13 @@ static int vdec_vp9_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, ret = vdec_write_nalu(inst, st->data, st->length, timestamp); else if (inst->ctx->is_stream_mode) ret = vdec_vbuf_write(vdec, buf, size); - else + else { + /*checked whether the resolution changes.*/ + if ((*res_chg = monitor_res_change(inst, buf, size))) + return 0; + ret = vdec_write_nalu(inst, buf, size, timestamp); + } return ret; } @@ -754,12 +617,82 @@ static int vdec_vp9_get_param(unsigned long h_vdec, return ret; } +static void set_param_write_sync(struct vdec_vp9_inst *inst) +{ + complete(&inst->comp); +} + +static void set_param_pic_info(struct vdec_vp9_inst *inst, + struct aml_vdec_pic_infos *info) +{ + struct vdec_pic_info *pic = &inst->vsi->pic; + struct vdec_vp9_dec_info *dec = &inst->vsi->dec; + struct v4l2_rect *rect = &inst->vsi->crop; + + /* fill visible area size that be used for EGL. */ + pic->visible_width = info->visible_width; + pic->visible_height = info->visible_height; + + /* calc visible ares. */ + rect->left = 0; + rect->top = 0; + rect->width = pic->visible_width; + rect->height = pic->visible_height; + + /* config canvas size that be used for decoder. */ + pic->coded_width = info->coded_width; + pic->coded_height = info->coded_height; + + pic->y_len_sz = pic->coded_width * pic->coded_height; + pic->c_len_sz = pic->y_len_sz >> 1; + + /* calc DPB size */ + dec->dpb_sz = 5; + + /*wake up*/ + complete(&inst->comp); + + pr_info("Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d\n", + info->visible_width, info->visible_height, + info->coded_width, info->coded_height, + info->dpb_size); +} + +static int vdec_vp9_set_param(unsigned long h_vdec, + enum vdec_set_param_type type, void *in) +{ + int ret = 0; + struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec; + + if (!inst) { + pr_err("the vp9 inst of dec is invalid.\n"); + return -1; + } + + switch (type) { + case SET_PARAM_WRITE_FRAME_SYNC: + set_param_write_sync(inst); + break; + + case SET_PARAM_PIC_INFO: + set_param_pic_info(inst, in); + break; + + default: + aml_vcodec_err(inst, "invalid set parameter type=%d", type); + ret = -EINVAL; + } + + return ret; +} + static struct vdec_common_if vdec_vp9_if = { - vdec_vp9_init, - vdec_vp9_probe, - vdec_vp9_decode, - vdec_vp9_get_param, - vdec_vp9_deinit, + .init = vdec_vp9_init, + .probe = vdec_vp9_probe, + .decode = vdec_vp9_decode, + .get_param = vdec_vp9_get_param, + .set_param = vdec_vp9_set_param, + .deinit = vdec_vp9_deinit, }; struct vdec_common_if *get_vp9_dec_comm_if(void); diff --git a/drivers/amvdec_ports/decoder/vdec_vp9_trigger.h b/drivers/amvdec_ports/decoder/vdec_vp9_trigger.h index 0097690..0097690 100755..100644 --- a/drivers/amvdec_ports/decoder/vdec_vp9_trigger.h +++ b/drivers/amvdec_ports/decoder/vdec_vp9_trigger.h diff --git a/drivers/amvdec_ports/test/vcodec_m2m_test.c b/drivers/amvdec_ports/test/vcodec_m2m_test.c index 0110676..bec040b 100644 --- a/drivers/amvdec_ports/test/vcodec_m2m_test.c +++ b/drivers/amvdec_ports/test/vcodec_m2m_test.c @@ -157,6 +157,24 @@ static void* read_thread(void *arg) case AV_CODEC_ID_VP9: forced_codec_name = "vp9_v4l2m2m"; break; + case AV_CODEC_ID_MPEG1VIDEO: + forced_codec_name = "mpeg1_v4l2m2m"; + break; + case AV_CODEC_ID_MPEG2VIDEO: + forced_codec_name = "mpeg2_v4l2m2m"; + break; + case AV_CODEC_ID_VC1: + forced_codec_name = "vc1_v4l2m2m"; + break; + case AV_CODEC_ID_H263: + forced_codec_name = "h263_v4l2m2m"; + break; + case AV_CODEC_ID_MPEG4: + forced_codec_name = "mpeg4_v4l2m2m"; + break; + case AV_CODEC_ID_MJPEG: + forced_codec_name = "mjpeg_v4l2m2m"; + break; } codec = avcodec_find_decoder_by_name(forced_codec_name); diff --git a/drivers/amvdec_ports/utils/common.c b/drivers/amvdec_ports/utils/common.c new file mode 100644 index 0000000..aa5c71b --- a/dev/null +++ b/drivers/amvdec_ports/utils/common.c @@ -0,0 +1,221 @@ +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/vmalloc.h> +#include <linux/mm.h> +#include <linux/string.h> + +#include "common.h" +#include "pixfmt.h" + +const u8 ff_zigzag_direct[64] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 +}; + +const u8 ff_zigzag_scan[16 + 1] = { + 0 + 0 * 4, 1 + 0 * 4, 0 + 1 * 4, 0 + 2 * 4, + 1 + 1 * 4, 2 + 0 * 4, 3 + 0 * 4, 2 + 1 * 4, + 1 + 2 * 4, 0 + 3 * 4, 1 + 3 * 4, 2 + 2 * 4, + 3 + 1 * 4, 3 + 2 * 4, 2 + 3 * 4, 3 + 3 * 4, +}; + +const char * const color_space_names[] = { + [AVCOL_SPC_RGB] = "gbr", + [AVCOL_SPC_BT709] = "bt709", + [AVCOL_SPC_UNSPECIFIED] = "unknown", + [AVCOL_SPC_RESERVED] = "reserved", + [AVCOL_SPC_FCC] = "fcc", + [AVCOL_SPC_BT470BG] = "bt470bg", + [AVCOL_SPC_SMPTE170M] = "smpte170m", + [AVCOL_SPC_SMPTE240M] = "smpte240m", + [AVCOL_SPC_YCGCO] = "ycgco", + [AVCOL_SPC_BT2020_NCL] = "bt2020nc", + [AVCOL_SPC_BT2020_CL] = "bt2020c", + [AVCOL_SPC_SMPTE2085] = "smpte2085", + [AVCOL_SPC_CHROMA_DERIVED_NCL] = "chroma-derived-nc", + [AVCOL_SPC_CHROMA_DERIVED_CL] = "chroma-derived-c", + [AVCOL_SPC_ICTCP] = "ictcp", +}; + +const char *av_color_space_name(enum AVColorSpace space) +{ + return (unsigned) space < AVCOL_SPC_NB ? + color_space_names[space] : NULL; +} + +const char * const color_primaries_names[AVCOL_PRI_NB] = { + [AVCOL_PRI_RESERVED0] = "reserved", + [AVCOL_PRI_BT709] = "bt709", + [AVCOL_PRI_UNSPECIFIED] = "unknown", + [AVCOL_PRI_RESERVED] = "reserved", + [AVCOL_PRI_BT470M] = "bt470m", + [AVCOL_PRI_BT470BG] = "bt470bg", + [AVCOL_PRI_SMPTE170M] = "smpte170m", + [AVCOL_PRI_SMPTE240M] = "smpte240m", + [AVCOL_PRI_FILM] = "film", + [AVCOL_PRI_BT2020] = "bt2020", + [AVCOL_PRI_SMPTE428] = "smpte428", + [AVCOL_PRI_SMPTE431] = "smpte431", + [AVCOL_PRI_SMPTE432] = "smpte432", + [AVCOL_PRI_JEDEC_P22] = "jedec-p22", +}; + +const char *av_color_primaries_name(enum AVColorPrimaries primaries) +{ + return (unsigned) primaries < AVCOL_PRI_NB ? + color_primaries_names[primaries] : NULL; +} + +const char * const color_transfer_names[] = { + [AVCOL_TRC_RESERVED0] = "reserved", + [AVCOL_TRC_BT709] = "bt709", + [AVCOL_TRC_UNSPECIFIED] = "unknown", + [AVCOL_TRC_RESERVED] = "reserved", + [AVCOL_TRC_GAMMA22] = "bt470m", + [AVCOL_TRC_GAMMA28] = "bt470bg", + [AVCOL_TRC_SMPTE170M] = "smpte170m", + [AVCOL_TRC_SMPTE240M] = "smpte240m", + [AVCOL_TRC_LINEAR] = "linear", + [AVCOL_TRC_LOG] = "log100", + [AVCOL_TRC_LOG_SQRT] = "log316", + [AVCOL_TRC_IEC61966_2_4] = "iec61966-2-4", + [AVCOL_TRC_BT1361_ECG] = "bt1361e", + [AVCOL_TRC_IEC61966_2_1] = "iec61966-2-1", + [AVCOL_TRC_BT2020_10] = "bt2020-10", + [AVCOL_TRC_BT2020_12] = "bt2020-12", + [AVCOL_TRC_SMPTE2084] = "smpte2084", + [AVCOL_TRC_SMPTE428] = "smpte428", + [AVCOL_TRC_ARIB_STD_B67] = "arib-std-b67", +}; + +const char *av_color_transfer_name(enum AVColorTransferCharacteristic transfer) +{ + return (unsigned) transfer < AVCOL_TRC_NB ? + color_transfer_names[transfer] : NULL; +} + +//math +const u8 ff_log2_tab[256]={ + 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +}; + +int av_log2(u32 v) +{ + int n = 0; + + if (v & 0xffff0000) { + v >>= 16; + n += 16; + } + if (v & 0xff00) { + v >>= 8; + n += 8; + } + n += ff_log2_tab[v]; + + return n; +} + +//bitstream +int find_start_code(u8 *data, int data_sz) +{ + if (data_sz > 3 && data[0] == 0 && data[1] == 0 && data[2] == 1) + return 3; + + if (data_sz > 4 && data[0] == 0 && data[1] == 0 && data[2] == 0 && data[3] == 1) + return 4; + + return -1; +} + +int calc_nal_len(u8 *data, int len) +{ + int i; + + for (i = 0; i < len - 4; i++) { + if (data[i]) + continue; + + if ((data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1) || + (data[i] == 0 && data[i + 1] == 0 && + data[i + 2]==0 && data[i + 3] == 1)) + return i; + } + return len; //Not find the end of nalu +} + +u8 *nal_unit_extract_rbsp(const u8 *src, u32 src_len, u32 *dst_len) +{ + u8 *dst; + u32 i, len; + + dst = vmalloc(src_len + AV_INPUT_BUFFER_PADDING_SIZE); + if (!dst) + return NULL; + + /* NAL unit header (2 bytes) */ + i = len = 0; + while (i < 2 && i < src_len) + dst[len++] = src[i++]; + + while (i + 2 < src_len) + if (!src[i] && !src[i + 1] && src[i + 2] == 3) { + dst[len++] = src[i++]; + dst[len++] = src[i++]; + i++; // remove emulation_prevention_three_byte + } else + dst[len++] = src[i++]; + + while (i < src_len) + dst[len++] = src[i++]; + + memset(dst + len, 0, AV_INPUT_BUFFER_PADDING_SIZE); + + *dst_len = len; + + return dst; +} + +//debug +static void _pr_hex(const char *fmt, ...) +{ + u8 buf[512]; + int len = 0; + + va_list args; + va_start(args, fmt); + vsnprintf(buf + len, 512 - len, fmt, args); + printk("%s", buf); + va_end(args); +} + +void print_hex_debug(u8 *data, u32 len, int max) +{ + int i, l; + + l = len > max ? max : len; + + for (i = 0; i < l; i++) { + if ((i & 0xf) == 0) + _pr_hex("%06x:", i); + _pr_hex("%02x ", data[i]); + if ((((i + 1) & 0xf) == 0) || ((i + 1) == l)) + _pr_hex("\n"); + } + + _pr_hex("print hex ending. len %d\n\n", l); +} + diff --git a/drivers/amvdec_ports/utils/common.h b/drivers/amvdec_ports/utils/common.h new file mode 100644 index 0000000..9540e28 --- a/dev/null +++ b/drivers/amvdec_ports/utils/common.h @@ -0,0 +1,72 @@ +#ifndef UTILS_COMMON_H +#define UTILS_COMMON_H + +#include "pixfmt.h" + +#define AV_INPUT_BUFFER_PADDING_SIZE 64 +#define MIN_CACHE_BITS 64 + +#define FFMAX(a,b) ((a) > (b) ? (a) : (b)) +#define FFMAX3(a,b,c) FFMAX(FFMAX(a,b),c) +#define FFMIN(a,b) ((a) > (b) ? (b) : (a)) +#define FFMIN3(a,b,c) FFMIN(FFMIN(a,b),c) + +#define AV_WL32(p, val) \ + do { \ + u32 d = (val); \ + ((u8*)(p))[0] = (d); \ + ((u8*)(p))[1] = (d) >> 8; \ + ((u8*)(p))[2] = (d) >> 16; \ + ((u8*)(p))[3] = (d) >> 24; \ + } while(0) + +#define AV_WB32(p, val) \ + do { u32 d = (val); \ + ((u8*)(p))[3] = (d); \ + ((u8*)(p))[2] = (d) >> 8; \ + ((u8*)(p))[1] = (d) >> 16; \ + ((u8*)(p))[0] = (d) >> 24; \ + } while(0) + +#define AV_RB32(x) \ + (((u32)((const u8*)(x))[0] << 24) | \ + (((const u8*)(x))[1] << 16) | \ + (((const u8*)(x))[2] << 8) | \ + ((const u8*)(x))[3]) + +#define AV_RL32(x) \ + (((u32)((const u8*)(x))[3] << 24) | \ + (((const u8*)(x))[2] << 16) | \ + (((const u8*)(x))[1] << 8) | \ + ((const u8*)(x))[0]) + +#define NEG_SSR32(a, s) (((int)(a)) >> ((s < 32) ? (32 - (s)) : 0)) +#define NEG_USR32(a, s) (((u32)(a)) >> ((s < 32) ? (32 - (s)) : 0)) + +//rounded division & shift +#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b)) +/* assume b>0 */ +#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) + +struct AVRational{ + int num; ///< numerator + int den; ///< denominator +}; + +//fmt +const char *av_color_space_name(enum AVColorSpace space); +const char *av_color_primaries_name(enum AVColorPrimaries primaries); +const char *av_color_transfer_name(enum AVColorTransferCharacteristic transfer); + +//math +int av_log2(u32 v); + +//bitstream +int find_start_code(u8 *data, int data_sz); +int calc_nal_len(u8 *data, int len); +u8 *nal_unit_extract_rbsp(const u8 *src, u32 src_len, u32 *dst_len); + +//debug +void print_hex_debug(u8 *data, u32 len, int max); + +#endif
\ No newline at end of file diff --git a/drivers/amvdec_ports/utils/get_bits.h b/drivers/amvdec_ports/utils/get_bits.h new file mode 100644 index 0000000..bb98ebd --- a/dev/null +++ b/drivers/amvdec_ports/utils/get_bits.h @@ -0,0 +1,590 @@ +#ifndef AVCODEC_GET_BITS_H +#define AVCODEC_GET_BITS_H + +#include <linux/kernel.h> +#include <linux/types.h> +#include "common.h" + +/* + * Safe bitstream reading: + * optionally, the get_bits API can check to ensure that we + * don't read past input buffer boundaries. This is protected + * with CONFIG_SAFE_BITSTREAM_READER at the global level, and + * then below that with UNCHECKED_BITSTREAM_READER at the per- + * decoder level. This means that decoders that check internally + * can "#define UNCHECKED_BITSTREAM_READER 1" to disable + * overread checks. + * Boundary checking causes a minor performance penalty so for + * applications that won't want/need this, it can be disabled + * globally using "#define CONFIG_SAFE_BITSTREAM_READER 0". + */ + +struct get_bits_context { + const u8 *buffer; + const u8 *buffer_end; + int index; + int size_in_bits; + int size_in_bits_plus8; +}; + +/* Bitstream reader API docs: + * name + * arbitrary name which is used as prefix for the internal variables + * + * gb + * struct get_bits_context + * + * OPEN_READER(name, gb) + * load gb into local variables + * + * CLOSE_READER(name, gb) + * store local vars in gb + * + * UPDATE_CACHE(name, gb) + * Refill the internal cache from the bitstream. + * After this call at least MIN_CACHE_BITS will be available. + * + * GET_CACHE(name, gb) + * Will output the contents of the internal cache, + * next bit is MSB of 32 or 64 bits (FIXME 64 bits). + * + * SHOW_UBITS(name, gb, num) + * Will return the next num bits. + * + * SHOW_SBITS(name, gb, num) + * Will return the next num bits and do sign extension. + * + * SKIP_BITS(name, gb, num) + * Will skip over the next num bits. + * Note, this is equivalent to SKIP_CACHE; SKIP_COUNTER. + * + * SKIP_CACHE(name, gb, num) + * Will remove the next num bits from the cache (note SKIP_COUNTER + * MUST be called before UPDATE_CACHE / CLOSE_READER). + * + * SKIP_COUNTER(name, gb, num) + * Will increment the internal bit counter (see SKIP_CACHE & SKIP_BITS). + * + * LAST_SKIP_BITS(name, gb, num) + * Like SKIP_BITS, to be used if next call is UPDATE_CACHE or CLOSE_READER. + * + * BITS_LEFT(name, gb) + * Return the number of bits left + * + * For examples see get_bits, show_bits, skip_bits, get_vlc. + */ + +#define OPEN_READER_NOSIZE(name, gb) \ + u32 name ## _index = (gb)->index; \ + u32 name ## _cache + +#define OPEN_READER(name, gb) OPEN_READER_NOSIZE(name, gb) +#define BITS_AVAILABLE(name, gb) 1 + +#define CLOSE_READER(name, gb) (gb)->index = name ## _index + +#define UPDATE_CACHE_LE(name, gb) name ##_cache = \ + AV_RL32((gb)->buffer + (name ## _index >> 3)) >> (name ## _index & 7) + +#define UPDATE_CACHE_BE(name, gb) name ## _cache = \ + AV_RB32((gb)->buffer + (name ## _index >> 3)) << (name ## _index & 7) + +#define SKIP_COUNTER(name, gb, num) name ## _index += (num) + +#define BITS_LEFT(name, gb) ((int)((gb)->size_in_bits - name ## _index)) + +#define SKIP_BITS(name, gb, num) \ + do { \ + SKIP_CACHE(name, gb, num); \ + SKIP_COUNTER(name, gb, num); \ + } while (0) + +#define GET_CACHE(name, gb) ((u32) name ## _cache) + +#define LAST_SKIP_BITS(name, gb, num) SKIP_COUNTER(name, gb, num) + +#define SHOW_UBITS_LE(name, gb, num) zero_extend(name ## _cache, num) +#define SHOW_SBITS_LE(name, gb, num) sign_extend(name ## _cache, num) + +#define SHOW_UBITS_BE(name, gb, num) NEG_USR32(name ## _cache, num) +#define SHOW_SBITS_BE(name, gb, num) NEG_SSR32(name ## _cache, num) + +#ifdef BITSTREAM_READER_LE +#define UPDATE_CACHE(name, gb) UPDATE_CACHE_LE(name, gb) +#define SKIP_CACHE(name, gb, num) name ## _cache >>= (num) + +#define SHOW_UBITS(name, gb, num) SHOW_UBITS_LE(name, gb, num) +#define SHOW_SBITS(name, gb, num) SHOW_SBITS_LE(name, gb, num) +#else +#define UPDATE_CACHE(name, gb) UPDATE_CACHE_BE(name, gb) +#define SKIP_CACHE(name, gb, num) name ## _cache <<= (num) + +#define SHOW_UBITS(name, gb, num) SHOW_UBITS_BE(name, gb, num) +#define SHOW_SBITS(name, gb, num) SHOW_SBITS_BE(name, gb, num) +#endif + +static inline const int sign_extend(int val, u32 bits) +{ + u32 shift = 8 * sizeof(int) - bits; + + union { u32 u; int s; } v = { (u32) val << shift }; + return v.s >> shift; +} + +static inline u32 zero_extend(u32 val, u32 bits) +{ + return (val << ((8 * sizeof(int)) - bits)) >> ((8 * sizeof(int)) - bits); +} + +static inline int get_bits_count(const struct get_bits_context *s) +{ + return s->index; +} + +/** + * Skips the specified number of bits. + * @param n the number of bits to skip, + * For the UNCHECKED_BITSTREAM_READER this must not cause the distance + * from the start to overflow int. Staying within the bitstream + padding + * is sufficient, too. + */ +static inline void skip_bits_long(struct get_bits_context *s, int n) +{ + s->index += n; +} + +/** + * Read MPEG-1 dc-style VLC (sign bit + mantissa with no MSB). + * if MSB not set it is negative + * @param n length in bits + */ +static inline int get_xbits(struct get_bits_context *s, int n) +{ + register int sign; + register int cache; + + OPEN_READER(re, s); + UPDATE_CACHE(re, s); + cache = GET_CACHE(re, s); + sign = ~cache >> 31; + LAST_SKIP_BITS(re, s, n); + CLOSE_READER(re, s); + + return (NEG_USR32(sign ^ cache, n) ^ sign) - sign; +} + + +static inline int get_xbits_le(struct get_bits_context *s, int n) +{ + register int sign; + register int cache; + + OPEN_READER(re, s); + UPDATE_CACHE_LE(re, s); + cache = GET_CACHE(re, s); + sign = sign_extend(~cache, n) >> 31; + LAST_SKIP_BITS(re, s, n); + CLOSE_READER(re, s); + + return (zero_extend(sign ^ cache, n) ^ sign) - sign; +} + +static inline int get_sbits(struct get_bits_context *s, int n) +{ + register int tmp; + + OPEN_READER(re, s); + UPDATE_CACHE(re, s); + tmp = SHOW_SBITS(re, s, n); + LAST_SKIP_BITS(re, s, n); + CLOSE_READER(re, s); + + return tmp; +} + +/** + * Read 1-25 bits. + */ +static inline u32 get_bits(struct get_bits_context *s, int n) +{ + register u32 tmp; + + OPEN_READER(re, s); + UPDATE_CACHE(re, s); + tmp = SHOW_UBITS(re, s, n); + LAST_SKIP_BITS(re, s, n); + CLOSE_READER(re, s); + + return tmp; +} + +/** + * Read 0-25 bits. + */ +static inline int get_bitsz(struct get_bits_context *s, int n) +{ + return n ? get_bits(s, n) : 0; +} + +static inline u32 get_bits_le(struct get_bits_context *s, int n) +{ + register int tmp; + + OPEN_READER(re, s); + UPDATE_CACHE_LE(re, s); + tmp = SHOW_UBITS_LE(re, s, n); + LAST_SKIP_BITS(re, s, n); + CLOSE_READER(re, s); + + return tmp; +} + +/** + * Show 1-25 bits. + */ +static inline u32 show_bits(struct get_bits_context *s, int n) +{ + register u32 tmp; + + OPEN_READER_NOSIZE(re, s); + UPDATE_CACHE(re, s); + tmp = SHOW_UBITS(re, s, n); + + return tmp; +} + +static inline void skip_bits(struct get_bits_context *s, int n) +{ + u32 re_index = s->index; + LAST_SKIP_BITS(re, s, n); + CLOSE_READER(re, s); +} + +static inline u32 get_bits1(struct get_bits_context *s) +{ + u32 index = s->index; + u8 result = s->buffer[index >> 3]; + +#ifdef BITSTREAM_READER_LE + result >>= index & 7; + result &= 1; +#else + result <<= index & 7; + result >>= 8 - 1; +#endif + + index++; + s->index = index; + + return result; +} + +static inline u32 show_bits1(struct get_bits_context *s) +{ + return show_bits(s, 1); +} + +static inline void skip_bits1(struct get_bits_context *s) +{ + skip_bits(s, 1); +} + +/** + * Read 0-32 bits. + */ +static inline u32 get_bits_long(struct get_bits_context *s, int n) +{ + if (!n) { + return 0; + } else if (n <= MIN_CACHE_BITS) { + return get_bits(s, n); + } else { +#ifdef BITSTREAM_READER_LE + u32 ret = get_bits(s, 16); + return ret | (get_bits(s, n - 16) << 16); +#else + u32 ret = get_bits(s, 16) << (n - 16); + return ret | get_bits(s, n - 16); +#endif + } +} + +/** + * Read 0-64 bits. + */ +static inline u64 get_bits64(struct get_bits_context *s, int n) +{ + if (n <= 32) { + return get_bits_long(s, n); + } else { +#ifdef BITSTREAM_READER_LE + u64 ret = get_bits_long(s, 32); + return ret | (u64) get_bits_long(s, n - 32) << 32; +#else + u64 ret = (u64) get_bits_long(s, n - 32) << 32; + return ret | get_bits_long(s, 32); +#endif + } +} + +/** + * Read 0-32 bits as a signed integer. + */ +static inline int get_sbits_long(struct get_bits_context *s, int n) +{ + if (!n) + return 0; + + return sign_extend(get_bits_long(s, n), n); +} + +/** + * Show 0-32 bits. + */ +static inline u32 show_bits_long(struct get_bits_context *s, int n) +{ + if (n <= MIN_CACHE_BITS) { + return show_bits(s, n); + } else { + struct get_bits_context gb = *s; + + return get_bits_long(&gb, n); + } +} + +static inline int check_marker(struct get_bits_context *s, const char *msg) +{ + int bit = get_bits1(s); + + if (!bit) + pr_err("Marker bit missing at %d of %d %s\n", + get_bits_count(s) - 1, s->size_in_bits, msg); + return bit; +} + +static inline int init_get_bits_xe(struct get_bits_context *s, + const u8 *buffer, int bit_size, int is_le) +{ + int buffer_size; + int ret = 0; + + if (bit_size >= INT_MAX - FFMAX(7, AV_INPUT_BUFFER_PADDING_SIZE * 8) || + bit_size < 0 || !buffer) { + bit_size = 0; + buffer = NULL; + ret = -1; + } + + buffer_size = (bit_size + 7) >> 3; + + s->buffer = buffer; + s->size_in_bits = bit_size; + s->size_in_bits_plus8 = bit_size + 8; + s->buffer_end = buffer + buffer_size; + s->index = 0; + + return ret; +} + +/** + * Initialize struct get_bits_context. + * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes + * larger than the actual read bits because some optimized bitstream + * readers read 32 or 64 bit at once and could read over the end + * @param bit_size the size of the buffer in bits + * @return 0 on success, -1 if the buffer_size would overflow. + */ +static inline int init_get_bits(struct get_bits_context *s, + const u8 *buffer, int bit_size) +{ +#ifdef BITSTREAM_READER_LE + return init_get_bits_xe(s, buffer, bit_size, 1); +#else + return init_get_bits_xe(s, buffer, bit_size, 0); +#endif +} + +/** + * Initialize struct get_bits_context. + * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes + * larger than the actual read bits because some optimized bitstream + * readers read 32 or 64 bit at once and could read over the end + * @param byte_size the size of the buffer in bytes + * @return 0 on success, -1 if the buffer_size would overflow. + */ +static inline int init_get_bits8(struct get_bits_context *s, + const u8 *buffer, int byte_size) +{ + if (byte_size > INT_MAX / 8 || byte_size < 0) + byte_size = -1; + return init_get_bits(s, buffer, byte_size * 8); +} + +static inline int init_get_bits8_le(struct get_bits_context *s, + const u8 *buffer, int byte_size) +{ + if (byte_size > INT_MAX / 8 || byte_size < 0) + byte_size = -1; + return init_get_bits_xe(s, buffer, byte_size * 8, 1); +} + +static inline const u8 *align_get_bits(struct get_bits_context *s) +{ + int n = -get_bits_count(s) & 7; + + if (n) + skip_bits(s, n); + return s->buffer + (s->index >> 3); +} + +/** + * If the vlc code is invalid and max_depth=1, then no bits will be removed. + * If the vlc code is invalid and max_depth>1, then the number of bits removed + * is undefined. + */ +#define GET_VLC(code, name, gb, table, bits, max_depth) \ + do { \ + int n, nb_bits; \ + u32 index; \ + \ + index = SHOW_UBITS(name, gb, bits); \ + code = table[index][0]; \ + n = table[index][1]; \ + \ + if (max_depth > 1 && n < 0) { \ + LAST_SKIP_BITS(name, gb, bits); \ + UPDATE_CACHE(name, gb); \ + \ + nb_bits = -n; \ + \ + index = SHOW_UBITS(name, gb, nb_bits) + code; \ + code = table[index][0]; \ + n = table[index][1]; \ + if (max_depth > 2 && n < 0) { \ + LAST_SKIP_BITS(name, gb, nb_bits); \ + UPDATE_CACHE(name, gb); \ + \ + nb_bits = -n; \ + \ + index = SHOW_UBITS(name, gb, nb_bits) + code; \ + code = table[index][0]; \ + n = table[index][1]; \ + } \ + } \ + SKIP_BITS(name, gb, n); \ + } while (0) + +#define GET_RL_VLC(level, run, name, gb, table, bits, \ + max_depth, need_update) \ + do { \ + int n, nb_bits; \ + u32 index; \ + \ + index = SHOW_UBITS(name, gb, bits); \ + level = table[index].level; \ + n = table[index].len; \ + \ + if (max_depth > 1 && n < 0) { \ + SKIP_BITS(name, gb, bits); \ + if (need_update) { \ + UPDATE_CACHE(name, gb); \ + } \ + \ + nb_bits = -n; \ + \ + index = SHOW_UBITS(name, gb, nb_bits) + level; \ + level = table[index].level; \ + n = table[index].len; \ + if (max_depth > 2 && n < 0) { \ + LAST_SKIP_BITS(name, gb, nb_bits); \ + if (need_update) { \ + UPDATE_CACHE(name, gb); \ + } \ + nb_bits = -n; \ + \ + index = SHOW_UBITS(name, gb, nb_bits) + level; \ + level = table[index].level; \ + n = table[index].len; \ + } \ + } \ + run = table[index].run; \ + SKIP_BITS(name, gb, n); \ + } while (0) + +/* Return the LUT element for the given bitstream configuration. */ +static inline int set_idx(struct get_bits_context *s, + int code, int *n, int *nb_bits, int (*table)[2]) +{ + u32 idx; + + *nb_bits = -*n; + idx = show_bits(s, *nb_bits) + code; + *n = table[idx][1]; + + return table[idx][0]; +} + +/** + * Parse a vlc code. + * @param bits is the number of bits which will be read at once, must be + * identical to nb_bits in init_vlc() + * @param max_depth is the number of times bits bits must be read to completely + * read the longest vlc code + * = (max_vlc_length + bits - 1) / bits + * @returns the code parsed or -1 if no vlc matches + */ +static inline int get_vlc2(struct get_bits_context *s, + int (*table)[2], int bits, int max_depth) +{ + int code; + + OPEN_READER(re, s); + UPDATE_CACHE(re, s); + + GET_VLC(code, re, s, table, bits, max_depth); + + CLOSE_READER(re, s); + + return code; +} + +static inline int decode012(struct get_bits_context *gb) +{ + int n; + + n = get_bits1(gb); + if (n == 0) + return 0; + else + return get_bits1(gb) + 1; +} + +static inline int decode210(struct get_bits_context *gb) +{ + if (get_bits1(gb)) + return 0; + else + return 2 - get_bits1(gb); +} + +static inline int get_bits_left(struct get_bits_context *gb) +{ + return gb->size_in_bits - get_bits_count(gb); +} + +static inline int skip_1stop_8data_bits(struct get_bits_context *gb) +{ + if (get_bits_left(gb) <= 0) + return -1; + + while (get_bits1(gb)) { + skip_bits(gb, 8); + if (get_bits_left(gb) <= 0) + return -1; + } + + return 0; +} + +#endif /* AVCODEC_GET_BITS_H */ + diff --git a/drivers/amvdec_ports/utils/golomb.c b/drivers/amvdec_ports/utils/golomb.c new file mode 100644 index 0000000..21fcb6a --- a/dev/null +++ b/drivers/amvdec_ports/utils/golomb.c @@ -0,0 +1,147 @@ +#include <linux/kernel.h> +#include <linux/types.h> + +const u8 ff_golomb_vlc_len[512]={ + 19,17,15,15,13,13,13,13,11,11,11,11,11,11,11,11,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +}; + +const u8 ff_ue_golomb_vlc_code[512]={ + 32,32,32,32,32,32,32,32,31,32,32,32,32,32,32,32,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9,10,10,10,10,11,11,11,11,12,12,12,12,13,13,13,13,14,14,14,14, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +const char ff_se_golomb_vlc_code[512]={ + 17, 17, 17, 17, 17, 17, 17, 17, 16, 17, 17, 17, 17, 17, 17, 17, 8, -8, 9, -9, 10,-10, 11,-11, 12,-12, 13,-13, 14,-14, 15,-15, + 4, 4, 4, 4, -4, -4, -4, -4, 5, 5, 5, 5, -5, -5, -5, -5, 6, 6, 6, 6, -6, -6, -6, -6, 7, 7, 7, 7, -7, -7, -7, -7, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +const u8 ff_ue_golomb_len[256]={ + 1, 3, 3, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,17, +}; + +const u8 ff_interleaved_golomb_vlc_len[256]={ + 9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5, + 9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5, + 9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +}; + +const u8 ff_interleaved_ue_golomb_vlc_code[256]={ + 15,16,7, 7, 17,18,8, 8, 3, 3, 3, 3, 3, 3, 3, 3, + 19,20,9, 9, 21,22,10,10,4, 4, 4, 4, 4, 4, 4, 4, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 23,24,11,11,25,26,12,12,5, 5, 5, 5, 5, 5, 5, 5, + 27,28,13,13,29,30,14,14,6, 6, 6, 6, 6, 6, 6, 6, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +const char ff_interleaved_se_golomb_vlc_code[256]={ + 8, -8, 4, 4, 9, -9, -4, -4, 2, 2, 2, 2, 2, 2, 2, 2, + 10,-10, 5, 5, 11,-11, -5, -5, -2, -2, -2, -2, -2, -2, -2, -2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 12,-12, 6, 6, 13,-13, -6, -6, 3, 3, 3, 3, 3, 3, 3, 3, + 14,-14, 7, 7, 15,-15, -7, -7, -3, -3, -3, -3, -3, -3, -3, -3, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +const u8 ff_interleaved_dirac_golomb_vlc_code[256]={ + 0, 1, 0, 0, 2, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 5, 2, 2, 6, 7, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 9, 4, 4, 10,11,5, 5, 2, 2, 2, 2, 2, 2, 2, 2, + 12,13,6, 6, 14,15,7, 7, 3, 3, 3, 3, 3, 3, 3, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + diff --git a/drivers/amvdec_ports/utils/golomb.h b/drivers/amvdec_ports/utils/golomb.h new file mode 100644 index 0000000..d66c182 --- a/dev/null +++ b/drivers/amvdec_ports/utils/golomb.h @@ -0,0 +1,500 @@ +#ifndef AVCODEC_GOLOMB_H +#define AVCODEC_GOLOMB_H + +#include <linux/kernel.h> +#include <linux/types.h> + +#include "get_bits.h" +#include "put_bits.h" +#include "common.h" + +#define INVALID_VLC 0x80000000 + +extern const u8 ff_golomb_vlc_len[512]; +extern const u8 ff_ue_golomb_vlc_code[512]; +extern const char ff_se_golomb_vlc_code[512]; +extern const u8 ff_ue_golomb_len[256]; + +extern const u8 ff_interleaved_golomb_vlc_len[256]; +extern const u8 ff_interleaved_ue_golomb_vlc_code[256]; +extern const char ff_interleaved_se_golomb_vlc_code[256]; +extern const u8 ff_interleaved_dirac_golomb_vlc_code[256]; + +/** + * Read an u32 Exp-Golomb code in the range 0 to 8190. + * + * @returns the read value or a negative error code. + */ +static inline int get_ue_golomb(struct get_bits_context *gb) +{ + u32 buf; + + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); + buf = GET_CACHE(re, gb); + + if (buf >= (1 << 27)) { + buf >>= 32 - 9; + LAST_SKIP_BITS(re, gb, ff_golomb_vlc_len[buf]); + CLOSE_READER(re, gb); + + return ff_ue_golomb_vlc_code[buf]; + } else { + int log = 2 * av_log2(buf) - 31; + LAST_SKIP_BITS(re, gb, 32 - log); + CLOSE_READER(re, gb); + if (log < 7) { + pr_err("Invalid UE golomb code\n"); + return -1; + } + buf >>= log; + buf--; + + return buf; + } +} + +/** + * Read an u32 Exp-Golomb code in the range 0 to UINT_MAX-1. + */ +static inline u32 get_ue_golomb_long(struct get_bits_context *gb) +{ + u32 buf, log; + + buf = show_bits_long(gb, 32); + log = 31 - av_log2(buf); + skip_bits_long(gb, log); + + return get_bits_long(gb, log + 1) - 1; +} + +/** + * read u32 exp golomb code, constraint to a max of 31. + * the return value is undefined if the stored value exceeds 31. + */ +static inline int get_ue_golomb_31(struct get_bits_context *gb) +{ + u32 buf; + + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); + buf = GET_CACHE(re, gb); + + buf >>= 32 - 9; + LAST_SKIP_BITS(re, gb, ff_golomb_vlc_len[buf]); + CLOSE_READER(re, gb); + + return ff_ue_golomb_vlc_code[buf]; +} + +static inline u32 get_interleaved_ue_golomb(struct get_bits_context *gb) +{ + u32 buf; + + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); + buf = GET_CACHE(re, gb); + + if (buf & 0xAA800000) { + buf >>= 32 - 8; + LAST_SKIP_BITS(re, gb, ff_interleaved_golomb_vlc_len[buf]); + CLOSE_READER(re, gb); + + return ff_interleaved_ue_golomb_vlc_code[buf]; + } else { + u32 ret = 1; + + do { + buf >>= 32 - 8; + LAST_SKIP_BITS(re, gb, + FFMIN(ff_interleaved_golomb_vlc_len[buf], 8)); + + if (ff_interleaved_golomb_vlc_len[buf] != 9) { + ret <<= (ff_interleaved_golomb_vlc_len[buf] - 1) >> 1; + ret |= ff_interleaved_dirac_golomb_vlc_code[buf]; + break; + } + ret = (ret << 4) | ff_interleaved_dirac_golomb_vlc_code[buf]; + UPDATE_CACHE(re, gb); + buf = GET_CACHE(re, gb); + } while (ret<0x8000000U && BITS_AVAILABLE(re, gb)); + + CLOSE_READER(re, gb); + return ret - 1; + } +} + +/** + * read u32 truncated exp golomb code. + */ +static inline int get_te0_golomb(struct get_bits_context *gb, int range) +{ + if (range == 1) + return 0; + else if (range == 2) + return get_bits1(gb) ^ 1; + else + return get_ue_golomb(gb); +} + +/** + * read u32 truncated exp golomb code. + */ +static inline int get_te_golomb(struct get_bits_context *gb, int range) +{ + if (range == 2) + return get_bits1(gb) ^ 1; + else + return get_ue_golomb(gb); +} + +/** + * read signed exp golomb code. + */ +static inline int get_se_golomb(struct get_bits_context *gb) +{ + u32 buf; + + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); + buf = GET_CACHE(re, gb); + + if (buf >= (1 << 27)) { + buf >>= 32 - 9; + LAST_SKIP_BITS(re, gb, ff_golomb_vlc_len[buf]); + CLOSE_READER(re, gb); + + return ff_se_golomb_vlc_code[buf]; + } else { + int log = av_log2(buf), sign; + LAST_SKIP_BITS(re, gb, 31 - log); + UPDATE_CACHE(re, gb); + buf = GET_CACHE(re, gb); + + buf >>= log; + + LAST_SKIP_BITS(re, gb, 32 - log); + CLOSE_READER(re, gb); + + sign = -(buf & 1); + buf = ((buf >> 1) ^ sign) - sign; + + return buf; + } +} + +static inline int get_se_golomb_long(struct get_bits_context *gb) +{ + u32 buf = get_ue_golomb_long(gb); + int sign = (buf & 1) - 1; + + return ((buf >> 1) ^ sign) + 1; +} + +static inline int get_interleaved_se_golomb(struct get_bits_context *gb) +{ + u32 buf; + + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); + buf = GET_CACHE(re, gb); + + if (buf & 0xAA800000) { + buf >>= 32 - 8; + LAST_SKIP_BITS(re, gb, ff_interleaved_golomb_vlc_len[buf]); + CLOSE_READER(re, gb); + + return ff_interleaved_se_golomb_vlc_code[buf]; + } else { + int log; + LAST_SKIP_BITS(re, gb, 8); + UPDATE_CACHE(re, gb); + buf |= 1 | (GET_CACHE(re, gb) >> 8); + + if ((buf & 0xAAAAAAAA) == 0) + return INVALID_VLC; + + for (log = 31; (buf & 0x80000000) == 0; log--) + buf = (buf << 2) - ((buf << log) >> (log - 1)) + (buf >> 30); + + LAST_SKIP_BITS(re, gb, 63 - 2 * log - 8); + CLOSE_READER(re, gb); + return (signed) (((((buf << log) >> log) - 1) ^ -(buf & 0x1)) + 1) >> 1; + } +} + +static inline int dirac_get_se_golomb(struct get_bits_context *gb) +{ + u32 ret = get_interleaved_ue_golomb(gb); + + if (ret) { + int sign = -get_bits1(gb); + ret = (ret ^ sign) - sign; + } + + return ret; +} + +/** + * read u32 golomb rice code (ffv1). + */ +static inline int get_ur_golomb(struct get_bits_context *gb, + int k, int limit, int esc_len) +{ + u32 buf; + int log; + + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); + buf = GET_CACHE(re, gb); + + log = av_log2(buf); + + if (log > 31 - limit) { + buf >>= log - k; + buf += (30U - log) << k; + LAST_SKIP_BITS(re, gb, 32 + k - log); + CLOSE_READER(re, gb); + + return buf; + } else { + LAST_SKIP_BITS(re, gb, limit); + UPDATE_CACHE(re, gb); + + buf = SHOW_UBITS(re, gb, esc_len); + + LAST_SKIP_BITS(re, gb, esc_len); + CLOSE_READER(re, gb); + + return buf + limit - 1; + } +} + +/** + * read u32 golomb rice code (jpegls). + */ +static inline int get_ur_golomb_jpegls(struct get_bits_context *gb, + int k, int limit, int esc_len) +{ + u32 buf; + int log; + + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); + buf = GET_CACHE(re, gb); + + log = av_log2(buf); + + if (log - k >= 32 - MIN_CACHE_BITS + (MIN_CACHE_BITS == 32) && + 32 - log < limit) { + buf >>= log - k; + buf += (30U - log) << k; + LAST_SKIP_BITS(re, gb, 32 + k - log); + CLOSE_READER(re, gb); + + return buf; + } else { + int i; + for (i = 0; i + MIN_CACHE_BITS <= limit && SHOW_UBITS(re, gb, MIN_CACHE_BITS) == 0; i += MIN_CACHE_BITS) { + if (gb->size_in_bits <= re_index) { + CLOSE_READER(re, gb); + return -1; + } + LAST_SKIP_BITS(re, gb, MIN_CACHE_BITS); + UPDATE_CACHE(re, gb); + } + for (; i < limit && SHOW_UBITS(re, gb, 1) == 0; i++) { + SKIP_BITS(re, gb, 1); + } + LAST_SKIP_BITS(re, gb, 1); + UPDATE_CACHE(re, gb); + + if (i < limit - 1) { + if (k) { + if (k > MIN_CACHE_BITS - 1) { + buf = SHOW_UBITS(re, gb, 16) << (k-16); + LAST_SKIP_BITS(re, gb, 16); + UPDATE_CACHE(re, gb); + buf |= SHOW_UBITS(re, gb, k-16); + LAST_SKIP_BITS(re, gb, k-16); + } else { + buf = SHOW_UBITS(re, gb, k); + LAST_SKIP_BITS(re, gb, k); + } + } else { + buf = 0; + } + buf += ((u32)i << k); + } else if (i == limit - 1) { + buf = SHOW_UBITS(re, gb, esc_len); + LAST_SKIP_BITS(re, gb, esc_len); + + buf ++; + } else { + buf = -1; + } + CLOSE_READER(re, gb); + return buf; + } +} + +/** + * read signed golomb rice code (ffv1). + */ +static inline int get_sr_golomb(struct get_bits_context *gb, + int k, int limit, int esc_len) +{ + u32 v = get_ur_golomb(gb, k, limit, esc_len); + + return (v >> 1) ^ -(v & 1); +} + +/** + * read signed golomb rice code (flac). + */ +static inline int get_sr_golomb_flac(struct get_bits_context *gb, + int k, int limit, int esc_len) +{ + u32 v = get_ur_golomb_jpegls(gb, k, limit, esc_len); + + return (v >> 1) ^ -(v & 1); +} + +/** + * read u32 golomb rice code (shorten). + */ +static inline u32 get_ur_golomb_shorten(struct get_bits_context *gb, int k) +{ + return get_ur_golomb_jpegls(gb, k, INT_MAX, 0); +} + +/** + * read signed golomb rice code (shorten). + */ +static inline int get_sr_golomb_shorten(struct get_bits_context *gb, int k) +{ + int uvar = get_ur_golomb_jpegls(gb, k + 1, INT_MAX, 0); + + return (uvar >> 1) ^ -(uvar & 1); +} + +/** + * write u32 exp golomb code. 2^16 - 2 at most + */ +static inline void set_ue_golomb(struct put_bits_context *pb, int i) +{ + if (i < 256) + put_bits(pb, ff_ue_golomb_len[i], i + 1); + else { + int e = av_log2(i + 1); + put_bits(pb, 2 * e + 1, i + 1); + } +} + +/** + * write u32 exp golomb code. 2^32-2 at most. + */ +static inline void set_ue_golomb_long(struct put_bits_context *pb, u32 i) +{ + if (i < 256) + put_bits(pb, ff_ue_golomb_len[i], i + 1); + else { + int e = av_log2(i + 1); + put_bits64(pb, 2 * e + 1, i + 1); + } +} + +/** + * write truncated u32 exp golomb code. + */ +static inline void set_te_golomb(struct put_bits_context *pb, int i, int range) +{ + if (range == 2) + put_bits(pb, 1, i ^ 1); + else + set_ue_golomb(pb, i); +} + +/** + * write signed exp golomb code. 16 bits at most. + */ +static inline void set_se_golomb(struct put_bits_context *pb, int i) +{ + i = 2 * i - 1; + + if (i < 0) + i ^= -1; //FIXME check if gcc does the right thing + set_ue_golomb(pb, i); +} + +/** + * write u32 golomb rice code (ffv1). + */ +static inline void set_ur_golomb(struct put_bits_context *pb, int i, int k, int limit, + int esc_len) +{ + int e; + + e = i >> k; + if (e < limit) + put_bits(pb, e + k + 1, (1 << k) + av_mod_uintp2(i, k)); + else + put_bits(pb, limit + esc_len, i - limit + 1); +} + +/** + * write u32 golomb rice code (jpegls). + */ +static inline void set_ur_golomb_jpegls(struct put_bits_context *pb, + int i, int k, int limit, int esc_len) +{ + int e; + + e = (i >> k) + 1; + if (e < limit) { + while (e > 31) { + put_bits(pb, 31, 0); + e -= 31; + } + put_bits(pb, e, 1); + if (k) + put_sbits(pb, k, i); + } else { + while (limit > 31) { + put_bits(pb, 31, 0); + limit -= 31; + } + put_bits(pb, limit, 1); + put_bits(pb, esc_len, i - 1); + } +} + +/** + * write signed golomb rice code (ffv1). + */ +static inline void set_sr_golomb(struct put_bits_context *pb, + int i, int k, int limit, int esc_len) +{ + int v; + + v = -2 * i - 1; + v ^= (v >> 31); + + set_ur_golomb(pb, v, k, limit, esc_len); +} + +/** + * write signed golomb rice code (flac). + */ +static inline void set_sr_golomb_flac(struct put_bits_context *pb, + int i, int k, int limit, int esc_len) +{ + int v; + + v = -2 * i - 1; + v ^= (v >> 31); + + set_ur_golomb_jpegls(pb, v, k, limit, esc_len); +} + +#endif /* AVCODEC_GOLOMB_H */ diff --git a/drivers/amvdec_ports/utils/pixfmt.h b/drivers/amvdec_ports/utils/pixfmt.h new file mode 100644 index 0000000..f13411e --- a/dev/null +++ b/drivers/amvdec_ports/utils/pixfmt.h @@ -0,0 +1,470 @@ +#ifndef AVUTIL_PIXFMT_H +#define AVUTIL_PIXFMT_H + +/** + * Pixel format. + * + * @note + * AV_PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA + * color is put together as: + * (A << 24) | (R << 16) | (G << 8) | B + * This is stored as BGRA on little-endian CPU architectures and ARGB on + * big-endian CPUs. + * + * @note + * If the resolution is not a multiple of the chroma subsampling factor + * then the chroma plane resolution must be rounded up. + * + * @par + * When the pixel format is palettized RGB32 (AV_PIX_FMT_PAL8), the palettized + * image data is stored in AVFrame.data[0]. The palette is transported in + * AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is + * formatted the same as in AV_PIX_FMT_RGB32 described above (i.e., it is + * also endian-specific). Note also that the individual RGB32 palette + * components stored in AVFrame.data[1] should be in the range 0..255. + * This is important as many custom PAL8 video codecs that were designed + * to run on the IBM VGA graphics adapter use 6-bit palette components. + * + * @par + * For all the 8 bits per pixel formats, an RGB32 palette is in data[1] like + * for pal8. This palette is filled in automatically by the function + * allocating the picture. + */ +enum AVPixelFormat { + AV_PIX_FMT_NONE = -1, + AV_PIX_FMT_YUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples) + AV_PIX_FMT_YUYV422, ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr + AV_PIX_FMT_RGB24, ///< packed RGB 8:8:8, 24bpp, RGBRGB... + AV_PIX_FMT_BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR... + AV_PIX_FMT_YUV422P, ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) + AV_PIX_FMT_YUV444P, ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples) + AV_PIX_FMT_YUV410P, ///< planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples) + AV_PIX_FMT_YUV411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) + AV_PIX_FMT_GRAY8, ///< Y , 8bpp + AV_PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb + AV_PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb + AV_PIX_FMT_PAL8, ///< 8 bits with AV_PIX_FMT_RGB32 palette + AV_PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting color_range + AV_PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting color_range + AV_PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting color_range + AV_PIX_FMT_UYVY422, ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1 + AV_PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3 + AV_PIX_FMT_BGR8, ///< packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb) + AV_PIX_FMT_BGR4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + AV_PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb) + AV_PIX_FMT_RGB8, ///< packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb) + AV_PIX_FMT_RGB4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + AV_PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb) + AV_PIX_FMT_NV12, ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) + AV_PIX_FMT_NV21, ///< as above, but U and V bytes are swapped + + AV_PIX_FMT_ARGB, ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB... + AV_PIX_FMT_RGBA, ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA... + AV_PIX_FMT_ABGR, ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR... + AV_PIX_FMT_BGRA, ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA... + + AV_PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian + AV_PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian + AV_PIX_FMT_YUV440P, ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples) + AV_PIX_FMT_YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range + AV_PIX_FMT_YUVA420P, ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples) + AV_PIX_FMT_RGB48BE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian + AV_PIX_FMT_RGB48LE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian + + AV_PIX_FMT_RGB565BE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian + AV_PIX_FMT_RGB565LE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian + AV_PIX_FMT_RGB555BE, ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined + AV_PIX_FMT_RGB555LE, ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined + + AV_PIX_FMT_BGR565BE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian + AV_PIX_FMT_BGR565LE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian + AV_PIX_FMT_BGR555BE, ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), big-endian , X=unused/undefined + AV_PIX_FMT_BGR555LE, ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), little-endian, X=unused/undefined + +#ifdef FF_API_VAAPI + /** @name Deprecated pixel formats */ + /**@{*/ + AV_PIX_FMT_VAAPI_MOCO, ///< HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers + AV_PIX_FMT_VAAPI_IDCT, ///< HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers + AV_PIX_FMT_VAAPI_VLD, ///< HW decoding through VA API, Picture.data[3] contains a VASurfaceID + /**@}*/ + AV_PIX_FMT_VAAPI = AV_PIX_FMT_VAAPI_VLD, +#else + /** + * Hardware acceleration through VA-API, data[3] contains a + * VASurfaceID. + */ + AV_PIX_FMT_VAAPI, +#endif + + AV_PIX_FMT_YUV420P16LE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P16BE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV422P16LE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV422P16BE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer + + AV_PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), big-endian, X=unused/undefined + AV_PIX_FMT_BGR444LE, ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_BGR444BE, ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), big-endian, X=unused/undefined + AV_PIX_FMT_YA8, ///< 8 bits gray, 8 bits alpha + + AV_PIX_FMT_Y400A = AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8 + AV_PIX_FMT_GRAY8A= AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8 + + AV_PIX_FMT_BGR48BE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian + AV_PIX_FMT_BGR48LE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian + + /** + * The following 12 formats have the disadvantage of needing 1 format for each bit depth. + * Notice that each 9/10 bits sample is stored in 16 bits with extra padding. + * If you want to support multiple bit depths, then using AV_PIX_FMT_YUV420P16* with the bpp stored separately is better. + */ + AV_PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV422P10BE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P10LE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV444P9BE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P9LE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P10BE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_GBRP, ///< planar GBR 4:4:4 24bpp + AV_PIX_FMT_GBR24P = AV_PIX_FMT_GBRP, // alias for #AV_PIX_FMT_GBRP + AV_PIX_FMT_GBRP9BE, ///< planar GBR 4:4:4 27bpp, big-endian + AV_PIX_FMT_GBRP9LE, ///< planar GBR 4:4:4 27bpp, little-endian + AV_PIX_FMT_GBRP10BE, ///< planar GBR 4:4:4 30bpp, big-endian + AV_PIX_FMT_GBRP10LE, ///< planar GBR 4:4:4 30bpp, little-endian + AV_PIX_FMT_GBRP16BE, ///< planar GBR 4:4:4 48bpp, big-endian + AV_PIX_FMT_GBRP16LE, ///< planar GBR 4:4:4 48bpp, little-endian + AV_PIX_FMT_YUVA422P, ///< planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples) + AV_PIX_FMT_YUVA444P, ///< planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples) + AV_PIX_FMT_YUVA420P9BE, ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), big-endian + AV_PIX_FMT_YUVA420P9LE, ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), little-endian + AV_PIX_FMT_YUVA422P9BE, ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), big-endian + AV_PIX_FMT_YUVA422P9LE, ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), little-endian + AV_PIX_FMT_YUVA444P9BE, ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), big-endian + AV_PIX_FMT_YUVA444P9LE, ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), little-endian + AV_PIX_FMT_YUVA420P10BE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian) + AV_PIX_FMT_YUVA420P10LE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian) + AV_PIX_FMT_YUVA422P10BE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA422P10LE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA444P10BE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA444P10LE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA420P16BE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian) + AV_PIX_FMT_YUVA420P16LE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian) + AV_PIX_FMT_YUVA422P16BE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA422P16LE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA444P16BE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA444P16LE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian) + + AV_PIX_FMT_VDPAU, ///< HW acceleration through VDPAU, Picture.data[3] contains a VdpVideoSurface + + AV_PIX_FMT_XYZ12LE, ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as little-endian, the 4 lower bits are set to 0 + AV_PIX_FMT_XYZ12BE, ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as big-endian, the 4 lower bits are set to 0 + AV_PIX_FMT_NV16, ///< interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) + AV_PIX_FMT_NV20LE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_NV20BE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + + AV_PIX_FMT_RGBA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + AV_PIX_FMT_BGRA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + + AV_PIX_FMT_YVYU422, ///< packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb + + AV_PIX_FMT_YA16BE, ///< 16 bits gray, 16 bits alpha (big-endian) + AV_PIX_FMT_YA16LE, ///< 16 bits gray, 16 bits alpha (little-endian) + + AV_PIX_FMT_GBRAP, ///< planar GBRA 4:4:4:4 32bpp + AV_PIX_FMT_GBRAP16BE, ///< planar GBRA 4:4:4:4 64bpp, big-endian + AV_PIX_FMT_GBRAP16LE, ///< planar GBRA 4:4:4:4 64bpp, little-endian + /** + * HW acceleration through QSV, data[3] contains a pointer to the + * mfxFrameSurface1 structure. + */ + AV_PIX_FMT_QSV, + /** + * HW acceleration though MMAL, data[3] contains a pointer to the + * MMAL_BUFFER_HEADER_T structure. + */ + AV_PIX_FMT_MMAL, + + AV_PIX_FMT_D3D11VA_VLD, ///< HW decoding through Direct3D11 via old API, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer + + /** + * HW acceleration through CUDA. data[i] contain CUdeviceptr pointers + * exactly as for system memory frames. + */ + AV_PIX_FMT_CUDA, + + AV_PIX_FMT_0RGB, ///< packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined + AV_PIX_FMT_RGB0, ///< packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined + AV_PIX_FMT_0BGR, ///< packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined + AV_PIX_FMT_BGR0, ///< packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined + + AV_PIX_FMT_YUV420P12BE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P12LE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P14BE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P14LE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV422P14BE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P14LE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P14BE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P14LE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_GBRP12BE, ///< planar GBR 4:4:4 36bpp, big-endian + AV_PIX_FMT_GBRP12LE, ///< planar GBR 4:4:4 36bpp, little-endian + AV_PIX_FMT_GBRP14BE, ///< planar GBR 4:4:4 42bpp, big-endian + AV_PIX_FMT_GBRP14LE, ///< planar GBR 4:4:4 42bpp, little-endian + AV_PIX_FMT_YUVJ411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV411P and setting color_range + + AV_PIX_FMT_BAYER_BGGR8, ///< bayer, BGBG..(odd line), GRGR..(even line), 8-bit samples */ + AV_PIX_FMT_BAYER_RGGB8, ///< bayer, RGRG..(odd line), GBGB..(even line), 8-bit samples */ + AV_PIX_FMT_BAYER_GBRG8, ///< bayer, GBGB..(odd line), RGRG..(even line), 8-bit samples */ + AV_PIX_FMT_BAYER_GRBG8, ///< bayer, GRGR..(odd line), BGBG..(even line), 8-bit samples */ + AV_PIX_FMT_BAYER_BGGR16LE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, little-endian */ + AV_PIX_FMT_BAYER_BGGR16BE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, big-endian */ + AV_PIX_FMT_BAYER_RGGB16LE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, little-endian */ + AV_PIX_FMT_BAYER_RGGB16BE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, big-endian */ + AV_PIX_FMT_BAYER_GBRG16LE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, little-endian */ + AV_PIX_FMT_BAYER_GBRG16BE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, big-endian */ + AV_PIX_FMT_BAYER_GRBG16LE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, little-endian */ + AV_PIX_FMT_BAYER_GRBG16BE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, big-endian */ + + AV_PIX_FMT_XVMC,///< XVideo Motion Acceleration via common packet passing + + AV_PIX_FMT_YUV440P10LE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian + AV_PIX_FMT_YUV440P10BE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian + AV_PIX_FMT_YUV440P12LE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian + AV_PIX_FMT_YUV440P12BE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian + AV_PIX_FMT_AYUV64LE, ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), little-endian + AV_PIX_FMT_AYUV64BE, ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), big-endian + + AV_PIX_FMT_VIDEOTOOLBOX, ///< hardware decoding through Videotoolbox + + AV_PIX_FMT_P010LE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, little-endian + AV_PIX_FMT_P010BE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, big-endian + + AV_PIX_FMT_GBRAP12BE, ///< planar GBR 4:4:4:4 48bpp, big-endian + AV_PIX_FMT_GBRAP12LE, ///< planar GBR 4:4:4:4 48bpp, little-endian + + AV_PIX_FMT_GBRAP10BE, ///< planar GBR 4:4:4:4 40bpp, big-endian + AV_PIX_FMT_GBRAP10LE, ///< planar GBR 4:4:4:4 40bpp, little-endian + + AV_PIX_FMT_MEDIACODEC, ///< hardware decoding through MediaCodec + + AV_PIX_FMT_GRAY12BE, ///< Y , 12bpp, big-endian + AV_PIX_FMT_GRAY12LE, ///< Y , 12bpp, little-endian + AV_PIX_FMT_GRAY10BE, ///< Y , 10bpp, big-endian + AV_PIX_FMT_GRAY10LE, ///< Y , 10bpp, little-endian + + AV_PIX_FMT_P016LE, ///< like NV12, with 16bpp per component, little-endian + AV_PIX_FMT_P016BE, ///< like NV12, with 16bpp per component, big-endian + + /** + * Hardware surfaces for Direct3D11. + * + * This is preferred over the legacy AV_PIX_FMT_D3D11VA_VLD. The new D3D11 + * hwaccel API and filtering support AV_PIX_FMT_D3D11 only. + * + * data[0] contains a ID3D11Texture2D pointer, and data[1] contains the + * texture array index of the frame as intptr_t if the ID3D11Texture2D is + * an array texture (or always 0 if it's a normal texture). + */ + AV_PIX_FMT_D3D11, + + AV_PIX_FMT_GRAY9BE, ///< Y , 9bpp, big-endian + AV_PIX_FMT_GRAY9LE, ///< Y , 9bpp, little-endian + + AV_PIX_FMT_GBRPF32BE, ///< IEEE-754 single precision planar GBR 4:4:4, 96bpp, big-endian + AV_PIX_FMT_GBRPF32LE, ///< IEEE-754 single precision planar GBR 4:4:4, 96bpp, little-endian + AV_PIX_FMT_GBRAPF32BE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, big-endian + AV_PIX_FMT_GBRAPF32LE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, little-endian + + /** + * DRM-managed buffers exposed through PRIME buffer sharing. + * + * data[0] points to an AVDRMFrameDescriptor. + */ + AV_PIX_FMT_DRM_PRIME, + /** + * Hardware surfaces for OpenCL. + * + * data[i] contain 2D image objects (typed in C as cl_mem, used + * in OpenCL as image2d_t) for each plane of the surface. + */ + AV_PIX_FMT_OPENCL, + + AV_PIX_FMT_GRAY14BE, ///< Y , 14bpp, big-endian + AV_PIX_FMT_GRAY14LE, ///< Y , 14bpp, little-endian + + AV_PIX_FMT_GRAYF32BE, ///< IEEE-754 single precision Y, 32bpp, big-endian + AV_PIX_FMT_GRAYF32LE, ///< IEEE-754 single precision Y, 32bpp, little-endian + + AV_PIX_FMT_YUVA422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, big-endian + AV_PIX_FMT_YUVA422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, little-endian + AV_PIX_FMT_YUVA444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, big-endian + AV_PIX_FMT_YUVA444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, little-endian + + AV_PIX_FMT_NV24, ///< planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) + AV_PIX_FMT_NV42, ///< as above, but U and V bytes are swapped + + AV_PIX_FMT_NB ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions +}; + +#ifdef AV_HAVE_BIGENDIAN +#define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##be +#else +#define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##le +#endif + +#define AV_PIX_FMT_YUV420P10 AV_PIX_FMT_NE(YUV420P10BE, YUV420P10LE) +#define AV_PIX_FMT_YUV422P10 AV_PIX_FMT_NE(YUV422P10BE, YUV422P10LE) +#define AV_PIX_FMT_YUV440P10 AV_PIX_FMT_NE(YUV440P10BE, YUV440P10LE) +#define AV_PIX_FMT_YUV444P10 AV_PIX_FMT_NE(YUV444P10BE, YUV444P10LE) +#define AV_PIX_FMT_YUV420P12 AV_PIX_FMT_NE(YUV420P12BE, YUV420P12LE) +#define AV_PIX_FMT_YUV422P12 AV_PIX_FMT_NE(YUV422P12BE, YUV422P12LE) +#define AV_PIX_FMT_YUV440P12 AV_PIX_FMT_NE(YUV440P12BE, YUV440P12LE) +#define AV_PIX_FMT_YUV444P12 AV_PIX_FMT_NE(YUV444P12BE, YUV444P12LE) + + +#define AV_PIX_FMT_GBRP9 AV_PIX_FMT_NE(GBRP9BE , GBRP9LE) +#define AV_PIX_FMT_GBRP10 AV_PIX_FMT_NE(GBRP10BE, GBRP10LE) +#define AV_PIX_FMT_GBRP12 AV_PIX_FMT_NE(GBRP12BE, GBRP12LE) +#define AV_PIX_FMT_GBRP14 AV_PIX_FMT_NE(GBRP14BE, GBRP14LE) +#define AV_PIX_FMT_GBRP16 AV_PIX_FMT_NE(GBRP16BE, GBRP16LE) +#define AV_PIX_FMT_GBRAP10 AV_PIX_FMT_NE(GBRAP10BE, GBRAP10LE) +#define AV_PIX_FMT_GBRAP12 AV_PIX_FMT_NE(GBRAP12BE, GBRAP12LE) +#define AV_PIX_FMT_GBRAP16 AV_PIX_FMT_NE(GBRAP16BE, GBRAP16LE) + +#define AV_PIX_FMT_GRAY9 AV_PIX_FMT_NE(GRAY9BE, GRAY9LE) +#define AV_PIX_FMT_GRAY10 AV_PIX_FMT_NE(GRAY10BE, GRAY10LE) +#define AV_PIX_FMT_GRAY12 AV_PIX_FMT_NE(GRAY12BE, GRAY12LE) + +#define AV_PIX_FMT_YUV420P9 AV_PIX_FMT_NE(YUV420P9BE , YUV420P9LE) +#define AV_PIX_FMT_YUV422P9 AV_PIX_FMT_NE(YUV422P9BE , YUV422P9LE) +#define AV_PIX_FMT_YUV444P9 AV_PIX_FMT_NE(YUV444P9BE , YUV444P9LE) + +/** + * Chromaticity coordinates of the source primaries. + * These values match the ones defined by ISO/IEC 23001-8_2013 § 7.1. + */ +enum AVColorPrimaries { + AVCOL_PRI_RESERVED0 = 0, + AVCOL_PRI_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B + AVCOL_PRI_UNSPECIFIED = 2, + AVCOL_PRI_RESERVED = 3, + AVCOL_PRI_BT470M = 4, ///< also FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + + AVCOL_PRI_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM + AVCOL_PRI_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC + AVCOL_PRI_SMPTE240M = 7, ///< functionally identical to above + AVCOL_PRI_FILM = 8, ///< colour filters using Illuminant C + AVCOL_PRI_BT2020 = 9, ///< ITU-R BT2020 + AVCOL_PRI_SMPTE428 = 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ) + AVCOL_PRI_SMPTEST428_1 = AVCOL_PRI_SMPTE428, + AVCOL_PRI_SMPTE431 = 11, ///< SMPTE ST 431-2 (2011) / DCI P3 + AVCOL_PRI_SMPTE432 = 12, ///< SMPTE ST 432-1 (2010) / P3 D65 / Display P3 + AVCOL_PRI_JEDEC_P22 = 22, ///< JEDEC P22 phosphors + AVCOL_PRI_NB ///< Not part of ABI +}; + +/** + * Color Transfer Characteristic. + * These values match the ones defined by ISO/IEC 23001-8_2013 § 7.2. + */ +enum AVColorTransferCharacteristic { + AVCOL_TRC_RESERVED0 = 0, + AVCOL_TRC_BT709 = 1, ///< also ITU-R BT1361 + AVCOL_TRC_UNSPECIFIED = 2, + AVCOL_TRC_RESERVED = 3, + AVCOL_TRC_GAMMA22 = 4, ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM + AVCOL_TRC_GAMMA28 = 5, ///< also ITU-R BT470BG + AVCOL_TRC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC + AVCOL_TRC_SMPTE240M = 7, + AVCOL_TRC_LINEAR = 8, ///< "Linear transfer characteristics" + AVCOL_TRC_LOG = 9, ///< "Logarithmic transfer characteristic (100:1 range)" + AVCOL_TRC_LOG_SQRT = 10, ///< "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)" + AVCOL_TRC_IEC61966_2_4 = 11, ///< IEC 61966-2-4 + AVCOL_TRC_BT1361_ECG = 12, ///< ITU-R BT1361 Extended Colour Gamut + AVCOL_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC) + AVCOL_TRC_BT2020_10 = 14, ///< ITU-R BT2020 for 10-bit system + AVCOL_TRC_BT2020_12 = 15, ///< ITU-R BT2020 for 12-bit system + AVCOL_TRC_SMPTE2084 = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems + AVCOL_TRC_SMPTEST2084 = AVCOL_TRC_SMPTE2084, + AVCOL_TRC_SMPTE428 = 17, ///< SMPTE ST 428-1 + AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428, + AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma" + AVCOL_TRC_NB ///< Not part of ABI +}; + +/** + * YUV colorspace type. + * These values match the ones defined by ISO/IEC 23001-8_2013 § 7.3. + */ +enum AVColorSpace { + AVCOL_SPC_RGB = 0, ///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB) + AVCOL_SPC_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B + AVCOL_SPC_UNSPECIFIED = 2, + AVCOL_SPC_RESERVED = 3, + AVCOL_SPC_FCC = 4, ///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + AVCOL_SPC_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601 + AVCOL_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC + AVCOL_SPC_SMPTE240M = 7, ///< functionally identical to above + AVCOL_SPC_YCGCO = 8, ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16 + AVCOL_SPC_YCOCG = AVCOL_SPC_YCGCO, + AVCOL_SPC_BT2020_NCL = 9, ///< ITU-R BT2020 non-constant luminance system + AVCOL_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance system + AVCOL_SPC_SMPTE2085 = 11, ///< SMPTE 2085, Y'D'zD'x + AVCOL_SPC_CHROMA_DERIVED_NCL = 12, ///< Chromaticity-derived non-constant luminance system + AVCOL_SPC_CHROMA_DERIVED_CL = 13, ///< Chromaticity-derived constant luminance system + AVCOL_SPC_ICTCP = 14, ///< ITU-R BT.2100-0, ICtCp + AVCOL_SPC_NB ///< Not part of ABI +}; + +/** + * MPEG vs JPEG YUV range. + */ +enum AVColorRange { + AVCOL_RANGE_UNSPECIFIED = 0, + AVCOL_RANGE_MPEG = 1, ///< the normal 219*2^(n-8) "MPEG" YUV ranges + AVCOL_RANGE_JPEG = 2, ///< the normal 2^n-1 "JPEG" YUV ranges + AVCOL_RANGE_NB ///< Not part of ABI +}; + +/** + * Location of chroma samples. + * + * Illustration showing the location of the first (top left) chroma sample of the + * image, the left shows only luma, the right + * shows the location of the chroma sample, the 2 could be imagined to overlay + * each other but are drawn separately due to limitations of ASCII + * + * 1st 2nd 1st 2nd horizontal luma sample positions + * v v v v + * ______ ______ + *1st luma line > |X X ... |3 4 X ... X are luma samples, + * | |1 2 1-6 are possible chroma positions + *2nd luma line > |X X ... |5 6 X ... 0 is undefined/unknown position + */ +enum AVChromaLocation { + AVCHROMA_LOC_UNSPECIFIED = 0, + AVCHROMA_LOC_LEFT = 1, ///< MPEG-2/4 4:2:0, H.264 default for 4:2:0 + AVCHROMA_LOC_CENTER = 2, ///< MPEG-1 4:2:0, JPEG 4:2:0, H.263 4:2:0 + AVCHROMA_LOC_TOPLEFT = 3, ///< ITU-R 601, SMPTE 274M 296M S314M(DV 4:1:1), mpeg2 4:2:2 + AVCHROMA_LOC_TOP = 4, + AVCHROMA_LOC_BOTTOMLEFT = 5, + AVCHROMA_LOC_BOTTOM = 6, + AVCHROMA_LOC_NB ///< Not part of ABI +}; + +#endif /* AVUTIL_PIXFMT_H */ + diff --git a/drivers/amvdec_ports/utils/put_bits.h b/drivers/amvdec_ports/utils/put_bits.h new file mode 100644 index 0000000..8b2aa15 --- a/dev/null +++ b/drivers/amvdec_ports/utils/put_bits.h @@ -0,0 +1,323 @@ +#ifndef AVCODEC_PUT_BITS_H +#define AVCODEC_PUT_BITS_H + +#include <linux/kernel.h> +#include <linux/types.h> +#include "common.h" + +struct put_bits_context { + u32 bit_buf; + int bit_left; + u8 *buf; + u8 *buf_ptr; + u8 *buf_end; + int size_in_bits; +}; + +/** + * Initialize the struct put_bits_context s. + * + * @param buffer the buffer where to put bits + * @param buffer_size the size in bytes of buffer + */ +static inline void init_put_bits(struct put_bits_context *s, + u8 *buffer, int buffer_size) +{ + if (buffer_size < 0) { + buffer_size = 0; + buffer = NULL; + } + + s->size_in_bits = 8 * buffer_size; + s->buf = buffer; + s->buf_end = s->buf + buffer_size; + s->buf_ptr = s->buf; + s->bit_left = 32; + s->bit_buf = 0; +} + +/** + * Rebase the bit writer onto a reallocated buffer. + * + * @param buffer the buffer where to put bits + * @param buffer_size the size in bytes of buffer, + * must be larger than the previous size + */ +static inline void rebase_put_bits(struct put_bits_context *s, + u8 *buffer, int buffer_size) +{ + s->buf_end = buffer + buffer_size; + s->buf_ptr = buffer + (s->buf_ptr - s->buf); + s->buf = buffer; + s->size_in_bits = 8 * buffer_size; +} + +/** + * @return the total number of bits written to the bitstream. + */ +static inline int put_bits_count(struct put_bits_context *s) +{ + return (s->buf_ptr - s->buf) * 8 + 32 - s->bit_left; +} + +/** + * @return the number of bits available in the bitstream. + */ +static inline int put_bits_left(struct put_bits_context* s) +{ + return (s->buf_end - s->buf_ptr) * 8 - 32 + s->bit_left; +} + +/** + * Pad the end of the output stream with zeros. + */ +static inline void flush_put_bits(struct put_bits_context *s) +{ +#ifndef BITSTREAM_WRITER_LE + if (s->bit_left < 32) + s->bit_buf <<= s->bit_left; +#endif + while (s->bit_left < 32) { +#ifdef BITSTREAM_WRITER_LE + *s->buf_ptr++ = s->bit_buf; + s->bit_buf >>= 8; +#else + *s->buf_ptr++ = s->bit_buf >> 24; + s->bit_buf <<= 8; +#endif + s->bit_left += 8; + } + s->bit_left = 32; + s->bit_buf = 0; +} + +static inline void flush_put_bits_le(struct put_bits_context *s) +{ + while (s->bit_left < 32) { + *s->buf_ptr++ = s->bit_buf; + s->bit_buf >>= 8; + s->bit_left += 8; + } + s->bit_left = 32; + s->bit_buf = 0; +} + +#ifdef BITSTREAM_WRITER_LE +#define avpriv_align_put_bits align_put_bits_unsupported_here +#define avpriv_put_string ff_put_string_unsupported_here +#define avpriv_copy_bits avpriv_copy_bits_unsupported_here +#else +/** + * Pad the bitstream with zeros up to the next byte boundary. + */ +void avpriv_align_put_bits(struct put_bits_context *s); + +/** + * Put the string string in the bitstream. + * + * @param terminate_string 0-terminates the written string if value is 1 + */ +void avpriv_put_string(struct put_bits_context *pb, + const char *string, int terminate_string); + +/** + * Copy the content of src to the bitstream. + * + * @param length the number of bits of src to copy + */ +void avpriv_copy_bits(struct put_bits_context *pb, const u8 *src, int length); +#endif + +/** + * Write up to 31 bits into a bitstream. + * Use put_bits32 to write 32 bits. + */ +static inline void put_bits(struct put_bits_context *s, int n, u32 value) +{ + u32 bit_buf; + int bit_left; + + bit_buf = s->bit_buf; + bit_left = s->bit_left; + + /* XXX: optimize */ +#ifdef BITSTREAM_WRITER_LE + bit_buf |= value << (32 - bit_left); + if (n >= bit_left) { + if (3 < s->buf_end - s->buf_ptr) { + AV_WL32(s->buf_ptr, bit_buf); + s->buf_ptr += 4; + } else { + pr_err("Internal error, put_bits buffer too small\n"); + } + bit_buf = value >> bit_left; + bit_left += 32; + } + bit_left -= n; +#else + if (n < bit_left) { + bit_buf = (bit_buf << n) | value; + bit_left -= n; + } else { + bit_buf <<= bit_left; + bit_buf |= value >> (n - bit_left); + if (3 < s->buf_end - s->buf_ptr) { + AV_WB32(s->buf_ptr, bit_buf); + s->buf_ptr += 4; + } else { + pr_err("Internal error, put_bits buffer too small\n"); + } + bit_left += 32 - n; + bit_buf = value; + } +#endif + s->bit_buf = bit_buf; + s->bit_left = bit_left; +} + +static inline void put_bits_le(struct put_bits_context *s, int n, u32 value) +{ + u32 bit_buf; + int bit_left; + + bit_buf = s->bit_buf; + bit_left = s->bit_left; + + bit_buf |= value << (32 - bit_left); + if (n >= bit_left) { + if (3 < s->buf_end - s->buf_ptr) { + AV_WL32(s->buf_ptr, bit_buf); + s->buf_ptr += 4; + } else { + pr_err("Internal error, put_bits buffer too small\n"); + } + bit_buf = value >> bit_left; + bit_left += 32; + } + bit_left -= n; + + s->bit_buf = bit_buf; + s->bit_left = bit_left; +} + +static inline u32 av_mod_uintp2(u32 a, u32 p) +{ + return a & ((1 << p) - 1); +} + +static inline void put_sbits(struct put_bits_context *pb, int n, int32_t value) +{ + put_bits(pb, n, av_mod_uintp2(value, n)); +} + +/** + * Write exactly 32 bits into a bitstream. + */ +static void put_bits32(struct put_bits_context *s, u32 value) +{ + u32 bit_buf; + int bit_left; + + bit_buf = s->bit_buf; + bit_left = s->bit_left; + +#ifdef BITSTREAM_WRITER_LE + bit_buf |= value << (32 - bit_left); + if (3 < s->buf_end - s->buf_ptr) { + AV_WL32(s->buf_ptr, bit_buf); + s->buf_ptr += 4; + } else { + pr_err("Internal error, put_bits buffer too small\n"); + } + bit_buf = (uint64_t)value >> bit_left; +#else + bit_buf = (uint64_t)bit_buf << bit_left; + bit_buf |= value >> (32 - bit_left); + if (3 < s->buf_end - s->buf_ptr) { + AV_WB32(s->buf_ptr, bit_buf); + s->buf_ptr += 4; + } else { + pr_err("Internal error, put_bits buffer too small\n"); + } + bit_buf = value; +#endif + + s->bit_buf = bit_buf; + s->bit_left = bit_left; +} + +/** + * Write up to 64 bits into a bitstream. + */ +static inline void put_bits64(struct put_bits_context *s, int n, uint64_t value) +{ + if (n < 32) + put_bits(s, n, value); + else if (n == 32) + put_bits32(s, value); + else if (n < 64) { + u32 lo = value & 0xffffffff; + u32 hi = value >> 32; +#ifdef BITSTREAM_WRITER_LE + put_bits32(s, lo); + put_bits(s, n - 32, hi); +#else + put_bits(s, n - 32, hi); + put_bits32(s, lo); +#endif + } else { + u32 lo = value & 0xffffffff; + u32 hi = value >> 32; +#ifdef BITSTREAM_WRITER_LE + put_bits32(s, lo); + put_bits32(s, hi); +#else + put_bits32(s, hi); + put_bits32(s, lo); +#endif + } +} + +/** + * Return the pointer to the byte where the bitstream writer will put + * the next bit. + */ +static inline u8 *put_bits_ptr(struct put_bits_context *s) +{ + return s->buf_ptr; +} + +/** + * Skip the given number of bytes. + * struct put_bits_context must be flushed & aligned to a byte boundary before calling this. + */ +static inline void skip_put_bytes(struct put_bits_context *s, int n) +{ + s->buf_ptr += n; +} + +/** + * Skip the given number of bits. + * Must only be used if the actual values in the bitstream do not matter. + * If n is 0 the behavior is undefined. + */ +static inline void skip_put_bits(struct put_bits_context *s, int n) +{ + s->bit_left -= n; + s->buf_ptr -= 4 * (s->bit_left >> 5); + s->bit_left &= 31; +} + +/** + * Change the end of the buffer. + * + * @param size the new size in bytes of the buffer where to put bits + */ +static inline void set_put_bits_buffer_size(struct put_bits_context *s, int size) +{ + s->buf_end = s->buf + size; + s->size_in_bits = 8*size; +} + +#endif /* AVCODEC_PUT_BITS_H */ + diff --git a/drivers/amvdec_ports/vdec_drv_base.h b/drivers/amvdec_ports/vdec_drv_base.h index dfe5d27..e192b20 100644 --- a/drivers/amvdec_ports/vdec_drv_base.h +++ b/drivers/amvdec_ports/vdec_drv_base.h @@ -43,7 +43,7 @@ struct vdec_common_if { * @res_chg : [out] resolution change happen */ int (*decode)(unsigned long h_vdec, struct aml_vcodec_mem *bs, - unsigned long int pts, bool *res_chg); + u64 pts, bool *res_chg); /** * (*get_param)() - get driver's parameter @@ -55,6 +55,15 @@ struct vdec_common_if { enum vdec_get_param_type type, void *out); /** + * (*set_param)() - set driver's parameter + * @h_vdec : [in] driver handle + * @type : [in] input parameter type + * @in : [in] buffer to store query result + */ + int (*set_param)(unsigned long h_vdec, + enum vdec_set_param_type type, void *in); + + /** * (*deinit)() - deinitialize driver. * @h_vdec : [in] driver handle to be deinit */ diff --git a/drivers/amvdec_ports/vdec_drv_if.c b/drivers/amvdec_ports/vdec_drv_if.c index d69ef9f..4b70ed0 100644 --- a/drivers/amvdec_ports/vdec_drv_if.c +++ b/drivers/amvdec_ports/vdec_drv_if.c @@ -29,6 +29,9 @@ const struct vdec_common_if *get_h264_dec_comm_if(void); const struct vdec_common_if *get_hevc_dec_comm_if(void); const struct vdec_common_if *get_vp9_dec_comm_if(void); +const struct vdec_common_if *get_mpeg12_dec_comm_if(void); +const struct vdec_common_if *get_mpeg4_dec_comm_if(void); +const struct vdec_common_if *get_mjpeg_dec_comm_if(void); int vdec_if_init(struct aml_vcodec_ctx *ctx, unsigned int fourcc) { @@ -44,15 +47,22 @@ int vdec_if_init(struct aml_vcodec_ctx *ctx, unsigned int fourcc) case V4L2_PIX_FMT_VP9: ctx->dec_if = get_vp9_dec_comm_if(); break; + case V4L2_PIX_FMT_MPEG: + case V4L2_PIX_FMT_MPEG1: + case V4L2_PIX_FMT_MPEG2: + ctx->dec_if = get_mpeg12_dec_comm_if(); + break; + case V4L2_PIX_FMT_MPEG4: + ctx->dec_if = get_mpeg4_dec_comm_if(); + break; + case V4L2_PIX_FMT_MJPEG: + ctx->dec_if = get_mjpeg_dec_comm_if(); + break; default: return -EINVAL; } - aml_vdec_lock(ctx); - //aml_vcodec_dec_clock_on(&ctx->dev->pm);//debug_tmp ret = ctx->dec_if->init(ctx, &ctx->drv_handle); - //aml_vcodec_dec_clock_off(&ctx->dev->pm); - aml_vdec_unlock(ctx); return ret; } @@ -62,15 +72,13 @@ int vdec_if_probe(struct aml_vcodec_ctx *ctx, { int ret = 0; - aml_vdec_lock(ctx); ret = ctx->dec_if->probe(ctx->drv_handle, bs, out); - aml_vdec_unlock(ctx); return ret; } int vdec_if_decode(struct aml_vcodec_ctx *ctx, struct aml_vcodec_mem *bs, - unsigned long int timestamp, bool *res_chg) + u64 timestamp, bool *res_chg) { int ret = 0; @@ -81,29 +89,13 @@ int vdec_if_decode(struct aml_vcodec_ctx *ctx, struct aml_vcodec_mem *bs, } } - /*if (fb) { - if (((fb->base_y.dma_addr & 511) != 0) || - ((fb->base_c.dma_addr & 511) != 0)) { - aml_v4l2_err("frame buffer dma_addr should 512 byte align"); - return -EINVAL; - } - }*/ - if (ctx->drv_handle == 0) return -EIO; - //aml_vdec_lock(ctx); - aml_vcodec_set_curr_ctx(ctx->dev, ctx); - //aml_vcodec_dec_clock_on(&ctx->dev->pm);//debug_tmp - //enable_irq(ctx->dev->dec_irq); ret = ctx->dec_if->decode(ctx->drv_handle, bs, timestamp, res_chg); - //disable_irq(ctx->dev->dec_irq); - //aml_vcodec_dec_clock_off(&ctx->dev->pm); aml_vcodec_set_curr_ctx(ctx->dev, NULL); - //aml_vdec_unlock(ctx); - return ret; } @@ -115,9 +107,7 @@ int vdec_if_get_param(struct aml_vcodec_ctx *ctx, if (ctx->drv_handle == 0) return -EIO; - //aml_vdec_lock(ctx); ret = ctx->dec_if->get_param(ctx->drv_handle, type, out); - //aml_vdec_unlock(ctx); return ret; } @@ -127,11 +117,6 @@ void vdec_if_deinit(struct aml_vcodec_ctx *ctx) if (ctx->drv_handle == 0) return; - //aml_vdec_lock(ctx); - //aml_vcodec_dec_clock_on(&ctx->dev->pm); ctx->dec_if->deinit(ctx->drv_handle); - //aml_vcodec_dec_clock_off(&ctx->dev->pm); - //aml_vdec_unlock(ctx); - ctx->drv_handle = 0; } diff --git a/drivers/amvdec_ports/vdec_drv_if.h b/drivers/amvdec_ports/vdec_drv_if.h index 1ac7045..29e48d3 100644 --- a/drivers/amvdec_ports/vdec_drv_if.h +++ b/drivers/amvdec_ports/vdec_drv_if.h @@ -71,6 +71,14 @@ enum vdec_get_param_type { GET_PARAM_DPB_SIZE }; +/* + * SET_PARAM_PIC_INFO : set picture info, data parsed from ucode. + */ +enum vdec_set_param_type { + SET_PARAM_WRITE_FRAME_SYNC, + SET_PARAM_PIC_INFO, +}; + /** * struct vdec_fb_node - decoder frame buffer node * @list : list to hold this node @@ -112,7 +120,7 @@ void vdec_if_deinit(struct aml_vcodec_ctx *ctx); * Return: 0 on success. -EIO on unrecoverable error. */ int vdec_if_decode(struct aml_vcodec_ctx *ctx, struct aml_vcodec_mem *bs, - unsigned long int timestamp, bool *res_chg); + u64 timestamp, bool *res_chg); /** * vdec_if_get_param() - get driver's parameter diff --git a/drivers/frame_provider/decoder/avs/avs.c b/drivers/frame_provider/decoder/avs/avs.c index 5d85fb9..642c3bb 100644 --- a/drivers/frame_provider/decoder/avs/avs.c +++ b/drivers/frame_provider/decoder/avs/avs.c @@ -1722,6 +1722,10 @@ static int amvdec_avs_probe(struct platform_device *pdev) static int amvdec_avs_remove(struct platform_device *pdev) { + if (stat & STAT_TIMER_ARM) { + del_timer_sync(&recycle_timer); + stat &= ~STAT_TIMER_ARM; + } cancel_work_sync(&fatal_error_wd_work); atomic_set(&error_handler_run, 0); @@ -1738,10 +1742,6 @@ static int amvdec_avs_remove(struct platform_device *pdev) stat &= ~STAT_ISR_REG; } - if (stat & STAT_TIMER_ARM) { - del_timer_sync(&recycle_timer); - stat &= ~STAT_TIMER_ARM; - } #ifdef AVSP_LONG_CABAC if (firmware_sel == 0) { mutex_lock(&vavs_mutex); diff --git a/drivers/frame_provider/decoder/avs2/vavs2.c b/drivers/frame_provider/decoder/avs2/vavs2.c index e958825..6258a75 100644 --- a/drivers/frame_provider/decoder/avs2/vavs2.c +++ b/drivers/frame_provider/decoder/avs2/vavs2.c @@ -250,7 +250,7 @@ static u32 work_buf_size = 32 * 1024 * 1024; static u32 mv_buf_margin; static int pre_decode_buf_level = 0x1000; -static u32 again_threshold = 0x40; +static u32 again_threshold; /* DOUBLE_WRITE_MODE is enabled only when NV21 8 bit output is needed */ @@ -266,6 +266,7 @@ static u32 again_threshold = 0x40; * 0x300, if > 720p, use mode 4, else use mode 1; */ static u32 double_write_mode; +static u32 without_display_mode; #define DRIVER_NAME "amvdec_avs2" #define MODULE_NAME "amvdec_avs2" @@ -4584,8 +4585,11 @@ static int avs2_prepare_display_buf(struct AVS2Decoder_s *dec) vdec_count_info(gvs, 0, stream_offset); #endif hw_to_vdec(dec)->vdec_fps_detec(hw_to_vdec(dec)->id); - vf_notify_receiver(dec->provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + if (without_display_mode == 0) { + vf_notify_receiver(dec->provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } else + vavs2_vf_put(vavs2_vf_get(dec), dec); } } /*!NO_DISPLAY*/ @@ -7773,6 +7777,9 @@ module_param(force_disp_pic_index, int, 0664); MODULE_PARM_DESC(force_disp_pic_index, "\n amvdec_h265 force_disp_pic_index\n"); +module_param(without_display_mode, uint, 0664); +MODULE_PARM_DESC(without_display_mode, "\n without_display_mode\n"); + module_init(amvdec_avs2_driver_init_module); module_exit(amvdec_avs2_driver_remove_module); diff --git a/drivers/frame_provider/decoder/h264_multi/h264_dpb.c b/drivers/frame_provider/decoder/h264_multi/h264_dpb.c index 2b9a920..2258f75 100644 --- a/drivers/frame_provider/decoder/h264_multi/h264_dpb.c +++ b/drivers/frame_provider/decoder/h264_multi/h264_dpb.c @@ -202,7 +202,7 @@ void ref_pic_list_reordering(struct h264_dpb_stru *p_H264_Dpb, */ i >= REORDERING_COMMAND_MAX_SIZE) { dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_ERROR, + PRINT_FLAG_DPB_DETAIL, "%s error %d %d\n", __func__, i, currSlice-> @@ -300,7 +300,7 @@ void ref_pic_list_reordering(struct h264_dpb_stru *p_H264_Dpb, /*i>currSlice->num_ref_idx_active[LIST_1] || */ i >= REORDERING_COMMAND_MAX_SIZE) { dpb_print(p_H264_Dpb->decoder_index, - PRINT_FLAG_ERROR, + PRINT_FLAG_DPB_DETAIL, "%s error %d %d\n", __func__, i, currSlice-> diff --git a/drivers/frame_provider/decoder/h264_multi/h264_dpb.h b/drivers/frame_provider/decoder/h264_multi/h264_dpb.h index f3c8114..471ffa5 100644 --- a/drivers/frame_provider/decoder/h264_multi/h264_dpb.h +++ b/drivers/frame_provider/decoder/h264_multi/h264_dpb.h @@ -41,6 +41,18 @@ #define PRINT_FLAG_V4L_DETAIL 0x8000 #define DISABLE_ERROR_HANDLE 0x10000 #define DEBUG_DUMP_STAT 0x80000 +/*setting canvas mode and endian. + if this flag is set, value of canvas mode + will according to the value of mem_map_mode. + endian will be forced set to 0 in + CANVAS_BLKMODE_LINEAR mode. + otherwise picture will display abnormal. + if this flag is not set, value of canvas mode + will be determined by the user speace config. + endian will be set 7 in CANVAS_BLKMODE_LINEAR mode. +*/ +#define IGNORE_PARAM_FROM_CONFIG 0x8000000 + #define PIC_SINGLE_FRAME 0 #define PIC_TOP_BOT_TOP 1 diff --git a/drivers/frame_provider/decoder/h264_multi/vmh264.c b/drivers/frame_provider/decoder/h264_multi/vmh264.c index aa065e5..35d67ad 100644 --- a/drivers/frame_provider/decoder/h264_multi/vmh264.c +++ b/drivers/frame_provider/decoder/h264_multi/vmh264.c @@ -58,13 +58,10 @@ #include <linux/amlogic/tee.h> #include <linux/uaccess.h> #include "../utils/config_parser.h" -#include "../../../amvdec_ports/vdec_drv_base.h" -#include "../../../amvdec_ports/aml_vcodec_adapt.h" #include "../../../common/chips/decoder_cpu_ver_info.h" +#include "../utils/vdec_v4l2_buffer_ops.h" #include <linux/crc32.h> - - #undef pr_info #define pr_info printk #define VDEC_DW @@ -120,6 +117,7 @@ #define H264_MMU #define VIDEO_SIGNAL_TYPE_AVAILABLE_MASK 0x20000000 + static int mmu_enable; /*mmu do not support mbaff*/ static int force_enable_mmu = 0; @@ -140,7 +138,7 @@ static unsigned int force_rate_framebase; static unsigned int force_disp_bufspec_num; static unsigned int fixed_frame_rate_mode; static unsigned int error_recovery_mode_in; -static int start_decode_buf_level = 0x8000; +static int start_decode_buf_level = 0x4000; static int pre_decode_buf_level = 0x1000; static int stream_mode_start_num = 4; @@ -319,7 +317,7 @@ static unsigned int frmbase_cont_bitlevel2 = 0x1; 0x20000: vdec dw horizotal/vertical 1/2 */ static u32 double_write_mode; - +static u32 without_display_mode; #define IS_VDEC_DW(hw) (hw->double_write_mode >> 16 & 0xf) static void vmh264_dump_state(struct vdec_s *vdec); @@ -482,6 +480,7 @@ static void vh264_vf_put(struct vframe_s *, void *); static int vh264_vf_states(struct vframe_states *states, void *); static int vh264_event_cb(int type, void *data, void *private_data); static void vh264_work(struct work_struct *work); +static void vh264_timeout_work(struct work_struct *work); static void vh264_notify_work(struct work_struct *work); #ifdef MH264_USERDATA_ENABLE static void user_data_ready_notify_work(struct work_struct *work); @@ -667,6 +666,7 @@ struct vdec_h264_hw_s { u8 config_bufmgr_done; u32 max_reference_size; u32 decode_pic_count; + u32 reflist_error_count; int start_search_pos; u32 reg_iqidct_control; u32 reg_vcop_ctrl_reg; @@ -830,6 +830,7 @@ struct vdec_h264_hw_s { u32 canvas_mode; bool is_used_v4l; void *v4l2_ctx; + bool v4l_params_parsed; wait_queue_head_t wait_q; u32 reg_g_status; struct mutex chunks_mutex; @@ -846,8 +847,9 @@ struct vdec_h264_hw_s { unsigned int first_i_policy; }; -static u32 again_threshold = 0x40; +static u32 again_threshold; +static void timeout_process(struct vdec_h264_hw_s *hw); static void dump_bufspec(struct vdec_h264_hw_s *hw, const char *caller); static void h264_reconfig(struct vdec_h264_hw_s *hw); @@ -1771,16 +1773,6 @@ static int alloc_one_buf_spec(struct vdec_h264_hw_s *hw, int i) return 0; } -static int v4l_get_fb(struct aml_vcodec_ctx *ctx, struct vdec_fb **out) -{ - int ret = 0; - - ret = ctx->dec_if->get_param(ctx->drv_handle, - GET_PARAM_FREE_FRAME_BUFFER, out); - - return ret; -} - static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) { int ret = 0; @@ -1788,8 +1780,8 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) struct buffer_spec_s *bs = &hw->buffer_spec[idx]; struct canvas_config_s *y_canvas_cfg = NULL; struct canvas_config_s *c_canvas_cfg = NULL; - struct vdec_fb *fb = NULL; - unsigned int y_addr, c_addr; + struct vdec_v4l2_buffer *fb = NULL; + unsigned int y_addr = 0, c_addr = 0; if (IS_ERR_OR_NULL(hw->v4l2_ctx)) { pr_err("the v4l context has err.\n"); @@ -1805,9 +1797,9 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) ctx->id, __func__, (hw->mb_total << 8) + (hw->mb_total << 7)); - ret = v4l_get_fb(hw->v4l2_ctx, &fb); + ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb); if (ret) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, "[%d] get fb fail.\n", ctx->id); return ret; } @@ -1817,15 +1809,23 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) "[%d] %s(), cma alloc addr: 0x%x\n", ctx->id, __func__, bs->cma_alloc_addr); - y_addr = virt_to_phys(fb->base_y.va); - c_addr = virt_to_phys(fb->base_c.va); + if (fb->num_planes == 1) { + y_addr = fb->m.mem[0].addr; + c_addr = fb->m.mem[0].addr + fb->m.mem[0].offset; + fb->m.mem[0].bytes_used = fb->m.mem[0].size; + } else if (fb->num_planes == 2) { + y_addr = fb->m.mem[0].addr; + c_addr = fb->m.mem[1].addr; + fb->m.mem[0].bytes_used = fb->m.mem[0].size; + fb->m.mem[1].bytes_used = fb->m.mem[1].size; + } dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "[%d] %s(), y_addr: %x, va: %p\n", - ctx->id, __func__, y_addr, fb->base_y.va); + "[%d] %s(), y_addr: %x, size: %u\n", + ctx->id, __func__, y_addr, fb->m.mem[0].size); dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, - "[%d] %s(), c_addr: %x, va: %p\n", - ctx->id, __func__, c_addr, fb->base_c.va); + "[%d] %s(), c_addr: %x, size: %u\n", + ctx->id, __func__, c_addr, fb->m.mem[1].size); bs->y_addr = y_addr; bs->u_addr = c_addr; @@ -1838,7 +1838,7 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) y_canvas_cfg->width = hw->mb_width << 4; y_canvas_cfg->height = hw->mb_height << 4; y_canvas_cfg->block_mode = CANVAS_BLKMODE_LINEAR; - fb->base_y.bytes_used = y_canvas_cfg->width * y_canvas_cfg->height; + //fb->m.mem[0].bytes_used = y_canvas_cfg->width * y_canvas_cfg->height; dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, "[%d] %s(), y_w: %d, y_h: %d\n", ctx->id, __func__, y_canvas_cfg->width,y_canvas_cfg->height); @@ -1847,7 +1847,7 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) c_canvas_cfg->width = hw->mb_width << 4; c_canvas_cfg->height = hw->mb_height << 3; c_canvas_cfg->block_mode = CANVAS_BLKMODE_LINEAR; - fb->base_c.bytes_used = c_canvas_cfg->width * c_canvas_cfg->height; + //fb->m.mem[1].bytes_used = c_canvas_cfg->width * c_canvas_cfg->height; dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, "[%d] %s(), c_w: %d, c_h: %d\n", ctx->id, __func__, c_canvas_cfg->width, c_canvas_cfg->height); @@ -1866,7 +1866,10 @@ static void config_decode_canvas(struct vdec_h264_hw_s *hw, int i) if (hw->canvas_mode == CANVAS_BLKMODE_LINEAR) { blkmode = CANVAS_BLKMODE_LINEAR; - endian = 7; + if ((h264_debug_flag & IGNORE_PARAM_FROM_CONFIG) == 0) + endian = 7; + else + endian = 0; } if (hw->is_used_v4l) { @@ -2029,14 +2032,25 @@ int get_free_buf_idx(struct vdec_s *vdec) int index = -1; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; int buf_total = BUFSPEC_POOL_SIZE; + + if (hw->is_used_v4l) + buf_total = hw->dpb.mDPB.size; + spin_lock_irqsave(&hw->bufspec_lock, flags); /*hw->start_search_pos = 0;*/ for (i = hw->start_search_pos; i < buf_total; i++) { if (hw->mmu_enable) addr = hw->buffer_spec[i].alloc_header_addr; - else + else { addr = hw->buffer_spec[i].cma_alloc_addr; - if (hw->buffer_spec[i].used == 0 && addr) { + if (hw->is_used_v4l && !addr) { + if (!alloc_one_buf_spec_from_queue(hw, i)) { + config_decode_canvas(hw, i); + addr = hw->buffer_spec[i].cma_alloc_addr; + } + } + } + if (hw->buffer_spec[i].used == 0 && addr) { hw->buffer_spec[i].used = 1; hw->start_search_pos = i+1; index = i; @@ -2047,8 +2061,15 @@ int get_free_buf_idx(struct vdec_s *vdec) for (i = 0; i < hw->start_search_pos; i++) { if (hw->mmu_enable) addr = hw->buffer_spec[i].alloc_header_addr; - else + else { addr = hw->buffer_spec[i].cma_alloc_addr; + if (hw->is_used_v4l && !addr) { + if (!alloc_one_buf_spec_from_queue(hw, i)) { + config_decode_canvas(hw, i); + addr = hw->buffer_spec[i].cma_alloc_addr; + } + } + } if (hw->buffer_spec[i].used == 0 && addr) { hw->buffer_spec[i].used = 1; hw->start_search_pos = i+1; @@ -2330,10 +2351,9 @@ unsigned char have_free_buf_spec(struct vdec_s *vdec) dealloc_buf_specs(hw, 0); if (max_alloc_buf_count == 0 || allocated_count < max_alloc_buf_count) { - if (hw->is_used_v4l) { - if (alloc_one_buf_spec_from_queue(hw, index) >= 0) - ret = 1; - } else if (alloc_one_buf_spec(hw, index) >= 0) + if (hw->is_used_v4l) + ret = 1; + else if (alloc_one_buf_spec(hw, index) >= 0) ret = 1; } mutex_unlock(&vmh264_mutex); @@ -2382,7 +2402,9 @@ static int check_force_interlace(struct vdec_h264_hw_s *hw, struct FrameStore *frame) { int bForceInterlace = 0; - + /* no di in secure mode, disable force di */ + if (vdec_secure(hw_to_vdec(hw))) + return 0; if (frame->frame) { if (frame->frame->coded_frame && !frame->frame->frame_mbs_only_flag) { @@ -2589,6 +2611,14 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) if (hw->is_used_v4l) { vf->v4l_mem_handle = hw->buffer_spec[buffer_index].cma_alloc_addr; + if (hw->mmu_enable) { + if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) { + dpb_print(DECODE_ID(hw), + PRINT_FLAG_V4L_DETAIL, + "v4l: binding vf fail.\n"); + return -1; + } + } dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, "[%d] %s(), v4l mem handle: 0x%x\n", ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, @@ -2712,8 +2742,11 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) ATRACE_COUNTER(MODULE_NAME, vf->pts); hw->vf_pre_count++; vdec->vdec_fps_detec(vdec->id); - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + if (without_display_mode == 0) { + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } else + vh264_vf_put(vh264_vf_get(vdec), vdec); } if (dpb_is_debug(DECODE_ID(hw), PRINT_FLAG_DUMP_BUFSPEC)) @@ -2727,7 +2760,7 @@ int notify_v4l_eos(struct vdec_s *vdec) struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); struct vframe_s *vf = NULL; - struct vdec_fb *fb = NULL; + struct vdec_v4l2_buffer *fb = NULL; if (hw->is_used_v4l && hw->eos) { if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) { @@ -2737,11 +2770,12 @@ int notify_v4l_eos(struct vdec_s *vdec) return -1; } - if (v4l_get_fb(hw->v4l2_ctx, &fb)) { + if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) { pr_err("[%d] get fb fail.\n", ctx->id); return -1; } + vf->type |= VIDTYPE_V4L_EOS; vf->timestamp = ULONG_MAX; vf->v4l_mem_handle = (unsigned long)fb; vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; @@ -3204,6 +3238,13 @@ int config_decode_buf(struct vdec_h264_hw_s *hw, struct StorablePicture *pic) j = 0; h264_buffer_info_data_write_count = 0; + //disable this read cache when frame width <= 64 (4MBs) + //IQIDCT_CONTROL, bit[16] – dcac_dma_read_cache_disable + if (hw->frame_width <= 64) + SET_VREG_MASK(IQIDCT_CONTROL,(1 << 16)); + else + CLEAR_VREG_MASK(IQIDCT_CONTROL,(1 << 16)); + if (last_pic) dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, "last_pic->data_flag %x slice_type %x last_pic->slice_type %x\n", @@ -4372,7 +4413,7 @@ static int get_max_dec_frame_buf_size(int level_idc, size /= pic_size; size = size + 1; /* need one more buffer */ - if (max_reference_frame_num > size) + if (max_reference_frame_num < size) size = max_reference_frame_num; return size; @@ -4592,9 +4633,7 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, if (hw->is_used_v4l) { if (i != -1) { - ret = alloc_one_buf_spec_from_queue(hw, i); - if (!ret) - config_decode_canvas(hw, i); + pr_info("alloc the buf of v4l when it is about to decoding.\n"); } } else { if ((i != -1) && alloc_one_buf_spec(hw, i) >= 0) @@ -4686,12 +4725,8 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, i = get_buf_spec_by_canvas_pos(hw, j); if (hw->is_used_v4l) { - if (alloc_one_buf_spec_from_queue - (hw, i) < 0) { - if (j++ != buf_cnt) - ret = -1; - break; - } + pr_info("alloc the buf of v4l when it is about to decoding.\n"); + break; } else if (alloc_one_buf_spec(hw, i) < 0) break; @@ -5158,7 +5193,7 @@ static int parse_one_sei_record(struct vdec_h264_hw_s *hw, if (p_sei + payload_size > sei_data_buf_end) { - dpb_print(DECODE_ID(hw), 0, + dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL, "%s: payload_type = %d, payload_size = %d is over\n", __func__, payload_type, payload_size); return read_size; @@ -5166,7 +5201,7 @@ static int parse_one_sei_record(struct vdec_h264_hw_s *hw, bit_offset = 0; if (payload_size <= 0) { - dpb_print(DECODE_ID(hw), 0, + dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL, "%s warning: this is a null sei message for payload_type = %d\n", __func__, payload_type); return read_size; @@ -5377,6 +5412,18 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) unsigned short *p = (unsigned short *)hw->lmem_addr; reset_process_time(hw); + if (hw->is_used_v4l) { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + + if (ctx->param_sets_from_ucode && !ctx->v4l_codec_ready) { + //amvdec_stop(); + hw->dec_result = DEC_RESULT_DONE; + vdec_schedule_work(&hw->work); + return IRQ_HANDLED; + } + } + hw->reg_iqidct_control = READ_VREG(IQIDCT_CONTROL); hw->reg_vcop_ctrl_reg = READ_VREG(VCOP_CTRL_REG); hw->reg_rv_ai_mb_count = READ_VREG(RV_AI_MB_COUNT); @@ -5496,6 +5543,7 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) if (!is_i_slice) { if (hw->has_i_frame == 0) { amvdec_stop(); + vdec->mc_loaded = 0; hw->dec_result = DEC_RESULT_DONE; vdec_schedule_work(&hw->work); dpb_print(DECODE_ID(hw), @@ -5549,10 +5597,19 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) if (p_H264_Dpb->mVideo.dec_picture) { int cfg_ret = 0; + bool field_pic_flag = false; + if (slice_header_process_status == 1) { - if ((p_H264_Dpb->mSPS.profile_idc == BASELINE) || + if (!p_H264_Dpb->mSPS.frame_mbs_only_flag) { + field_pic_flag = + (p_H264_Dpb->mSlice.structure == TOP_FIELD || + p_H264_Dpb->mSlice.structure == BOTTOM_FIELD) ? + true : false; + } + + if (!field_pic_flag && ((p_H264_Dpb->mSPS.profile_idc == BASELINE) || (((unsigned long)(hw->vh264_amstream_dec_info - .param)) & 0x8)) { + .param)) & 0x8))) { p_H264_Dpb->fast_output_enable = H264_OUTPUT_MODE_FAST; } @@ -5609,11 +5666,13 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) if (error_proc_policy & 0x400) { int ret = dpb_check_ref_list_error(p_H264_Dpb); if (ret != 0) { + hw->reflist_error_count ++; dpb_print(DECODE_ID(hw), 0, - "reference list error %d frame count %d to skip %d\n", + "reference list error %d frame count %d to skip %d reflist_error_count %d\n", ret, hw->decode_pic_count+1, - hw->skip_frame_count); + hw->skip_frame_count, + hw->reflist_error_count); if (hw->ref_err_flush_dpb_flag) { flush_dpb(p_H264_Dpb); @@ -5624,19 +5683,20 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) } } - hw->data_flag |= ERROR_FLAG; - p_H264_Dpb->mVideo.dec_picture->data_flag |= ERROR_FLAG; - if ((error_proc_policy & 0x80) + p_H264_Dpb->mVideo.dec_picture->data_flag = NODISP_FLAG; + if (((error_proc_policy & 0x80) && ((hw->dec_flag & - NODISP_FLAG) == 0)) { + NODISP_FLAG) == 0)) ||(hw->reflist_error_count > 50)) { hw->reset_bufmgr_flag = 1; + hw->reflist_error_count =0; amvdec_stop(); - hw->dec_result - = DEC_RESULT_DONE; + vdec->mc_loaded = 0; + hw->dec_result = DEC_RESULT_DONE; vdec_schedule_work(&hw->work); return IRQ_HANDLED; } - } + } else + hw->reflist_error_count = 0; } if ((error_proc_policy & 0x800) && p_H264_Dpb->dpb_error_flag != 0) { @@ -5649,6 +5709,7 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) ((hw->dec_flag & NODISP_FLAG) == 0)) { hw->reset_bufmgr_flag = 1; amvdec_stop(); + vdec->mc_loaded = 0; hw->dec_result = DEC_RESULT_DONE; vdec_schedule_work(&hw->work); return IRQ_HANDLED; @@ -5681,7 +5742,8 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) hw->last_mby_mbx = 0; hw->last_vld_level = 0; start_process_time(hw); - } else if (dec_dpb_status == H264_PIC_DATA_DONE) { + } else if (dec_dpb_status == H264_PIC_DATA_DONE + ||((dec_dpb_status == H264_DATA_REQUEST) && input_frame_based(vdec))) { pic_done_proc: reset_process_time(hw); @@ -5933,6 +5995,7 @@ empty_proc: goto send_again; } amvdec_stop(); + vdec->mc_loaded = 0; dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, "%s %s\n", __func__, (dec_dpb_status == H264_SEARCH_BUFEMPTY) ? @@ -5948,13 +6011,15 @@ empty_proc: hw->search_dataempty_num++; else if (dec_dpb_status == H264_DECODE_TIMEOUT) { hw->decode_timeout_num++; - amvdec_stop(); if (error_proc_policy & 0x4000) { hw->data_flag |= ERROR_FLAG; if ((p_H264_Dpb->last_dpb_status == H264_DECODE_TIMEOUT) || (p_H264_Dpb->last_dpb_status == H264_PIC_DATA_DONE) || ((p_H264_Dpb->last_dpb_status == H264_SLICE_HEAD_DONE) && (p_H264_Dpb->mSlice.slice_type != B_SLICE))) { + dpb_print(DECODE_ID(hw), + PRINT_FLAG_ERROR, "%s last dpb status 0x%x need bugmgr reset \n", + p_H264_Dpb->last_dpb_status, __func__); hw->reset_bufmgr_flag = 1; } } @@ -6172,18 +6237,34 @@ static irqreturn_t vh264_isr(struct vdec_s *vdec, int irq) static void timeout_process(struct vdec_h264_hw_s *hw) { + struct vdec_s *vdec = hw_to_vdec(hw); + struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; + + /* + * In this very timeout point,the vh264_work arrives, + * let it to handle the scenario. + */ + if (work_pending(&hw->work)) + return; + hw->timeout_num++; amvdec_stop(); + vdec->mc_loaded = 0; if (hw->mmu_enable) { hevc_set_frame_done(hw); hevc_sao_wait_done(hw); } + if (!hw->i_only && (error_proc_policy & 0x2)) + flush_dpb(p_H264_Dpb); dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, "%s decoder timeout\n", __func__); release_cur_decoding_buf(hw); hw->dec_result = DEC_RESULT_DONE; hw->data_flag |= ERROR_FLAG; - vdec_schedule_work(&hw->work); + + if (work_pending(&hw->work)) + return; + vdec_schedule_work(&hw->timeout_work); } static void dump_bufspec(struct vdec_h264_hw_s *hw, @@ -6413,7 +6494,7 @@ static void check_timer_func(unsigned long arg) if (hw->decode_timeout_count == 0) { reset_process_time(hw); - vdec_schedule_work(&hw->timeout_work); + timeout_process(hw); } } else start_process_time(hw); @@ -6425,7 +6506,7 @@ static void check_timer_func(unsigned long arg) if (hw->decode_timeout_count == 0) { reset_process_time(hw); - vdec_schedule_work(&hw->timeout_work); + timeout_process(hw); } } } @@ -6544,8 +6625,9 @@ static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw) #endif /* cbcr_merge_swap_en */ - if (hw->is_used_v4l && v4l2_ctx->ada_ctx->vfm_path - != FRAME_BASE_PATH_V4L_VIDEO) + if (hw->is_used_v4l + && (v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21 + || v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21M)) SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16); SET_VREG_MASK(MDEC_PIC_DC_CTRL, 0xbf << 24); @@ -6703,9 +6785,6 @@ static void vh264_local_init(struct vdec_h264_hw_s *hw) hw->first_i_policy = first_i_policy; - hw->is_used_v4l = (((unsigned long) - hw->vh264_amstream_dec_info.param & 0x80) >> 7); - if (hw->is_used_v4l) mem_map_mode = CANVAS_BLKMODE_LINEAR; @@ -6750,14 +6829,6 @@ static void vh264_local_init(struct vdec_h264_hw_s *hw) return; } -static void timeout_process_work(struct work_struct *work) -{ - struct vdec_h264_hw_s *hw = container_of(work, - struct vdec_h264_hw_s, timeout_work); - - timeout_process(hw); -} - static s32 vh264_init(struct vdec_h264_hw_s *hw) { int size = -1; @@ -6785,7 +6856,7 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) vh264_local_init(hw); INIT_WORK(&hw->work, vh264_work); INIT_WORK(&hw->notify_work, vh264_notify_work); - INIT_WORK(&hw->timeout_work, timeout_process_work); + INIT_WORK(&hw->timeout_work, vh264_timeout_work); #ifdef MH264_USERDATA_ENABLE INIT_WORK(&hw->user_data_ready_work, user_data_ready_notify_work); #endif @@ -7713,11 +7784,9 @@ static void vmh264_wakeup_userdata_poll(struct vdec_s *vdec) #endif -static void vh264_work(struct work_struct *work) +static void vh264_work_implement(struct vdec_h264_hw_s *hw, + struct vdec_s *vdec, int from) { - struct vdec_h264_hw_s *hw = container_of(work, - struct vdec_h264_hw_s, work); - struct vdec_s *vdec = hw_to_vdec(hw); /* finished decoding one frame or error, * notify vdec core to switch context */ @@ -7739,12 +7808,32 @@ static void vh264_work(struct work_struct *work) u32 param2 = READ_VREG(AV_SCRATCH_2); u32 param3 = READ_VREG(AV_SCRATCH_6); u32 param4 = READ_VREG(AV_SCRATCH_B); + if (vh264_set_params(hw, param1, param2, param3, param4) < 0) dpb_print(DECODE_ID(hw), 0, "set parameters error\n"); + WRITE_VREG(AV_SCRATCH_0, (hw->max_reference_size<<24) | (hw->dpb.mDPB.size<<16) | (hw->dpb.mDPB.size<<8)); + + if (hw->is_used_v4l) { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + + if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) { + struct aml_vdec_pic_infos info; + + info.visible_width = hw->frame_width; + info.visible_height = hw->frame_height; + info.coded_width = ALIGN(hw->frame_width, 64); + info.coded_height = ALIGN(hw->frame_height, 64); + info.dpb_size = hw->dpb.mDPB.size; + hw->v4l_params_parsed = true; + vdec_v4l_set_pic_infos(ctx, &info); + } + } + start_process_time(hw); return; } else @@ -7951,6 +8040,17 @@ result_done: vdec_set_next_sched(vdec, vdec); #endif + if (from == 1) { + /* This is a timeout work */ + if (work_pending(&hw->work)) { + /* + * The vh264_work arrives at the last second, + * give it a chance to handle the scenario. + */ + return; + } + } + /* mark itself has all HW resource released and input released */ if (vdec->parallel_dec == 1) { if (hw->mmu_enable == 0) @@ -7961,10 +8061,43 @@ result_done: vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); wake_up_interruptible(&hw->wait_q); + + if (hw->is_used_v4l) { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + + if (ctx->param_sets_from_ucode && + !hw->v4l_params_parsed) + vdec_v4l_write_frame_sync(ctx); + } + if (hw->vdec_cb) hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg); } + +static void vh264_work(struct work_struct *work) +{ + struct vdec_h264_hw_s *hw = container_of(work, + struct vdec_h264_hw_s, work); + struct vdec_s *vdec = hw_to_vdec(hw); + + vh264_work_implement(hw, vdec, 0); +} + + +static void vh264_timeout_work(struct work_struct *work) +{ + struct vdec_h264_hw_s *hw = container_of(work, + struct vdec_h264_hw_s, timeout_work); + struct vdec_s *vdec = hw_to_vdec(hw); + + if (work_pending(&hw->work)) + return; + + vh264_work_implement(hw, vdec, 1); +} + static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) { bool ret = 0; @@ -8057,6 +8190,16 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) get_used_buf_count(hw) >= run_ready_max_buf_num) ret = 0; + + if (hw->is_used_v4l) { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + + if (ctx->param_sets_from_ucode && + !ctx->v4l_codec_ready && + hw->v4l_params_parsed) + ret = 0; /*the params has parsed.*/ + } } #endif if (ret) @@ -8345,6 +8488,7 @@ static void reset(struct vdec_s *vdec) hw->dec_result = DEC_RESULT_NONE; reset_process_time(hw); h264_reset_bufmgr(vdec); + dpb_print(DECODE_ID(hw), 0, "%s\n", __func__); } @@ -8392,6 +8536,12 @@ static void h264_reconfig(struct vdec_h264_hw_s *hw) hw->has_i_frame = 0; hw->config_bufmgr_done = 0; + if (hw->is_used_v4l) { + mutex_lock(&vmh264_mutex); + dealloc_buf_specs(hw, 1); + mutex_unlock(&vmh264_mutex); + } + if (dpb_is_debug(DECODE_ID(hw), PRINT_FLAG_DUMP_BUFSPEC)) dump_bufspec(hw, "after h264_reconfig"); @@ -8502,28 +8652,28 @@ static void h264_reset_bufmgr(struct vdec_s *vdec) vh264_local_init(hw); /*hw->decode_pic_count = 0; hw->seq_info2 = 0;*/ - if (!hw->is_used_v4l) { - if (vh264_set_params(hw, - hw->cfg_param1, - hw->cfg_param2, - hw->cfg_param3, - hw->cfg_param4) < 0) - hw->stat |= DECODER_FATAL_ERROR_SIZE_OVERFLOW; - } else { - /* V4L2 decoder reset keeps decoder in same status as - * after probe when there is no SPS/PPS header processed - * and no buffers allocated. - */ - hw->seq_info = 0; - hw->seq_info2 = 0; + + if (hw->is_used_v4l) { + mutex_lock(&vmh264_mutex); + /* detach relationship with v4l buffs.*/ + dealloc_buf_specs(hw, 1); + mutex_unlock(&vmh264_mutex); } + + if (vh264_set_params(hw, + hw->cfg_param1, + hw->cfg_param2, + hw->cfg_param3, + hw->cfg_param4) < 0) + hw->stat |= DECODER_FATAL_ERROR_SIZE_OVERFLOW; + /*drop 3 frames after reset bufmgr if bit0 is set 1 */ if (first_i_policy & 0x01) hw->first_i_policy = (3 << 8) | first_i_policy; + hw->init_flag = 1; hw->reset_bufmgr_count++; #endif - } int ammvdec_h264_mmu_init(struct vdec_h264_hw_s *hw) @@ -8600,7 +8750,10 @@ static int ammvdec_h264_probe(struct platform_device *pdev) /* the ctx from v4l2 driver. */ hw->v4l2_ctx = pdata->private; - hw->canvas_mode = pdata->canvas_mode; + if ((h264_debug_flag & IGNORE_PARAM_FROM_CONFIG) == 0) + hw->canvas_mode = pdata->canvas_mode; + else + hw->canvas_mode = mem_map_mode; platform_set_drvdata(pdev, pdata); @@ -8608,6 +8761,20 @@ static int ammvdec_h264_probe(struct platform_device *pdev) hw->first_head_check_flag = 0; hw->new_iframe_flag = 0; hw->ref_err_flush_dpb_flag = 0; + + if (pdata->sys_info) + hw->vh264_amstream_dec_info = *pdata->sys_info; + + hw->is_used_v4l = (((unsigned long) + hw->vh264_amstream_dec_info.param & 0x80) >> 7); + if (hw->is_used_v4l) { + hw->mmu_enable = (((unsigned long) + hw->vh264_amstream_dec_info.param & 0x100) >> 8); + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "%s v4: enable mmu %d.\n", + __func__, hw->mmu_enable); + } + if (force_enable_mmu && pdata->sys_info && (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX) && (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_GXLX) && @@ -8769,8 +8936,6 @@ static int ammvdec_h264_probe(struct platform_device *pdev) } /**/ - if (pdata->sys_info) - hw->vh264_amstream_dec_info = *pdata->sys_info; #if 0 if (NULL == hw->sei_data_buffer) { hw->sei_data_buffer = @@ -9181,6 +9346,10 @@ MODULE_PARM_DESC(double_write_mode, "\n double_write_mode\n"); module_param(mem_map_mode, uint, 0664); MODULE_PARM_DESC(mem_map_mode, "\n mem_map_mode\n"); +module_param(without_display_mode, uint, 0664); +MODULE_PARM_DESC(without_display_mode, "\n without_display_mode\n"); + + module_init(ammvdec_h264_driver_init_module); module_exit(ammvdec_h264_driver_remove_module); diff --git a/drivers/frame_provider/decoder/h265/vh265.c b/drivers/frame_provider/decoder/h265/vh265.c index 02944e6..37e6969 100644 --- a/drivers/frame_provider/decoder/h265/vh265.c +++ b/drivers/frame_provider/decoder/h265/vh265.c @@ -46,7 +46,7 @@ #include "../utils/config_parser.h" #include "../utils/firmware.h" #include "../../../common/chips/decoder_cpu_ver_info.h" -#include "../../../amvdec_ports/vdec_drv_base.h" +#include "../utils/vdec_v4l2_buffer_ops.h" #define CONSTRAIN_MAX_BUF_NUM @@ -535,6 +535,8 @@ static DEFINE_MUTEX(vh265_log_mutex); static struct vdec_info *gvs; +static u32 without_display_mode; + /************************************************** * *h265 buffer management include @@ -1302,6 +1304,7 @@ struct BUF_s { unsigned long start_adr; unsigned int size; int used_flag; + unsigned int y_size; ulong v4l_ref_buf_addr; } /*BUF_t */; @@ -1324,6 +1327,8 @@ struct PIC_s { unsigned char recon_mark; unsigned char output_ready; unsigned char error_mark; + //dis_mark = 0:discard mark,dis_mark = 1:no discard mark + unsigned char dis_mark; /**/ int slice_idx; int m_aiRefPOCList0[MAX_SLICE_NUM][16]; int m_aiRefPOCList1[MAX_SLICE_NUM][16]; @@ -1367,6 +1372,7 @@ struct PIC_s { u32 pts; u64 pts64; + u64 timestamp; u32 aspect_ratio_idc; u32 sar_width; @@ -1422,8 +1428,10 @@ struct tile_s { #define DEC_RESULT_GET_DATA_RETRY 8 #define DEC_RESULT_EOS 9 #define DEC_RESULT_FORCE_EXIT 10 +#define DEC_RESULT_FREE_CANVAS 11 static void vh265_work(struct work_struct *work); +static void vh265_timeout_work(struct work_struct *work); static void vh265_notify_work(struct work_struct *work); #endif @@ -1441,6 +1449,7 @@ struct hevc_state_s { struct vframe_chunk_s *chunk; int dec_result; struct work_struct work; + struct work_struct timeout_work; struct work_struct notify_work; struct work_struct set_clk_work; /* timeout handle */ @@ -1717,20 +1726,11 @@ struct hevc_state_s { struct vframe_qos_s vframe_qos; bool is_used_v4l; void *v4l2_ctx; + bool v4l_params_parsed; } /*hevc_stru_t */; -static int v4l_get_fb(struct aml_vcodec_ctx *ctx, struct vdec_fb **out) -{ - int ret = 0; - - ret = ctx->dec_if->get_param(ctx->drv_handle, - GET_PARAM_FREE_FRAME_BUFFER, out); - - return ret; -} - #ifdef AGAIN_HAS_THRESHOLD -u32 again_threshold = 0x40; +u32 again_threshold; #endif #ifdef SEND_LMEM_WITH_RPM #define get_lmem_params(hevc, ladr) \ @@ -2083,7 +2083,7 @@ static void restore_decode_state(struct hevc_state_s *hevc) static void hevc_init_stru(struct hevc_state_s *hevc, struct BuffInfo_s *buf_spec_i) { - int i; + //int i; INIT_LIST_HEAD(&hevc->log_list); hevc->work_space_buf = buf_spec_i; hevc->prefix_aux_size = 0; @@ -2140,8 +2140,11 @@ static void hevc_init_stru(struct hevc_state_s *hevc, else hevc->ignore_bufmgr_error = 0x0; - for (i = 0; i < MAX_REF_PIC_NUM; i++) - hevc->m_PIC[i] = NULL; + hevc->dec_result = DEC_RESULT_FREE_CANVAS; + vdec_schedule_work(&hevc->work); + /*for (i = 0; i < MAX_REF_PIC_NUM; i++) + hevc->m_PIC[i] = NULL;*/ + hevc->pic_num = 0; hevc->lcu_x_num_pre = 0; hevc->lcu_y_num_pre = 0; @@ -2755,6 +2758,31 @@ static int alloc_mv_buf(struct hevc_state_s *hevc, int i) (void *)hevc->m_mv_BUF[i].start_adr, hevc->m_mv_BUF[i].size); } + if (!vdec_secure(hw_to_vdec(hevc)) && (hevc->m_mv_BUF[i].start_adr)) { + void *mem_start_virt; + mem_start_virt = + codec_mm_phys_to_virt(hevc->m_mv_BUF[i].start_adr); + if (mem_start_virt) { + memset(mem_start_virt, 0, hevc->m_mv_BUF[i].size); + codec_mm_dma_flush(mem_start_virt, + hevc->m_mv_BUF[i].size, DMA_TO_DEVICE); + } else { + mem_start_virt = codec_mm_vmap( + hevc->m_mv_BUF[i].start_adr, + hevc->m_mv_BUF[i].size); + if (mem_start_virt) { + memset(mem_start_virt, 0, hevc->m_mv_BUF[i].size); + codec_mm_dma_flush(mem_start_virt, + hevc->m_mv_BUF[i].size, + DMA_TO_DEVICE); + codec_mm_unmap_phyaddr(mem_start_virt); + } else { + /*not virt for tvp playing, + may need clear on ucode.*/ + pr_err("ref %s mem_start_virt failed\n", __func__); + } + } + } } /*put_cma_alloc_ref();*/ /*DEBUG_TMP*/ return ret; @@ -2940,7 +2968,9 @@ static int alloc_buf(struct hevc_state_s *hevc) int i; int ret = -1; int buf_size = cal_current_buf_size(hevc, NULL); - struct vdec_fb *fb = NULL; + + if (hevc->is_used_v4l) + return 0; if (hevc->fatal_error & DECODER_FATAL_ERROR_NO_MEM) return ret; @@ -2954,38 +2984,19 @@ static int alloc_buf(struct hevc_state_s *hevc) /*get_cma_alloc_ref();*/ /*DEBUG_TMP*/ /*alloc compress header first*/ - if (hevc->is_used_v4l) { - ret = v4l_get_fb(hevc->v4l2_ctx, &fb); - if (ret) { + ret = decoder_bmmu_box_alloc_buf_phy + (hevc->bmmu_box, + VF_BUFFER_IDX(i), buf_size, + DRIVER_NAME, + &hevc->m_BUF[i].start_adr); + if (ret < 0) { + hevc->m_BUF[i].start_adr = 0; + if (i <= 8) { + hevc->fatal_error |= + DECODER_FATAL_ERROR_NO_MEM; hevc_print(hevc, PRINT_FLAG_ERROR, - "[%d] get fb fail.\n", - ((struct aml_vcodec_ctx *) - (hevc->v4l2_ctx))->id); - return ret; - } - - hevc->m_BUF[i].v4l_ref_buf_addr = (ulong)fb; - hevc->m_BUF[i].start_adr = - virt_to_phys(fb->base_y.va); - hevc_print(hevc, PRINT_FLAG_V4L_DETAIL, - "[%d] %s(), v4l ref buf addr: 0x%x\n", - ((struct aml_vcodec_ctx *) - (hevc->v4l2_ctx))->id, __func__, fb); - } else { - ret = decoder_bmmu_box_alloc_buf_phy - (hevc->bmmu_box, - VF_BUFFER_IDX(i), buf_size, - DRIVER_NAME, - &hevc->m_BUF[i].start_adr); - if (ret < 0) { - hevc->m_BUF[i].start_adr = 0; - if (i <= 8) { - hevc->fatal_error |= - DECODER_FATAL_ERROR_NO_MEM; - hevc_print(hevc, PRINT_FLAG_ERROR, - "%s[%d], size: %d, no mem fatal err\n", - __func__, i, buf_size); - } + "%s[%d], size: %d, no mem fatal err\n", + __func__, i, buf_size); } } @@ -2993,6 +3004,7 @@ static int alloc_buf(struct hevc_state_s *hevc) hevc->m_BUF[i].size = buf_size; hevc->m_BUF[i].used_flag = 0; ret = 0; + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) { hevc_print(hevc, 0, "Buffer %d: start_adr %p size %x\n", @@ -3000,6 +3012,32 @@ static int alloc_buf(struct hevc_state_s *hevc) (void *)hevc->m_BUF[i].start_adr, hevc->m_BUF[i].size); } + /*flush the buffer make sure no cache dirty*/ + if (!vdec_secure(hw_to_vdec(hevc)) && (hevc->m_BUF[i].start_adr)) { + void *mem_start_virt; + mem_start_virt = + codec_mm_phys_to_virt(hevc->m_BUF[i].start_adr); + if (mem_start_virt) { + memset(mem_start_virt, 0, hevc->m_BUF[i].size); + codec_mm_dma_flush(mem_start_virt, + hevc->m_BUF[i].size, DMA_TO_DEVICE); + } else { + mem_start_virt = codec_mm_vmap( + hevc->m_BUF[i].start_adr, + hevc->m_BUF[i].size); + if (mem_start_virt) { + memset(mem_start_virt, 0, hevc->m_BUF[i].size); + codec_mm_dma_flush(mem_start_virt, + hevc->m_BUF[i].size, + DMA_TO_DEVICE); + codec_mm_unmap_phyaddr(mem_start_virt); + } else { + /*not virt for tvp playing, + may need clear on ucode.*/ + pr_err("ref %s mem_start_virt failed\n", __func__); + } + } + } } /*put_cma_alloc_ref();*/ /*DEBUG_TMP*/ } else @@ -3096,7 +3134,6 @@ static int get_work_pic_num(struct hevc_state_s *hevc) sps_pic_buf_diff = hevc->param.p.sps_max_dec_pic_buffering_minus1_0 - hevc->sps_num_reorder_pics_0; - #ifdef MULTI_INSTANCE_SUPPORT /* need one more for multi instance, as @@ -3152,8 +3189,45 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic) struct buf_stru_s buf_stru; int buf_size = cal_current_buf_size(hevc, &buf_stru); int dw_mode = get_double_write_mode(hevc); + struct vdec_v4l2_buffer *fb = NULL; + + if (hevc->is_used_v4l) + buf_size = 0; for (i = 0; i < BUF_POOL_SIZE; i++) { + if (hevc->is_used_v4l && !hevc->m_BUF[i].start_adr) { + ret = vdec_v4l_get_buffer(hevc->v4l2_ctx, &fb); + if (ret) { + hevc_print(hevc, PRINT_FLAG_V4L_DETAIL, + "[%d] get fb fail.\n", + ((struct aml_vcodec_ctx *) + (hevc->v4l2_ctx))->id); + return ret; + } + + hevc->m_BUF[i].used_flag = 0; + hevc->m_BUF[i].v4l_ref_buf_addr = (ulong)fb; + if (fb->num_planes == 1) { + hevc->m_BUF[i].start_adr = fb->m.mem[0].addr; + hevc->m_BUF[i].size = fb->m.mem[0].size; + hevc->m_BUF[i].y_size = fb->m.mem[0].offset; + fb->m.mem[0].bytes_used = fb->m.mem[0].size; + } else if (fb->num_planes == 2) { + hevc->m_BUF[i].start_adr = fb->m.mem[0].addr; + hevc->m_BUF[i].size = fb->m.mem[0].size + fb->m.mem[1].size; + hevc->m_BUF[i].y_size = fb->m.mem[0].size; + fb->m.mem[0].bytes_used = fb->m.mem[0].size; + fb->m.mem[1].bytes_used = fb->m.mem[1].size; + } + + pic->BUF_index = i; + + hevc_print(hevc, PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), v4l ref buf addr: 0x%x\n", + ((struct aml_vcodec_ctx *) + (hevc->v4l2_ctx))->id, __func__, fb); + } + if (hevc->m_BUF[i].start_adr != 0 && hevc->m_BUF[i].used_flag == 0 && buf_size <= hevc->m_BUF[i].size) { @@ -3161,6 +3235,7 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic) break; } } + if (i >= BUF_POOL_SIZE) return -1; @@ -3176,7 +3251,9 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic) } else y_adr = hevc->m_BUF[i].start_adr; - y_adr = ((y_adr + 0xffff) >> 16) << 16; /*64k alignment*/ + if (!hevc->is_used_v4l) + y_adr = ((y_adr + 0xffff) >> 16) << 16; /*64k alignment*/ + pic->POC = INVALID_POC; /*ensure get_pic_by_POC() not get the buffer not decoded*/ @@ -3191,9 +3268,14 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic) pic->mc_canvas_y = pic->index; pic->mc_canvas_u_v = pic->index; if (dw_mode & 0x10) { - pic->mc_y_adr = y_adr; - pic->mc_u_v_adr = y_adr + - ((buf_stru.mc_buffer_size_u_v_h << 16) << 1); + if (hevc->is_used_v4l) { + pic->mc_y_adr = y_adr; + pic->mc_u_v_adr = y_adr + hevc->m_BUF[i].y_size; + } else { + pic->mc_y_adr = y_adr; + pic->mc_u_v_adr = y_adr + + ((buf_stru.mc_buffer_size_u_v_h << 16) << 1); + } pic->mc_canvas_y = (pic->index << 1); pic->mc_canvas_u_v = (pic->index << 1) + 1; @@ -3262,19 +3344,24 @@ static void init_pic_list(struct hevc_state_s *hevc) pic->y_canvas_index = -1; pic->uv_canvas_index = -1; } - if (config_pic(hevc, pic) < 0) { - if (get_dbg_flag(hevc)) - hevc_print(hevc, 0, - "Config_pic %d fail\n", pic->index); - pic->index = -1; - i++; - break; - } + pic->width = hevc->pic_w; pic->height = hevc->pic_h; pic->double_write_mode = dw_mode; - if (pic->double_write_mode) - set_canvas(hevc, pic); + + if (!hevc->is_used_v4l) { + if (config_pic(hevc, pic) < 0) { + if (get_dbg_flag(hevc)) + hevc_print(hevc, 0, + "Config_pic %d fail\n", pic->index); + pic->index = -1; + i++; + break; + } + + if (pic->double_write_mode) + set_canvas(hevc, pic); + } } for (; i < MAX_REF_PIC_NUM; i++) { @@ -4901,6 +4988,7 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params) hevc->lcu_total * hevc->lcu_size * hevc->lcu_size / 2; int mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16; struct PIC_s *cur_pic = hevc->cur_pic; + struct aml_vcodec_ctx * v4l2_ctx = hevc->v4l2_ctx; data32 = READ_VREG(HEVC_SAO_CTRL0); data32 &= (~0xf); @@ -5088,6 +5176,27 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params) "[DBLK DEBUG] HEVC1 CFGB : 0x%x\n", data); } + /* swap uv */ + if (hevc->is_used_v4l) { + if ((v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21) || + (v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21M)) + data32 &= ~(1 << 8); /* NV21 */ + else + data32 |= (1 << 8); /* NV12 */ + } + + /* + * [31:24] ar_fifo1_axi_thred + * [23:16] ar_fifo0_axi_thred + * [15:14] axi_linealign, 0-16bytes, 1-32bytes, 2-64bytes + * [13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32 + * [11:08] axi_lendian_C + * [07:04] axi_lendian_Y + * [3] reserved + * [2] clk_forceon + * [1] dw_disable:disable double write output + * [0] cm_disable:disable compress output + */ WRITE_VREG(HEVC_SAO_CTRL1, data32); if (get_double_write_mode(hevc) & 0x10) { /* [23:22] dw_v1_ctrl @@ -5109,6 +5218,25 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params) data32 &= (~0xF); data32 |= 0xf; /* valid only when double write only */ /*data32 |= 0x8;*/ /* Big-Endian per 64-bit */ + + /* swap uv */ + if (hevc->is_used_v4l) { + if ((v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21) || + (v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21M)) + data32 |= (1 << 12); /* NV21 */ + else + data32 &= ~(1 << 12); /* NV12 */ + } + + /* + * [3:0] little_endian + * [5:4] address_format 00:linear 01:32x32 10:64x32 + * [7:6] reserved + * [9:8] Linear_LineAlignment 00:16byte 01:32byte 10:64byte + * [11:10] reserved + * [12] CbCr_byte_swap + * [31:13] reserved + */ WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); #endif data32 = 0; @@ -5359,6 +5487,7 @@ static struct PIC_s *get_new_pic(struct hevc_state_s *hevc, new_pic->output_mark = 0; new_pic->recon_mark = 0; new_pic->error_mark = 0; + new_pic->dis_mark = 0; /* new_pic->output_ready = 0; */ new_pic->num_reorder_pic = rpm_param->p.sps_num_reorder_pics_0; new_pic->losless_comp_body_size = hevc->losless_comp_body_size; @@ -5731,6 +5860,7 @@ static inline void hevc_pre_pic(struct hevc_state_s *hevc, pic->output_mark = 1; pic->recon_mark = 1; + pic->dis_mark = 1; } do { pic_display = output_pic(hevc, 0); @@ -5877,9 +6007,9 @@ static void check_pic_decoded_error(struct hevc_state_s *hevc, current_lcu_idx, hevc->lcu_x_num*hevc->lcu_y_num); if (((hevc->i_only & 0x4) == 0) && hevc->cur_pic->POC && ( hevc->cur_pic->slice_type == 0) - && ((hevc->cur_pic->POC + hevc->sps_num_reorder_pics_0) < hevc->iPrevPOC)) { + && ((hevc->cur_pic->POC + MAX_BUF_NUM) < hevc->iPrevPOC)) { hevc_print(hevc, 0, - "Flush .. num_reorder_pic %d pic->POC %d hevc->iPrevPOC %d\n", + "Flush.. num_reorder_pic %d pic->POC %d hevc->iPrevPOC %d\n", hevc->sps_num_reorder_pics_0,hevc->cur_pic->POC ,hevc->iPrevPOC); flush_output(hevc, get_pic_by_POC(hevc, hevc->cur_pic->POC )); } @@ -6886,7 +7016,7 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, if (is_log_enable(hevc)) add_log(hevc, "WRONG,fail to get the pic Col_POC"); - } else if (hevc->col_pic->error_mark) { + } else if (hevc->col_pic->error_mark || hevc->col_pic->dis_mark == 0) { hevc->cur_pic->error_mark = 1; if (get_dbg_flag(hevc)) { hevc_print(hevc, 0, @@ -7951,6 +8081,7 @@ static int process_pending_vframe(struct hevc_state_s *hevc, "top" : "bot"); if (kfifo_len(&hevc->pending_q) > 1) { + unsigned long flags; /* do not pending more than 1 frame */ if (kfifo_get(&hevc->pending_q, &vf) == 0) { hevc_print(hevc, 0, @@ -7961,8 +8092,22 @@ static int process_pending_vframe(struct hevc_state_s *hevc, hevc_print(hevc, 0, "%s warning(1), vf=>display_q: (index 0x%x)\n", __func__, vf->index); + if ((hevc->double_write_mode == 3) && + (!(IS_8K_SIZE(vf->width, vf->height)))) { + vf->type |= VIDTYPE_COMPRESS; + if (hevc->mmu_enable) + vf->type |= VIDTYPE_SCATTER; + } hevc->vf_pre_count++; - kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); + kfifo_put(&hevc->newframe_q, (const struct vframe_s *)vf); + spin_lock_irqsave(&lock, flags); + vf->index &= 0xff; + hevc->m_PIC[vf->index]->output_ready = 0; + if (hevc->wait_buf != 0) + WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, + 0x1); + spin_unlock_irqrestore(&lock, flags); + ATRACE_COUNTER(MODULE_NAME, vf->pts); } @@ -7982,6 +8127,12 @@ static int process_pending_vframe(struct hevc_state_s *hevc, "%s warning(2), vf=>display_q: (index 0x%x)\n", __func__, vf->index); if (vf) { + if ((hevc->double_write_mode == 3) && + (!(IS_8K_SIZE(vf->width, vf->height)))) { + vf->type |= VIDTYPE_COMPRESS; + if (hevc->mmu_enable) + vf->type |= VIDTYPE_SCATTER; + } hevc->vf_pre_count++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); @@ -7995,8 +8146,12 @@ static int process_pending_vframe(struct hevc_state_s *hevc, return -1; } if (vf) { - vf->type = VIDTYPE_PROGRESSIVE - | VIDTYPE_VIU_NV21; + if ((hevc->double_write_mode == 3) && + (!(IS_8K_SIZE(vf->width, vf->height)))) { + vf->type |= VIDTYPE_COMPRESS; + if (hevc->mmu_enable) + vf->type |= VIDTYPE_SCATTER; + } vf->index &= 0xff; vf->index |= (pair_pic->index << 8); vf->canvas1Addr = spec2canvas(pair_pic); @@ -8018,8 +8173,12 @@ static int process_pending_vframe(struct hevc_state_s *hevc, return -1; } if (vf) { - vf->type = VIDTYPE_PROGRESSIVE - | VIDTYPE_VIU_NV21; + if ((hevc->double_write_mode == 3) && + (!(IS_8K_SIZE(vf->width, vf->height)))) { + vf->type |= VIDTYPE_COMPRESS; + if (hevc->mmu_enable) + vf->type |= VIDTYPE_SCATTER; + } vf->index &= 0xff00; vf->index |= pair_pic->index; vf->canvas0Addr = spec2canvas(pair_pic); @@ -8150,6 +8309,13 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) if (hevc->is_used_v4l) { vf->v4l_mem_handle = hevc->m_BUF[pic->BUF_index].v4l_ref_buf_addr; + if (hevc->mmu_enable) { + if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) { + hevc_print(hevc, PRINT_FLAG_V4L_DETAIL, + "v4l: binding vf fail.\n"); + return -1; + } + } hevc_print(hevc, PRINT_FLAG_V4L_DETAIL, "[%d] %s(), v4l mem handle: 0x%lx\n", ((struct aml_vcodec_ctx *)(hevc->v4l2_ctx))->id, @@ -8160,6 +8326,7 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) if (vdec_frame_based(hw_to_vdec(hevc))) { vf->pts = pic->pts; vf->pts_us64 = pic->pts64; + vf->timestamp = pic->timestamp; } /* if (pts_lookup_offset(PTS_TYPE_VIDEO, stream_offset, &vf->pts, 0) != 0) { */ @@ -8555,6 +8722,9 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) hevc->pre_top_pic, 1); } + if (hevc->vf_pre_count == 0) + hevc->vf_pre_count++; + /**/ if (pic->pic_struct == 9) hevc->pre_top_pic = pic; @@ -8586,6 +8756,8 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) decoder_do_frame_check(hw_to_vdec(hevc), vf); kfifo_put(&hevc->pending_q, (const struct vframe_s *)vf); + if (hevc->vf_pre_count == 0) + hevc->vf_pre_count++; /**/ if (pic->pic_struct == 11) @@ -8653,8 +8825,12 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) vdec_count_info(gvs, 0, stream_offset); #endif hw_to_vdec(hevc)->vdec_fps_detec(hw_to_vdec(hevc)->id); - vf_notify_receiver(hevc->provider_name, + if (without_display_mode == 0) { + vf_notify_receiver(hevc->provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } + else + vh265_vf_put(vh265_vf_get(vdec), vdec); } return 0; @@ -8665,7 +8841,7 @@ static int notify_v4l_eos(struct vdec_s *vdec) struct hevc_state_s *hw = (struct hevc_state_s *)vdec->private; struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); struct vframe_s *vf = NULL; - struct vdec_fb *fb = NULL; + struct vdec_v4l2_buffer *fb = NULL; if (hw->is_used_v4l && hw->eos) { if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) { @@ -8675,11 +8851,12 @@ static int notify_v4l_eos(struct vdec_s *vdec) return -1; } - if (v4l_get_fb(hw->v4l2_ctx, &fb)) { + if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) { pr_err("[%d] get fb fail.\n", ctx->id); return -1; } + vf->type |= VIDTYPE_V4L_EOS; vf->timestamp = ULONG_MAX; vf->v4l_mem_handle = (unsigned long)fb; vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; @@ -9152,6 +9329,7 @@ static irqreturn_t vh265_isr_thread_fn(int irq, void *data) && (hevc->chunk)) { hevc->cur_pic->pts = hevc->chunk->pts; hevc->cur_pic->pts64 = hevc->chunk->pts64; + hevc->cur_pic->timestamp = hevc->chunk->timestamp; } mutex_unlock(&hevc->chunks_mutex); @@ -9300,9 +9478,13 @@ pic_done: pic->output_mark = 1; pic->recon_mark = 1; } + check_pic_decoded_error(hevc, + READ_VREG(HEVC_PARSER_LCU_START) & 0xffffff); + if (hevc->cur_pic != NULL && + (READ_VREG(HEVC_PARSER_LCU_START) & 0xffffff) == 0) + hevc->cur_pic->error_mark = 1; force_output: pic_display = output_pic(hevc, 1); - if (pic_display) { if ((pic_display->error_mark && ((hevc->ignore_bufmgr_error & @@ -9689,6 +9871,27 @@ force_output: hevc->param.p.vui_time_scale_hi, hevc->param.p.vui_time_scale_lo); } + + if (hevc->is_used_v4l) { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hevc->v4l2_ctx); + + if (ctx->param_sets_from_ucode && !hevc->v4l_params_parsed) { + struct aml_vdec_pic_infos info; + + hevc->frame_width = hevc->param.p.pic_width_in_luma_samples; + hevc->frame_height = hevc->param.p.pic_height_in_luma_samples; + info.visible_width = hevc->frame_width; + info.visible_height = hevc->frame_height; + info.coded_width = ALIGN(hevc->frame_width, 32); + info.coded_height = ALIGN(hevc->frame_height, 32); + info.dpb_size = get_work_pic_num(hevc); + hevc->v4l_params_parsed = true; + /*notice the v4l2 codec.*/ + vdec_v4l_set_pic_infos(ctx, &info); + } + } + if ( #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION vdec->master == NULL && @@ -10597,7 +10800,7 @@ static int vh265_local_init(struct hevc_state_s *hevc) INIT_KFIFO(hevc->display_q); INIT_KFIFO(hevc->newframe_q); - + INIT_KFIFO(hevc->pending_q); for (i = 0; i < VF_POOL_SIZE; i++) { const struct vframe_s *vf = &hevc->vfpool[i]; @@ -10627,6 +10830,15 @@ static s32 vh265_init(struct hevc_state_s *hevc) init_timer(&hevc->timer); hevc->stat |= STAT_TIMER_INIT; + + if (hevc->m_ins_flag) { +#ifdef USE_UNINIT_SEMA + sema_init(&hevc->h265_uninit_done_sema, 0); +#endif + INIT_WORK(&hevc->work, vh265_work); + INIT_WORK(&hevc->timeout_work, vh265_timeout_work); + } + if (vh265_local_init(hevc) < 0) return -EBUSY; @@ -10699,16 +10911,6 @@ static s32 vh265_init(struct hevc_state_s *hevc) hevc->timer.function = vh265_check_timer_func; hevc->timer.expires = jiffies + PUT_INTERVAL; -#ifdef USE_UNINIT_SEMA - sema_init(&hevc->h265_uninit_done_sema, 0); -#endif - - /*add_timer(&hevc->timer); - *hevc->stat |= STAT_TIMER_ARM; - */ - - INIT_WORK(&hevc->work, vh265_work); - hevc->fw = fw; return 0; @@ -10977,6 +11179,13 @@ static void restart_process_time(struct hevc_state_s *hevc) static void timeout_process(struct hevc_state_s *hevc) { + /* + * In this very timeout point,the vh265_work arrives, + * let it to handle the scenario. + */ + if (work_pending(&hevc->work)) + return; + hevc->timeout_num++; amhevc_stop(); read_decode_info(hevc); @@ -10989,7 +11198,10 @@ static void timeout_process(struct hevc_state_s *hevc) hevc->decoding_pic = NULL; hevc->dec_result = DEC_RESULT_DONE; reset_process_time(hevc); - vdec_schedule_work(&hevc->work); + + if (work_pending(&hevc->work)) + return; + vdec_schedule_work(&hevc->timeout_work); } #ifdef CONSTRAIN_MAX_BUF_NUM @@ -11057,11 +11269,15 @@ static unsigned char is_new_pic_available(struct hevc_state_s *hevc) new_pic = pic; } } - +/*If the number of reference frames of DPB >= (the DPB buffer size - the number of reorders -3)*/ +/*and the back-end state is RECEIVER INACTIVE, it will cause the decoder have no buffer to*/ +/*decode. all reference frames are removed and setting error flag.*/ +/*3 represents 2 filed are needed for back-end display and 1 filed is needed for decoding*/ +/*when file is interlace.*/ if ((new_pic == NULL) && (ref_pic >= get_work_pic_num(hevc) - - hevc->sps_num_reorder_pics_0 - 1)) { + hevc->sps_num_reorder_pics_0 - 3)) { enum receviver_start_e state = RECEIVER_INACTIVE; if (vf_get_receiver(vdec->vf_provider_name)) { state = @@ -11080,18 +11296,10 @@ static unsigned char is_new_pic_available(struct hevc_state_s *hevc) if ((pic->referenced == 1) && (pic->error_mark == 1)) { - if (new_pic) { - if (pic->POC < new_pic->POC) - new_pic = pic; - } else - new_pic = pic; + pic->referenced = 0; + put_mv_buf(hevc, pic); } - } - if (new_pic != NULL) { - new_pic->referenced = 0; - put_mv_buf(hevc, pic); - if (pic_list_debug & 0x2) - pr_err("err ref poc :%d\n", new_pic->POC); + pic->error_mark = 1; } } } @@ -11129,7 +11337,9 @@ static int vmh265_stop(struct hevc_state_s *hevc) if (use_cma) { hevc->uninit_list = 1; reset_process_time(hevc); + hevc->dec_result = DEC_RESULT_FREE_CANVAS; vdec_schedule_work(&hevc->work); + flush_work(&hevc->work); #ifdef USE_UNINIT_SEMA if (hevc->init_flag) { down(&hevc->h265_uninit_done_sema); @@ -11144,6 +11354,7 @@ static int vmh265_stop(struct hevc_state_s *hevc) cancel_work_sync(&hevc->notify_work); cancel_work_sync(&hevc->set_clk_work); cancel_work_sync(&hevc->work); + cancel_work_sync(&hevc->timeout_work); uninit_mmu_buffers(hevc); vfree(hevc->fw); @@ -11209,13 +11420,10 @@ static void vh265_notify_work(struct work_struct *work) return; } -static void vh265_work(struct work_struct *work) +static void vh265_work_implement(struct hevc_state_s *hevc, + struct vdec_s *vdec,int from) { - struct hevc_state_s *hevc = container_of(work, - struct hevc_state_s, work); - struct vdec_s *vdec = hw_to_vdec(hevc); - - if (hevc->uninit_list) { + if (hevc->dec_result == DEC_RESULT_FREE_CANVAS) { /*USE_BUF_BLOCK*/ uninit_pic_list(hevc); hevc_print(hevc, 0, "uninit list\n"); @@ -11604,16 +11812,58 @@ static void vh265_work(struct work_struct *work) vdec_set_next_sched(vdec, vdec); #endif + if (from == 1) { + /* This is a timeout work */ + if (work_pending(&hevc->work)) { + /* + * The vh265_work arrives at the last second, + * give it a chance to handle the scenario. + */ + return; + //cancel_work_sync(&hevc->work);//reserved for future considraion + } + } + /* mark itself has all HW resource released and input released */ if (vdec->parallel_dec == 1) vdec_core_finish_run(vdec, CORE_MASK_HEVC); else vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + if (hevc->is_used_v4l) { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hevc->v4l2_ctx); + + if (ctx->param_sets_from_ucode && + !hevc->v4l_params_parsed) + vdec_v4l_write_frame_sync(ctx); + } + if (hevc->vdec_cb) hevc->vdec_cb(hw_to_vdec(hevc), hevc->vdec_cb_arg); } +static void vh265_work(struct work_struct *work) +{ + struct hevc_state_s *hevc = container_of(work, + struct hevc_state_s, work); + struct vdec_s *vdec = hw_to_vdec(hevc); + + vh265_work_implement(hevc, vdec, 0); +} + +static void vh265_timeout_work(struct work_struct *work) +{ + struct hevc_state_s *hevc = container_of(work, + struct hevc_state_s, timeout_work); + struct vdec_s *vdec = hw_to_vdec(hevc); + + if (work_pending(&hevc->work)) + return; + vh265_work_implement(hevc, vdec, 1); +} + + static int vh265_hw_ctx_restore(struct hevc_state_s *hevc) { /* new to do ... */ @@ -11667,7 +11917,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) again_threshold) { int r = vdec_sync_input(vdec); hevc_print(hevc, - PRINT_FLAG_VDEC_DETAIL, "%s buf lelvel:%x\n", __func__, r); + PRINT_FLAG_VDEC_DETAIL, "%s buf lelvel:%x\n", __func__, r); return 0; } } @@ -11715,6 +11965,17 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) } #endif + if (hevc->is_used_v4l) { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hevc->v4l2_ctx); + + if (ctx->param_sets_from_ucode && + !ctx->v4l_codec_ready && + hevc->v4l_params_parsed) + ret = 0; /*the params has parsed.*/ + } + + if (ret) not_run_ready[hevc->index] = 0; else @@ -11906,10 +12167,32 @@ static void reset(struct vdec_s *vdec) struct hevc_state_s *hevc = (struct hevc_state_s *)vdec->private; + int i; - hevc_print(hevc, - PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__); + cancel_work_sync(&hevc->work); + cancel_work_sync(&hevc->notify_work); + if (hevc->stat & STAT_VDEC_RUN) { + amhevc_stop(); + hevc->stat &= ~STAT_VDEC_RUN; + } + + if (hevc->stat & STAT_TIMER_ARM) { + del_timer_sync(&hevc->timer); + hevc->stat &= ~STAT_TIMER_ARM; + } + hevc->dec_result = DEC_RESULT_NONE; + reset_process_time(hevc); + hevc->init_flag = 0; + hevc->pic_list_init_flag = 0; + dealloc_mv_bufs(hevc); + hevc_local_uninit(hevc); + if (vh265_local_init(hevc) < 0) + pr_debug(" %s local init fail\n", __func__); + for (i = 0; i < BUF_POOL_SIZE; i++) { + hevc->m_BUF[i].start_adr = 0; + } + hevc_print(hevc, PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__); } static irqreturn_t vh265_irq_cb(struct vdec_s *vdec, int irq) @@ -11937,6 +12220,7 @@ static int amvdec_h265_probe(struct platform_device *pdev) struct vdec_dev_reg_s *pdata = (struct vdec_dev_reg_s *)pdev->dev.platform_data; #endif + char *tmpbuf; int ret; struct hevc_state_s *hevc; @@ -12001,6 +12285,29 @@ static int amvdec_h265_probe(struct platform_device *pdev) } hevc->buf_size = work_buf_size; + + if (!vdec_secure(pdata)) { + tmpbuf = (char *)codec_mm_phys_to_virt(hevc->buf_start); + if (tmpbuf) { + memset(tmpbuf, 0, work_buf_size); + dma_sync_single_for_device(amports_get_dma_device(), + hevc->buf_start, + work_buf_size, DMA_TO_DEVICE); + } else { + tmpbuf = codec_mm_vmap(hevc->buf_start, + work_buf_size); + if (tmpbuf) { + memset(tmpbuf, 0, work_buf_size); + dma_sync_single_for_device( + amports_get_dma_device(), + hevc->buf_start, + work_buf_size, + DMA_TO_DEVICE); + codec_mm_unmap_phyaddr(tmpbuf); + } + } + } + if (get_dbg_flag(hevc)) { hevc_print(hevc, 0, "===H.265 decoder mem resource 0x%lx size 0x%x\n", @@ -12406,8 +12713,14 @@ static int ammvdec_h265_probe(struct platform_device *pdev) hevc->is_used_v4l = (((unsigned long) hevc->vh265_amstream_dec_info.param & 0x80) >> 7); if (hevc->is_used_v4l) { - hevc->double_write_mode = 0x10; - hevc->mmu_enable = 0; + hevc->mmu_enable = (((unsigned long) // scatter mem + hevc->vh265_amstream_dec_info.param & 0x100) >> 8); + if (!hevc->mmu_enable) + hevc->double_write_mode = 0x10; + + hevc_print(hevc, PRINT_FLAG_V4L_DETAIL, + "%s v4: enable mmu %d.\n", + __func__, hevc->mmu_enable); } if (init_mmu_buffers(hevc) < 0) { @@ -12941,6 +13254,8 @@ MODULE_PARM_DESC(disp_vframe_valve_level, "\n disp_vframe_valve_level\n"); module_param(pic_list_debug, uint, 0664); MODULE_PARM_DESC(pic_list_debug, "\n pic_list_debug\n"); +module_param(without_display_mode, uint, 0664); +MODULE_PARM_DESC(without_display_mode, "\n amvdec_h265 without_display_mode\n"); module_init(amvdec_h265_driver_init_module); module_exit(amvdec_h265_driver_remove_module); diff --git a/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c b/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c index 3318523..c8c3eaa 100644 --- a/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c +++ b/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c @@ -43,8 +43,7 @@ #include <linux/amlogic/media/codec_mm/codec_mm.h> #include <linux/amlogic/media/codec_mm/configs.h> #include "../utils/firmware.h" - - +#include "../utils/vdec_v4l2_buffer_ops.h" #define MEM_NAME "codec_mmjpeg" @@ -95,6 +94,7 @@ static int vmjpeg_vf_states(struct vframe_states *states, void *); static int vmjpeg_event_cb(int type, void *data, void *private_data); static void vmjpeg_work(struct work_struct *work); static int pre_decode_buf_level = 0x800; +static u32 without_display_mode; #undef pr_info #define pr_info printk unsigned int mmjpeg_debug_mask = 0xff; @@ -110,6 +110,7 @@ unsigned int mmjpeg_debug_mask = 0xff; #define PRINT_FLAG_FORCE_DONE 0x0100 #define PRINT_FRAMEBASE_DATA 0x0400 #define PRINT_FLAG_TIMEOUT_STATUS 0x1000 +#define PRINT_FLAG_V4L_DETAIL 0x8000 int mmjpeg_debug_print(int index, int debug_flag, const char *fmt, ...) { @@ -142,8 +143,9 @@ static const struct vframe_operations_s vf_provider_ops = { #define DEC_RESULT_NONE 0 #define DEC_RESULT_DONE 1 #define DEC_RESULT_AGAIN 2 -#define DEC_RESULT_FORCE_EXIT 3 -#define DEC_RESULT_EOS 4 +#define DEC_RESULT_ERROR 3 +#define DEC_RESULT_FORCE_EXIT 4 +#define DEC_RESULT_EOS 5 #define DEC_DECODE_TIMEOUT 0x21 @@ -160,6 +162,7 @@ struct buffer_spec_s { unsigned long cma_alloc_addr; int cma_alloc_count; unsigned int buf_adr; + ulong v4l_ref_buf_addr; }; #define spec2canvas(x) \ @@ -205,9 +208,13 @@ struct vdec_mjpeg_hw_s { u32 put_num; u32 run_count; u32 not_run_ready; + u32 buffer_not_ready; u32 input_empty; u32 peek_num; u32 get_num; + bool is_used_v4l; + void *v4l2_ctx; + bool v4l_params_parsed; }; static void reset_process_time(struct vdec_mjpeg_hw_s *hw); @@ -279,6 +286,40 @@ static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq) return IRQ_HANDLED; } + if (hw->is_used_v4l) { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + + if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) { + struct aml_vdec_pic_infos info; + + info.visible_width = hw->frame_width; + info.visible_height = hw->frame_height; + info.coded_width = ALIGN(hw->frame_width, 64); + info.coded_height = ALIGN(hw->frame_height, 64); + info.dpb_size = MAX_BMMU_BUFFER_NUM - 1; + hw->v4l_params_parsed = true; + vdec_v4l_set_pic_infos(ctx, &info); + } + + if (!ctx->v4l_codec_ready) + return IRQ_HANDLED; + } + + if (hw->is_used_v4l) { + vf->v4l_mem_handle + = hw->buffer_spec[index].v4l_ref_buf_addr; + if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) { + mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "v4l: binding vf fail.\n"); + return -1; + } + mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), v4l mem handle: 0x%lx\n", + ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, + __func__, vf->v4l_mem_handle); + } + vf->index = index; set_frame_info(hw, vf); @@ -316,9 +357,12 @@ static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq) __func__, hw->frame_num, vf->pts, vf->pts_us64, vf->duration); vdec->vdec_fps_detec(vdec->id); - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); + if (without_display_mode == 0) { + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } else + vmjpeg_vf_put(vmjpeg_vf_get(vdec), vdec); hw->dec_result = DEC_RESULT_DONE; @@ -411,14 +455,13 @@ static int vmjpeg_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) } /****************************************/ -static void vmjpeg_canvas_init(struct vdec_s *vdec) +static void vmjpeg_canvas_init(struct vdec_mjpeg_hw_s *hw) { int i, ret; u32 canvas_width, canvas_height; u32 decbuf_size, decbuf_y_size, decbuf_uv_size; unsigned long buf_start, addr; - struct vdec_mjpeg_hw_s *hw = - (struct vdec_mjpeg_hw_s *)vdec->private; + struct vdec_s *vdec = hw_to_vdec(hw); canvas_width = 1920; canvas_height = 1088; @@ -429,12 +472,16 @@ static void vmjpeg_canvas_init(struct vdec_s *vdec) for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { int canvas; - ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i, - decbuf_size, DRIVER_NAME, &buf_start); - if (ret < 0) { - pr_err("CMA alloc failed! size 0x%d idx %d\n", - decbuf_size, i); - return; + if (hw->is_used_v4l) { + continue; + } else { + ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i, + decbuf_size, DRIVER_NAME, &buf_start); + if (ret < 0) { + pr_err("CMA alloc failed! size 0x%d idx %d\n", + decbuf_size, i); + return; + } } hw->buffer_spec[i].buf_adr = buf_start; @@ -778,27 +825,178 @@ static void check_timer_func(unsigned long arg) mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); } -static void vmjpeg_hw_ctx_restore(struct vdec_s *vdec, int index) +static int vmjpeg_v4l_alloc_buff_config_canvas(struct vdec_mjpeg_hw_s *hw, int i) +{ + int ret; + u32 canvas; + ulong decbuf_start = 0, addr; + int decbuf_y_size = 0, decbuf_uv_size = 0; + u32 canvas_width = 0, canvas_height = 0; + struct vdec_s *vdec = hw_to_vdec(hw); + struct vdec_v4l2_buffer *fb = NULL; + + if (hw->buffer_spec[i].v4l_ref_buf_addr) + return 0; + + ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb); + if (ret) { + mmjpeg_debug_print(DECODE_ID(hw), 0, + "[%d] get fb fail.\n", + ((struct aml_vcodec_ctx *) + (hw->v4l2_ctx))->id); + return ret; + } + + hw->buffer_spec[i].v4l_ref_buf_addr = (ulong)fb; + if (fb->num_planes == 1) { + decbuf_start = fb->m.mem[0].addr; + decbuf_y_size = fb->m.mem[0].offset; + decbuf_uv_size = fb->m.mem[0].size - fb->m.mem[0].offset; + canvas_width = ALIGN(hw->frame_width, 16); + canvas_height = ALIGN(hw->frame_height, 16); + fb->m.mem[0].bytes_used = fb->m.mem[0].size; + } else if (fb->num_planes == 2) { + decbuf_start = fb->m.mem[0].addr; + decbuf_y_size = fb->m.mem[0].size; + decbuf_uv_size = fb->m.mem[1].size << 1; + canvas_width = ALIGN(hw->frame_width, 16); + canvas_height = ALIGN(hw->frame_height, 16); + fb->m.mem[0].bytes_used = decbuf_y_size; + fb->m.mem[1].bytes_used = decbuf_uv_size >> 1; + } + + hw->buffer_spec[i].buf_adr = decbuf_start; + addr = hw->buffer_spec[i].buf_adr; + hw->buffer_spec[i].y_addr = addr; + addr += decbuf_y_size; + hw->buffer_spec[i].u_addr = addr; + addr += decbuf_uv_size; + hw->buffer_spec[i].v_addr = addr; + + mmjpeg_debug_print(DECODE_ID(hw), 0, "[%d] %s(), v4l ref buf addr: 0x%x\n", + ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, __func__, fb); + + if (vdec->parallel_dec == 1) { + if (hw->buffer_spec[i].y_canvas_index == -1) + hw->buffer_spec[i].y_canvas_index = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + if (hw->buffer_spec[i].u_canvas_index == -1) + hw->buffer_spec[i].u_canvas_index = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + if (hw->buffer_spec[i].v_canvas_index == -1) + hw->buffer_spec[i].v_canvas_index = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + } else { + canvas = vdec->get_canvas(i, 3); + hw->buffer_spec[i].y_canvas_index = canvas_y(canvas); + hw->buffer_spec[i].u_canvas_index = canvas_u(canvas); + hw->buffer_spec[i].v_canvas_index = canvas_v(canvas); + } + + canvas_config(hw->buffer_spec[i].y_canvas_index, + hw->buffer_spec[i].y_addr, + canvas_width, + canvas_height, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + hw->buffer_spec[i].canvas_config[0].phy_addr = + hw->buffer_spec[i].y_addr; + hw->buffer_spec[i].canvas_config[0].width = + canvas_width; + hw->buffer_spec[i].canvas_config[0].height = + canvas_height; + hw->buffer_spec[i].canvas_config[0].block_mode = + CANVAS_BLKMODE_LINEAR; + + canvas_config(hw->buffer_spec[i].u_canvas_index, + hw->buffer_spec[i].u_addr, + canvas_width / 2, + canvas_height / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + hw->buffer_spec[i].canvas_config[1].phy_addr = + hw->buffer_spec[i].u_addr; + hw->buffer_spec[i].canvas_config[1].width = + canvas_width / 2; + hw->buffer_spec[i].canvas_config[1].height = + canvas_height / 2; + hw->buffer_spec[i].canvas_config[1].block_mode = + CANVAS_BLKMODE_LINEAR; + + canvas_config(hw->buffer_spec[i].v_canvas_index, + hw->buffer_spec[i].v_addr, + canvas_width / 2, + canvas_height / 2, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + hw->buffer_spec[i].canvas_config[2].phy_addr = + hw->buffer_spec[i].v_addr; + hw->buffer_spec[i].canvas_config[2].width = + canvas_width / 2; + hw->buffer_spec[i].canvas_config[2].height = + canvas_height / 2; + hw->buffer_spec[i].canvas_config[2].block_mode = + CANVAS_BLKMODE_LINEAR; + + return 0; +} + +static bool is_enough_free_buffer(struct vdec_mjpeg_hw_s *hw) +{ + int i; + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + if (hw->vfbuf_use[i] == 0) + break; + } + + return i == DECODE_BUFFER_NUM_MAX ? false : true; +} + +static int find_free_buffer(struct vdec_mjpeg_hw_s *hw) +{ + int i; + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + if (hw->vfbuf_use[i] == 0) + break; + } + + if (i == DECODE_BUFFER_NUM_MAX) + return -1; + + if (hw->is_used_v4l) + if (vmjpeg_v4l_alloc_buff_config_canvas(hw, i)) + return -1; + + return i; +} + +static int vmjpeg_hw_ctx_restore(struct vdec_mjpeg_hw_s *hw) { - struct vdec_mjpeg_hw_s *hw = - (struct vdec_mjpeg_hw_s *)vdec->private; struct buffer_spec_s *buff_spec; - u32 i; + u32 index, i; + + index = find_free_buffer(hw); + if (index < 0) + return -1; WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6)); WRITE_VREG(DOS_SW_RESET0, 0); if (!hw->init_flag) { - vmjpeg_canvas_init(vdec); + vmjpeg_canvas_init(hw); } else { - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { - buff_spec = &hw->buffer_spec[i]; - canvas_config_config(buff_spec->y_canvas_index, - &buff_spec->canvas_config[0]); - canvas_config_config(buff_spec->u_canvas_index, - &buff_spec->canvas_config[1]); - canvas_config_config(buff_spec->v_canvas_index, - &buff_spec->canvas_config[2]); + if (!hw->is_used_v4l) { + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + buff_spec = &hw->buffer_spec[i]; + canvas_config_config(buff_spec->y_canvas_index, + &buff_spec->canvas_config[0]); + canvas_config_config(buff_spec->u_canvas_index, + &buff_spec->canvas_config[1]); + canvas_config_config(buff_spec->v_canvas_index, + &buff_spec->canvas_config[2]); + } } } @@ -824,6 +1022,7 @@ static void vmjpeg_hw_ctx_restore(struct vdec_s *vdec, int index) #if 1/*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6*/ CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); #endif + return 0; } static s32 vmjpeg_init(struct vdec_s *vdec) @@ -925,8 +1124,14 @@ static unsigned long run_ready(struct vdec_s *vdec, if (level < pre_decode_buf_level) return 0; } - hw->not_run_ready = 0; + if (!is_enough_free_buffer(hw)) { + hw->buffer_not_ready++; + return 0; + } + + hw->not_run_ready = 0; + hw->buffer_not_ready = 0; if (vdec->parallel_dec == 1) return CORE_MASK_VDEC_1; else @@ -994,7 +1199,13 @@ static void run(struct vdec_s *vdec, unsigned long mask, return; }*/ - vmjpeg_hw_ctx_restore(vdec, i); + if (vmjpeg_hw_ctx_restore(hw) < 0) { + hw->dec_result = DEC_RESULT_ERROR; + mmjpeg_debug_print(DECODE_ID(hw), 0, + "amvdec_mmjpeg: error HW context restore\n"); + vdec_schedule_work(&hw->work); + return; + } #if 0 vdec_enable_input(vdec); mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); @@ -1009,19 +1220,19 @@ static void run(struct vdec_s *vdec, unsigned long mask, hw->init_flag = 1; mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, - "%s (0x%x 0x%x 0x%x) vldcrl 0x%x bitcnt 0x%x powerctl 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", - __func__, - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP), - READ_VREG(VLD_DECODE_CONTROL), - READ_VREG(VIFF_BIT_CNT), - READ_VREG(POWER_CTL_VLD), - READ_VREG(VLD_MEM_VIFIFO_START_PTR), - READ_VREG(VLD_MEM_VIFIFO_CURR_PTR), - READ_VREG(VLD_MEM_VIFIFO_CONTROL), - READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL), - READ_VREG(VLD_MEM_VIFIFO_END_PTR)); + "%s (0x%x 0x%x 0x%x) vldcrl 0x%x bitcnt 0x%x powerctl 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + __func__, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP), + READ_VREG(VLD_DECODE_CONTROL), + READ_VREG(VIFF_BIT_CNT), + READ_VREG(POWER_CTL_VLD), + READ_VREG(VLD_MEM_VIFIFO_START_PTR), + READ_VREG(VLD_MEM_VIFIFO_CURR_PTR), + READ_VREG(VLD_MEM_VIFIFO_CONTROL), + READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL), + READ_VREG(VLD_MEM_VIFIFO_END_PTR)); } static void wait_vmjpeg_search_done(struct vdec_mjpeg_hw_s *hw) { @@ -1043,6 +1254,40 @@ static void wait_vmjpeg_search_done(struct vdec_mjpeg_hw_s *hw) } while (1); } +static int notify_v4l_eos(struct vdec_s *vdec) +{ + struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private; + struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + struct vframe_s *vf = NULL; + struct vdec_v4l2_buffer *fb = NULL; + + if (hw->is_used_v4l && hw->eos) { + if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) { + mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "%s fatal error, no available buffer slot.\n", + __func__); + return -1; + } + + if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) { + pr_err("[%d] get fb fail.\n", ctx->id); + return -1; + } + + vf->timestamp = ULONG_MAX; + vf->v4l_mem_handle = (unsigned long)fb; + vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; + + kfifo_put(&hw->display_q, (const struct vframe_s *)vf); + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + + pr_info("[%d] mpeg12 EOS notify.\n", ctx->id); + } + + return 0; +} + static void vmjpeg_work(struct work_struct *work) { struct vdec_mjpeg_hw_s *hw = container_of(work, @@ -1083,6 +1328,9 @@ static void vmjpeg_work(struct work_struct *work) hw->stat &= ~STAT_VDEC_RUN; } hw->eos = 1; + if (hw->is_used_v4l) + notify_v4l_eos(vdec); + vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); hw->chunk = NULL; vdec_clean_input(hw_to_vdec(hw)); @@ -1161,6 +1409,9 @@ static int ammvdec_mjpeg_probe(struct platform_device *pdev) return -ENOMEM; } + /* the ctx from v4l2 driver. */ + hw->v4l2_ctx = pdata->private; + pdata->private = hw; pdata->dec_status = vmjpeg_dec_status; @@ -1192,8 +1443,11 @@ static int ammvdec_mjpeg_probe(struct platform_device *pdev) hw->platform_dev = pdev; - if (pdata->sys_info) + if (pdata->sys_info) { hw->vmjpeg_amstream_dec_info = *pdata->sys_info; + hw->is_used_v4l = (((unsigned long) + hw->vmjpeg_amstream_dec_info.param & 0x80) >> 7); + } vdec_source_changed(VFORMAT_MJPEG, 1920, 1080, 60); @@ -1317,6 +1571,9 @@ MODULE_PARM_DESC(radr, "\nradr\n"); module_param(rval, uint, 0664); MODULE_PARM_DESC(rval, "\nrval\n"); +module_param(without_display_mode, uint, 0664); +MODULE_PARM_DESC(without_display_mode, "\n without_display_mode\n"); + module_init(ammvdec_mjpeg_driver_init_module); module_exit(ammvdec_mjpeg_driver_remove_module); diff --git a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c index 8898743..6643f41 100644 --- a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c +++ b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c @@ -47,6 +47,7 @@ #include <linux/amlogic/media/codec_mm/codec_mm.h> #include <linux/amlogic/media/codec_mm/configs.h> #include "../utils/firmware.h" +#include "../utils/vdec_v4l2_buffer_ops.h" #define MEM_NAME "codec_mmpeg12" @@ -106,12 +107,14 @@ static u32 buf_size = 32 * 1024 * 1024; static int pre_decode_buf_level = 0x800; static u32 dec_control; -static u32 error_frame_skip_level; +static u32 error_frame_skip_level = 2; static u32 stat; static u32 udebug_flag; static unsigned int radr; static unsigned int rval; +static u32 without_display_mode; + #define VMPEG12_DEV_NUM 9 static unsigned int max_decode_instance_num = VMPEG12_DEV_NUM; static unsigned int max_process_time[VMPEG12_DEV_NUM]; @@ -135,7 +138,7 @@ static unsigned int decode_timeout_val = 100; #define AGAIN_HAS_THRESHOLD #ifdef AGAIN_HAS_THRESHOLD -u32 again_threshold = 0x40; +u32 again_threshold; #endif /* @@ -195,6 +198,7 @@ struct pic_info_t { u32 pts; u64 pts64; bool pts_valid; + ulong v4l_ref_buf_addr; }; struct vdec_mpeg12_hw_s { @@ -243,6 +247,7 @@ struct vdec_mpeg12_hw_s { s32 refs[2]; int dec_result; struct work_struct work; + struct work_struct timeout_work; struct work_struct notify_work; void (*vdec_cb)(struct vdec_s *, void *); void *vdec_cb_arg; @@ -292,6 +297,9 @@ struct vdec_mpeg12_hw_s { u32 reference[MAX_UD_RECORDS]; #endif int tvp_flag; + bool is_used_v4l; + void *v4l2_ctx; + bool v4l_params_parsed; }; static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw); static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw); @@ -307,7 +315,7 @@ unsigned int mpeg12_debug_mask = 0xff; #define PRINT_FLAG_ERROR 0x0 #define PRINT_FLAG_RUN_FLOW 0X0001 #define PRINT_FLAG_TIMEINFO 0x0002 -#define PRINT_FLAG_UCODE_DETAIL 0x0004 +#define PRINT_FLAG_UCODE_DETAIL 0x0004 #define PRINT_FLAG_VLD_DETAIL 0x0008 #define PRINT_FLAG_DEC_DETAIL 0x0010 #define PRINT_FLAG_BUFFER_DETAIL 0x0020 @@ -319,7 +327,8 @@ unsigned int mpeg12_debug_mask = 0xff; #define PRINT_FLAG_VDEC_STATUS 0x0800 #define PRINT_FLAG_PARA_DATA 0x1000 #define PRINT_FLAG_USERDATA_DETAIL 0x2000 -#define PRINT_FLAG_TIMEOUT_STATUS 0x4000 +#define PRINT_FLAG_TIMEOUT_STATUS 0x4000 +#define PRINT_FLAG_V4L_DETAIL 0x8000 @@ -361,17 +370,114 @@ static const u32 frame_rate_tab[16] = { 96000 / 24, 96000 / 24, 96000 / 24 }; +static int vmpeg12_v4l_alloc_buff_config_canvas(struct vdec_mpeg12_hw_s *hw, int i) +{ + int ret; + u32 canvas; + ulong decbuf_start = 0; + int decbuf_y_size = 0; + u32 canvas_width = 0, canvas_height = 0; + struct vdec_s *vdec = hw_to_vdec(hw); + struct vdec_v4l2_buffer *fb = NULL; + + if (hw->pics[i].v4l_ref_buf_addr) + return 0; + + ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb); + if (ret) { + debug_print(DECODE_ID(hw), 0, + "[%d] get fb fail.\n", + ((struct aml_vcodec_ctx *) + (hw->v4l2_ctx))->id); + return ret; + } + + hw->pics[i].v4l_ref_buf_addr = (ulong)fb; + if (fb->num_planes == 1) { + decbuf_start = fb->m.mem[0].addr; + decbuf_y_size = fb->m.mem[0].offset; + canvas_width = ALIGN(hw->frame_width, 64); + canvas_height = ALIGN(hw->frame_height, 32); + fb->m.mem[0].bytes_used = fb->m.mem[0].size; + } else if (fb->num_planes == 2) { + decbuf_start = fb->m.mem[0].addr; + decbuf_y_size = fb->m.mem[0].size; + canvas_width = ALIGN(hw->frame_width, 64); + canvas_height = ALIGN(hw->frame_height, 32); + fb->m.mem[0].bytes_used = decbuf_y_size; + fb->m.mem[1].bytes_used = decbuf_y_size << 1; + } + + debug_print(DECODE_ID(hw), 0, "[%d] %s(), v4l ref buf addr: 0x%x\n", + ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, __func__, fb); + + if (vdec->parallel_dec == 1) { + u32 tmp; + if (canvas_y(hw->canvas_spec[i]) == 0xff) { + tmp = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->canvas_spec[i] &= ~0xff; + hw->canvas_spec[i] |= tmp; + } + if (canvas_u(hw->canvas_spec[i]) == 0xff) { + tmp = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->canvas_spec[i] &= ~(0xffff << 8); + hw->canvas_spec[i] |= tmp << 8; + hw->canvas_spec[i] |= tmp << 16; + } + canvas = hw->canvas_spec[i]; + } else { + canvas = vdec->get_canvas(i, 2); + hw->canvas_spec[i] = canvas; + } + + hw->canvas_config[i][0].phy_addr = decbuf_start; + hw->canvas_config[i][0].width = canvas_width; + hw->canvas_config[i][0].height = canvas_height; + hw->canvas_config[i][0].block_mode = hw->canvas_mode; + hw->canvas_config[i][0].endian = + (hw->canvas_mode == CANVAS_BLKMODE_LINEAR) ? 7 : 0; + canvas_config_config(canvas_y(canvas), &hw->canvas_config[i][0]); + + hw->canvas_config[i][1].phy_addr = decbuf_start + decbuf_y_size; + hw->canvas_config[i][1].width = canvas_width; + hw->canvas_config[i][1].height = canvas_height / 2; + hw->canvas_config[i][1].block_mode = hw->canvas_mode; + hw->canvas_config[i][1].endian = + (hw->canvas_mode == CANVAS_BLKMODE_LINEAR) ? 7 : 0; + canvas_config_config(canvas_u(canvas), &hw->canvas_config[i][1]); + + return 0; +} + -static u32 find_buffer(struct vdec_mpeg12_hw_s *hw) +static bool is_enough_free_buffer(struct vdec_mpeg12_hw_s *hw) { - u32 i; + int i; for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { if (hw->vfbuf_use[i] == 0) - return i; + break; } - return DECODE_BUFFER_NUM_MAX; + return i == DECODE_BUFFER_NUM_MAX ? false : true; +} + +static int find_free_buffer(struct vdec_mpeg12_hw_s *hw) +{ + int i; + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + if (hw->vfbuf_use[i] == 0) + break; + } + + if (i == DECODE_BUFFER_NUM_MAX) + return -1; + + if (hw->is_used_v4l) + if (vmpeg12_v4l_alloc_buff_config_canvas(hw, i)) + return -1; + return i; } static u32 spec_to_index(struct vdec_mpeg12_hw_s *hw, u32 spec) @@ -1086,9 +1192,10 @@ static void userdata_push_do_work(struct work_struct *work) } if (hw->cur_ud_idx >= MAX_UD_RECORDS) { - debug_print(DECODE_ID(hw), 0, + debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, "UD Records over: %d, skip it\n", MAX_UD_RECORDS); WRITE_VREG(AV_SCRATCH_J, 0); + hw->cur_ud_idx = 0; return; } @@ -1265,6 +1372,21 @@ static int prepare_display_buf(struct vdec_mpeg12_hw_s *hw, vdec_schedule_work(&hw->work); return -1; } + + if (hw->is_used_v4l) { + vf->v4l_mem_handle + = hw->pics[index].v4l_ref_buf_addr; + if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) { + debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "v4l: binding vf fail.\n"); + return -1; + } + debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), v4l mem handle: 0x%lx\n", + ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, + __func__, vf->v4l_mem_handle); + } + hw->vfbuf_use[index]++; vf->index = index; set_frame_info(hw, vf); @@ -1331,8 +1453,14 @@ static int prepare_display_buf(struct vdec_mpeg12_hw_s *hw, hw->mm_blk_handle, index); kfifo_put(&hw->display_q, (const struct vframe_s *)vf); - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + if (without_display_mode == 0) { + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } else + vmpeg_vf_put(vmpeg_vf_get(vdec), vdec); + + } } return 0; @@ -1401,6 +1529,15 @@ static int update_reference(struct vdec_mpeg12_hw_s *hw, return index; } +static bool is_ref_error(struct vdec_mpeg12_hw_s *hw) +{ + if ((hw->pics[hw->refs[0]].buffer_info & PICINFO_ERROR) || + (hw->pics[hw->refs[1]].buffer_info & PICINFO_ERROR)) + return 1; + return 0; +} + + static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq) { u32 reg, index, info, seqinfo, offset, pts, frame_size, tmp; @@ -1482,14 +1619,34 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq) } tmp = READ_VREG(MREG_PIC_HEIGHT); - if ((tmp > 1080) || (tmp == 0)) { - new_pic->height = 1080; - hw->frame_height = 1080; + if ((tmp > 1088) || (tmp == 0)) { + new_pic->height = 1088; + hw->frame_height = 1088; } else { new_pic->height = tmp; hw->frame_height = tmp; } + if (hw->is_used_v4l) { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + + if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) { + struct aml_vdec_pic_infos info; + + info.visible_width = hw->frame_width; + info.visible_height = hw->frame_height; + info.coded_width = ALIGN(hw->frame_width, 64); + info.coded_height = ALIGN(hw->frame_height, 64); + info.dpb_size = MAX_BMMU_BUFFER_NUM - 1; + hw->v4l_params_parsed = true; + vdec_v4l_set_pic_infos(ctx, &info); + } + + if (!ctx->v4l_codec_ready) + return IRQ_HANDLED; + } + new_pic->buffer_info = info; new_pic->offset = offset; new_pic->index = index; @@ -1529,6 +1686,11 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq) hw->frame_prog = 0; force_interlace_check(hw); + if (is_ref_error(hw)) { + if ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_B) + new_pic->buffer_info |= PICINFO_ERROR; + } + if (((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) || ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_P)) { index = update_reference(hw, index); @@ -1636,12 +1798,43 @@ static void flush_output(struct vdec_mpeg12_hw_s *hw) prepare_display_buf(hw, &hw->pics[index]); } -static void vmpeg12_work(struct work_struct *work) +static int notify_v4l_eos(struct vdec_s *vdec) { - struct vdec_mpeg12_hw_s *hw = - container_of(work, struct vdec_mpeg12_hw_s, work); - struct vdec_s *vdec = hw_to_vdec(hw); + struct vdec_mpeg12_hw_s *hw = (struct vdec_mpeg12_hw_s *)vdec->private; + struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + struct vframe_s *vf = NULL; + struct vdec_v4l2_buffer *fb = NULL; + + if (hw->is_used_v4l && hw->eos) { + if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) { + debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "%s fatal error, no available buffer slot.\n", + __func__); + return -1; + } + + if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) { + pr_err("[%d] get fb fail.\n", ctx->id); + return -1; + } + + vf->timestamp = ULONG_MAX; + vf->v4l_mem_handle = (unsigned long)fb; + vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; + + kfifo_put(&hw->display_q, (const struct vframe_s *)vf); + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + + pr_info("[%d] mpeg12 EOS notify.\n", ctx->id); + } + + return 0; +} +static void vmpeg12_work_implement(struct vdec_mpeg12_hw_s *hw, + struct vdec_s *vdec, int from) +{ if (hw->dec_result != DEC_RESULT_DONE) debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, "%s, result=%d, status=%d\n", __func__, @@ -1699,6 +1892,9 @@ static void vmpeg12_work(struct work_struct *work) hw->chunk = NULL; vdec_clean_input(vdec); flush_output(hw); + if (hw->is_used_v4l) + notify_v4l_eos(vdec); + debug_print(DECODE_ID(hw), 0, "%s: end of stream, num %d(%d)\n", __func__, hw->disp_num, hw->dec_num); @@ -1707,6 +1903,19 @@ static void vmpeg12_work(struct work_struct *work) amvdec_stop(); hw->stat &= ~STAT_VDEC_RUN; } + + if (from == 1) { + /*This is a timeout work*/ + if (work_pending(&hw->work)) { + pr_err("timeout work return befor finishing."); + /* + * The vmpeg12_work arrives at the last second, + * give it a chance to handle the scenario. + */ + return; + } + } + /*disable mbox interrupt */ WRITE_VREG(ASSIST_MBOX1_MASK, 0); wait_vmmpeg12_search_done(hw); @@ -1721,6 +1930,28 @@ static void vmpeg12_work(struct work_struct *work) hw->vdec_cb(vdec, hw->vdec_cb_arg); } +static void vmpeg12_work(struct work_struct *work) +{ + struct vdec_mpeg12_hw_s *hw = + container_of(work, struct vdec_mpeg12_hw_s, work); + struct vdec_s *vdec = hw_to_vdec(hw); + + vmpeg12_work_implement(hw, vdec, 0); +} +static void vmpeg12_timeout_work(struct work_struct *work) +{ + struct vdec_mpeg12_hw_s *hw = + container_of(work, struct vdec_mpeg12_hw_s, timeout_work); + struct vdec_s *vdec = hw_to_vdec(hw); + + if (work_pending(&hw->work)) { + pr_err("timeout work return befor executing."); + return; + } + + vmpeg12_work_implement(hw, vdec, 1); +} + static struct vframe_s *vmpeg_vf_peek(void *op_arg) { struct vframe_s *vf; @@ -1847,16 +2078,21 @@ static void vmpeg12_canvas_init(struct vdec_mpeg12_hw_s *hw) } for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) { - unsigned canvas; + if (i == (MAX_BMMU_BUFFER_NUM - 1)) /* SWAP&CCBUF&MATIRX&MV */ decbuf_size = WORKSPACE_SIZE; - ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i, - decbuf_size, DRIVER_NAME, &decbuf_start); - if (ret < 0) { - pr_err("mmu alloc failed! size 0x%d idx %d\n", - decbuf_size, i); - return; + + if (hw->is_used_v4l && !(i == (MAX_BMMU_BUFFER_NUM - 1))) { + continue; + } else { + ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i, + decbuf_size, DRIVER_NAME, &decbuf_start); + if (ret < 0) { + pr_err("mmu alloc failed! size 0x%d idx %d\n", + decbuf_size, i); + return; + } } if (i == (MAX_BMMU_BUFFER_NUM - 1)) { @@ -2059,6 +2295,10 @@ static void timeout_process(struct vdec_mpeg12_hw_s *hw) { struct vdec_s *vdec = hw_to_vdec(hw); + if (work_pending(&hw->work)) { + pr_err("timeout_process return befor do anything."); + return; + } reset_process_time(hw); amvdec_stop(); debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, @@ -2066,7 +2306,16 @@ static void timeout_process(struct vdec_mpeg12_hw_s *hw) __func__, vdec->status, READ_VREG(VLD_MEM_VIFIFO_LEVEL)); hw->dec_result = DEC_RESULT_DONE; hw->first_i_frame_ready = 0; - vdec_schedule_work(&hw->work); + + /* + * In this very timeout point,the vmpeg12_work arrives, + * let it to handle the scenario. + */ + if (work_pending(&hw->work)) { + pr_err("timeout_process return befor schedule."); + return; + } + vdec_schedule_work(&hw->timeout_work); } static void check_timer_func(unsigned long arg) @@ -2086,8 +2335,6 @@ static void check_timer_func(unsigned long arg) } if (((debug_enable & PRINT_FLAG_TIMEOUT_STATUS) == 0) && - (vdec_frame_based(vdec) || - ((u32)READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0x100)) && (timeout_val > 0) && (hw->start_process_time > 0) && ((1000 * (jiffies - hw->start_process_time) / HZ) @@ -2114,18 +2361,20 @@ static void check_timer_func(unsigned long arg) static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw) { u32 index, i; - index = find_buffer(hw); + index = find_free_buffer(hw); if (index >= DECODE_BUFFER_NUM_MAX) return -1; if (!hw->init_flag) vmpeg12_canvas_init(hw); else { - WRITE_VREG(MREG_CO_MV_START, hw->buf_start); - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { - canvas_config_config(canvas_y(hw->canvas_spec[i]), - &hw->canvas_config[i][0]); - canvas_config_config(canvas_u(hw->canvas_spec[i]), - &hw->canvas_config[i][1]); + if (!hw->is_used_v4l) { + WRITE_VREG(MREG_CO_MV_START, hw->buf_start); + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + canvas_config_config(canvas_y(hw->canvas_spec[i]), + &hw->canvas_config[i][0]); + canvas_config_config(canvas_u(hw->canvas_spec[i]), + &hw->canvas_config[i][1]); + } } } @@ -2292,6 +2541,7 @@ static s32 vmpeg12_init(struct vdec_mpeg12_hw_s *hw) INIT_WORK(&hw->userdata_push_work, userdata_push_do_work); INIT_WORK(&hw->work, vmpeg12_work); + INIT_WORK(&hw->timeout_work, vmpeg12_timeout_work); INIT_WORK(&hw->notify_work, vmpeg12_notify_work); if (NULL == hw->user_data_buffer) { @@ -2325,8 +2575,6 @@ static s32 vmpeg12_init(struct vdec_mpeg12_hw_s *hw) static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) { - int index; - struct vdec_mpeg12_hw_s *hw = (struct vdec_mpeg12_hw_s *)vdec->private; if (hw->eos) @@ -2365,8 +2613,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) } #endif - index = find_buffer(hw); - if (index >= DECODE_BUFFER_NUM_MAX) { + if (!is_enough_free_buffer(hw)) { hw->buffer_not_ready++; return 0; } @@ -2551,6 +2798,9 @@ static int ammvdec_mpeg12_probe(struct platform_device *pdev) return -ENOMEM; } + /* the ctx from v4l2 driver. */ + hw->v4l2_ctx = pdata->private; + pdata->private = hw; pdata->dec_status = vmmpeg12_dec_status; pdata->run_ready = run_ready; @@ -2615,6 +2865,9 @@ static int ammvdec_mpeg12_probe(struct platform_device *pdev) reset_user_data_buf(hw); #endif + hw->is_used_v4l = (((unsigned long) + hw->vmpeg12_amstream_dec_info.param & 0x80) >> 7); + /*INIT_WORK(&userdata_push_work, userdata_push_do_work);*/ return 0; } @@ -2645,6 +2898,7 @@ static int ammvdec_mpeg12_remove(struct platform_device *pdev) cancel_work_sync(&hw->userdata_push_work); cancel_work_sync(&hw->notify_work); cancel_work_sync(&hw->work); + cancel_work_sync(&hw->timeout_work); if (hw->mm_blk_handle) { decoder_bmmu_box_free(hw->mm_blk_handle); @@ -2785,11 +3039,16 @@ module_param_array(max_process_time, uint, &max_decode_instance_num, 0664); module_param(udebug_flag, uint, 0664); MODULE_PARM_DESC(udebug_flag, "\n ammvdec_mpeg12 udebug_flag\n"); + #ifdef AGAIN_HAS_THRESHOLD module_param(again_threshold, uint, 0664); MODULE_PARM_DESC(again_threshold, "\n again_threshold\n"); #endif +module_param(without_display_mode, uint, 0664); +MODULE_PARM_DESC(without_display_mode, "\n ammvdec_mpeg12 without_display_mode\n"); + + module_init(ammvdec_mpeg12_driver_init_module); module_exit(ammvdec_mpeg12_driver_remove_module); diff --git a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c index e8d62c2..30e4072 100644 --- a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c +++ b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c @@ -45,8 +45,7 @@ #include "../utils/decoder_bmmu_box.h" #include <linux/amlogic/media/codec_mm/configs.h> #include "../utils/firmware.h" - - +#include "../utils/vdec_v4l2_buffer_ops.h" #define DRIVER_NAME "ammvdec_mpeg4" #define MODULE_NAME "ammvdec_mpeg4" @@ -139,6 +138,7 @@ static int pre_decode_buf_level = 0x800; static int debug_enable; static unsigned int radr; static unsigned int rval; +/* 0x40bit = 8byte */ static unsigned int frmbase_cont_bitlevel = 0x40; #define VMPEG4_DEV_NUM 9 @@ -146,6 +146,8 @@ static unsigned int max_decode_instance_num = VMPEG4_DEV_NUM; static unsigned int max_process_time[VMPEG4_DEV_NUM]; static unsigned int decode_timeout_val = 100; +static u32 without_display_mode; + #undef pr_info #define pr_info printk unsigned int mpeg4_debug_mask = 0xff; @@ -164,6 +166,7 @@ unsigned int mpeg4_debug_mask = 0xff; #define PRINT_FRAMEBASE_DATA 0x0400 #define PRINT_FLAG_VDEC_STATUS 0x0800 #define PRINT_FLAG_TIMEOUT_STATUS 0x1000 +#define PRINT_FLAG_V4L_DETAIL 0x8000 int mmpeg4_debug_print(int index, int debug_flag, const char *fmt, ...) { @@ -191,6 +194,7 @@ struct pic_info_t { bool pts_valid; u32 duration; u32 repeat_cnt; + ulong v4l_ref_buf_addr; }; struct vdec_mpeg4_hw_s { @@ -291,6 +295,9 @@ struct vdec_mpeg4_hw_s { struct firmware_s *fw; u32 blkmode; wait_queue_head_t wait_q; + bool is_used_v4l; + void *v4l2_ctx; + bool v4l_params_parsed; }; static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw); static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw); @@ -323,16 +330,122 @@ static unsigned char aspect_ratio_table[16] = { }; static void reset_process_time(struct vdec_mpeg4_hw_s *hw); -static int find_buffer(struct vdec_mpeg4_hw_s *hw) + +static int vmpeg4_v4l_alloc_buff_config_canvas(struct vdec_mpeg4_hw_s *hw, int i) +{ + int ret; + u32 canvas; + ulong decbuf_start = 0; + int decbuf_y_size = 0; + u32 canvas_width = 0, canvas_height = 0; + struct vdec_s *vdec = hw_to_vdec(hw); + struct vdec_v4l2_buffer *fb = NULL; + + if (hw->pic[i].v4l_ref_buf_addr) + return 0; + + ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb); + if (ret) { + mmpeg4_debug_print(DECODE_ID(hw), 0, + "[%d] get fb fail.\n", + ((struct aml_vcodec_ctx *) + (hw->v4l2_ctx))->id); + return ret; + } + + hw->pic[i].v4l_ref_buf_addr = (ulong)fb; + if (fb->num_planes == 1) { + decbuf_start = fb->m.mem[0].addr; + decbuf_y_size = fb->m.mem[0].offset; + canvas_width = ALIGN(hw->frame_width, 64); + canvas_height = ALIGN(hw->frame_height, 32); + fb->m.mem[0].bytes_used = fb->m.mem[0].size; + } else if (fb->num_planes == 2) { + decbuf_start = fb->m.mem[0].addr; + decbuf_y_size = fb->m.mem[0].size; + canvas_width = ALIGN(hw->frame_width, 64); + canvas_height = ALIGN(hw->frame_height, 32); + fb->m.mem[0].bytes_used = decbuf_y_size; + fb->m.mem[1].bytes_used = decbuf_y_size << 1; + } + + mmpeg4_debug_print(DECODE_ID(hw), 0, "[%d] %s(), v4l ref buf addr: 0x%x\n", + ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, __func__, fb); + + if (vdec->parallel_dec == 1) { + u32 tmp; + if (canvas_y(hw->canvas_spec[i]) == 0xff) { + tmp = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->canvas_spec[i] &= ~0xff; + hw->canvas_spec[i] |= tmp; + } + if (canvas_u(hw->canvas_spec[i]) == 0xff) { + tmp = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->canvas_spec[i] &= ~(0xffff << 8); + hw->canvas_spec[i] |= tmp << 8; + hw->canvas_spec[i] |= tmp << 16; + } + canvas = hw->canvas_spec[i]; + } else { + canvas = vdec->get_canvas(i, 2); + hw->canvas_spec[i] = canvas; + } + + hw->canvas_config[i][0].phy_addr = decbuf_start; + hw->canvas_config[i][0].width = canvas_width; + hw->canvas_config[i][0].height = canvas_height; + hw->canvas_config[i][0].block_mode = hw->blkmode; + if (hw->blkmode == CANVAS_BLKMODE_LINEAR) + hw->canvas_config[i][0].endian = 7; + else + hw->canvas_config[i][0].endian = 0; + canvas_config_config(canvas_y(canvas), + &hw->canvas_config[i][0]); + + hw->canvas_config[i][1].phy_addr = + decbuf_start + decbuf_y_size; + hw->canvas_config[i][1].width = canvas_width; + hw->canvas_config[i][1].height = (canvas_height >> 1); + hw->canvas_config[i][1].block_mode = hw->blkmode; + if (hw->blkmode == CANVAS_BLKMODE_LINEAR) + hw->canvas_config[i][1].endian = 7; + else + hw->canvas_config[i][1].endian = 0; + canvas_config_config(canvas_u(canvas), + &hw->canvas_config[i][1]); + + return 0; +} + +static bool is_enough_free_buffer(struct vdec_mpeg4_hw_s *hw) { int i; for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { if (hw->vfbuf_use[i] == 0) - return i; + break; + } + + return i == DECODE_BUFFER_NUM_MAX ? false : true; +} + +static int find_free_buffer(struct vdec_mpeg4_hw_s *hw) +{ + int i; + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + if (hw->vfbuf_use[i] == 0) + break; } - return DECODE_BUFFER_NUM_MAX; + if (i == DECODE_BUFFER_NUM_MAX) + return -1; + + if (hw->is_used_v4l) + if (vmpeg4_v4l_alloc_buff_config_canvas(hw, i)) + return -1; + + return i; } static int spec_to_index(struct vdec_mpeg4_hw_s *hw, u32 spec) @@ -474,7 +587,6 @@ static int update_ref(struct vdec_mpeg4_hw_s *hw, int index) return index; } - static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw, struct pic_info_t *pic) { @@ -489,6 +601,15 @@ static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw, return -1; } + if (hw->is_used_v4l) { + vf->v4l_mem_handle + = hw->pic[index].v4l_ref_buf_addr; + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), v4l mem handle: 0x%lx\n", + ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, + __func__, vf->v4l_mem_handle); + } + vf->index = pic->index; vf->width = hw->frame_width; vf->height = hw->frame_height; @@ -527,8 +648,11 @@ static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw, ATRACE_COUNTER(MODULE_NAME, vf->pts); vdec->vdec_fps_detec(vdec->id); hw->frame_num++; - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + if (without_display_mode == 0) { + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } else + vmpeg_vf_put(vmpeg_vf_get(vdec), vdec); } if (kfifo_get(&hw->newframe_q, &vf) == 0) { @@ -575,8 +699,11 @@ static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw, vdec->vdec_fps_detec(vdec->id); decoder_do_frame_check(vdec, vf); hw->frame_num++; - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + if (without_display_mode == 0) { + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } else + vmpeg_vf_put(vmpeg_vf_get(vdec), vdec); } } else { /* progressive */ @@ -587,6 +714,20 @@ static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw, return -1; } + if (hw->is_used_v4l) { + vf->v4l_mem_handle + = hw->pic[index].v4l_ref_buf_addr; + if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) { + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "v4l: binding vf fail.\n"); + return -1; + } + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), v4l mem handle: 0x%lx\n", + ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, + __func__, vf->v4l_mem_handle); + } + vf->index = index; vf->width = hw->frame_width; vf->height = hw->frame_height; @@ -628,8 +769,12 @@ static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw, vdec->vdec_fps_detec(vdec->id); decoder_do_frame_check(vdec, vf); hw->frame_num++; - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + + if (without_display_mode == 0) { + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } else + vmpeg_vf_put(vmpeg_vf_get(vdec), vdec); } } @@ -804,6 +949,26 @@ static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq) if (dec_h != 0) hw->frame_height = dec_h; + if (hw->is_used_v4l) { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + + if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) { + struct aml_vdec_pic_infos info; + + info.visible_width = hw->frame_width; + info.visible_height = hw->frame_height; + info.coded_width = ALIGN(hw->frame_width, 64); + info.coded_height = ALIGN(hw->frame_height, 64); + info.dpb_size = MAX_BMMU_BUFFER_NUM - 1; + hw->v4l_params_parsed = true; + vdec_v4l_set_pic_infos(ctx, &info); + } + + if (!ctx->v4l_codec_ready) + return IRQ_HANDLED; + } + if (hw->vmpeg4_amstream_dec_info.rate == 0) { if (vop_time_inc < hw->last_vop_time_inc) { duration = vop_time_inc + @@ -905,7 +1070,6 @@ static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq) return IRQ_HANDLED; } disp_pic = &hw->pic[index]; - if ((hw->first_i_frame_ready == 0) && (I_PICTURE == disp_pic->pic_type)) hw->first_i_frame_ready = 1; @@ -1031,15 +1195,35 @@ static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq) if (vdec_frame_based(vdec) && (frmbase_cont_bitlevel != 0) && (hw->first_i_frame_ready)) { - u32 bitcnt = READ_VREG(VIFF_BIT_CNT); - if (bitcnt > frmbase_cont_bitlevel) { - hw->dec_result = DEC_RESULT_UNFINISH; - hw->chunk_offset += - (hw->chunk_size - (bitcnt >> 3) - VDEC_FIFO_ALIGN); - hw->chunk_size = (bitcnt >> 3); - hw->chunk_frame_count++; - hw->unstable_pts = 1; + u32 consume_byte, res_byte, bitcnt; + + bitcnt = READ_VREG(VIFF_BIT_CNT); + res_byte = bitcnt >> 3; + + if (hw->chunk_size > res_byte) { + if (bitcnt > frmbase_cont_bitlevel) { + consume_byte = hw->chunk_size - res_byte; + + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "%s, size %d, consume %d, res %d\n", __func__, + hw->chunk_size, consume_byte, res_byte); + + if (consume_byte > VDEC_FIFO_ALIGN) { + consume_byte -= VDEC_FIFO_ALIGN; + res_byte += VDEC_FIFO_ALIGN; + } + hw->chunk_offset += consume_byte; + hw->chunk_size = res_byte; + hw->dec_result = DEC_RESULT_UNFINISH; + hw->chunk_frame_count++; + hw->unstable_pts = 1; + } else { + hw->chunk_size = 0; + hw->chunk_offset = 0; + } } else { + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "error: bitbyte %d hw->chunk_size %d\n", res_byte, hw->chunk_size); hw->chunk_size = 0; hw->chunk_offset = 0; } @@ -1073,6 +1257,40 @@ static void flush_output(struct vdec_mpeg4_hw_s * hw) } } +static int notify_v4l_eos(struct vdec_s *vdec) +{ + struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; + struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + struct vframe_s *vf = NULL; + struct vdec_v4l2_buffer *fb = NULL; + + if (hw->is_used_v4l && hw->eos) { + if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) { + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "%s fatal error, no available buffer slot.\n", + __func__); + return -1; + } + + if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) { + pr_err("[%d] get fb fail.\n", ctx->id); + return -1; + } + + vf->timestamp = ULONG_MAX; + vf->v4l_mem_handle = (unsigned long)fb; + vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; + + kfifo_put(&hw->display_q, (const struct vframe_s *)vf); + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + + pr_info("[%d] mpeg4 EOS notify.\n", ctx->id); + } + + return 0; +} + static void vmpeg4_work(struct work_struct *work) { struct vdec_mpeg4_hw_s *hw = @@ -1127,6 +1345,10 @@ static void vmpeg4_work(struct work_struct *work) hw->chunk = NULL; vdec_clean_input(vdec); flush_output(hw); + + if (hw->is_used_v4l) + notify_v4l_eos(vdec); + mmpeg4_debug_print(DECODE_ID(hw), 0, "%s: eos flushed, frame_num %d\n", __func__, hw->frame_num); @@ -1256,55 +1478,61 @@ static int vmpeg4_canvas_init(struct vdec_mpeg4_hw_s *hw) canvas_height = 576; decbuf_y_size = 0x80000; decbuf_size = 0x100000; + } else { + int w = 1920; + int h = 1088; + int align_w, align_h; + int max, min; + + align_w = ALIGN(w, 64); + align_h = ALIGN(h, 64); + if (align_w > align_h) { + max = align_w; + min = align_h; } else { - int w = 1920; - int h = 1088; - int align_w, align_h; - int max, min; - - align_w = ALIGN(w, 64); - align_h = ALIGN(h, 64); - if (align_w > align_h) { - max = align_w; - min = align_h; + max = align_h; + min = align_w; + } + /* HD & SD */ + if ((max > 1920 || min > 1088) && + ALIGN(align_w * align_h * 3/2, SZ_64K) * 9 <= + buf_size) { + canvas_width = align_w; + canvas_height = align_h; + decbuf_y_size = + ALIGN(align_w * align_h, SZ_64K); + decbuf_size = + ALIGN(align_w * align_h * 3/2, SZ_64K); + } else { /*1080p*/ + if (h > w) { + canvas_width = 1088; + canvas_height = 1920; } else { - max = align_h; - min = align_w; - } - /* HD & SD */ - if ((max > 1920 || min > 1088) && - ALIGN(align_w * align_h * 3/2, SZ_64K) * 9 <= - buf_size) { - canvas_width = align_w; - canvas_height = align_h; - decbuf_y_size = - ALIGN(align_w * align_h, SZ_64K); - decbuf_size = - ALIGN(align_w * align_h * 3/2, SZ_64K); - } else { /*1080p*/ - if (h > w) { - canvas_width = 1088; - canvas_height = 1920; - } else { - canvas_width = 1920; - canvas_height = 1088; - } - decbuf_y_size = 0x200000; - decbuf_size = 0x300000; + canvas_width = 1920; + canvas_height = 1088; } + decbuf_y_size = 0x200000; + decbuf_size = 0x300000; } + } for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) { unsigned canvas; + if (i == (MAX_BMMU_BUFFER_NUM - 1)) decbuf_size = WORKSPACE_SIZE; - ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i, - decbuf_size, DRIVER_NAME, &decbuf_start); - if (ret < 0) { - pr_err("mmu alloc failed! size 0x%d idx %d\n", - decbuf_size, i); - return ret; + + if (hw->is_used_v4l && !(i == (MAX_BMMU_BUFFER_NUM - 1))) { + continue; + } else { + ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i, + decbuf_size, DRIVER_NAME, &decbuf_start); + if (ret < 0) { + pr_err("mmu alloc failed! size %d idx %d\n", + decbuf_size, i); + return ret; + } } if (i == (MAX_BMMU_BUFFER_NUM - 1)) { @@ -1358,6 +1586,7 @@ static int vmpeg4_canvas_init(struct vdec_mpeg4_hw_s *hw) return 0; } + static void vmpeg4_dump_state(struct vdec_s *vdec) { struct vdec_mpeg4_hw_s *hw = @@ -1557,19 +1786,21 @@ static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw) int index, i; void *workspace_buf = NULL; - index = find_buffer(hw); - if (index >= DECODE_BUFFER_NUM_MAX) + index = find_free_buffer(hw); + if (index < 0) return -1; if (!hw->init_flag) { if (vmpeg4_canvas_init(hw) < 0) return -1; } else { - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { - canvas_config_config(canvas_y(hw->canvas_spec[i]), - &hw->canvas_config[i][0]); - canvas_config_config(canvas_u(hw->canvas_spec[i]), - &hw->canvas_config[i][1]); + if (!hw->is_used_v4l) { + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + canvas_config_config(canvas_y(hw->canvas_spec[i]), + &hw->canvas_config[i][0]); + canvas_config_config(canvas_u(hw->canvas_spec[i]), + &hw->canvas_config[i][1]); + } } } /* prepare REF0 & REF1 @@ -1794,7 +2025,6 @@ static s32 vmmpeg4_init(struct vdec_mpeg4_hw_s *hw) static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) { - int index; struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; if (hw->eos) @@ -1815,11 +2045,11 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) } } - index = find_buffer(hw); - if (index >= DECODE_BUFFER_NUM_MAX) { + if (!is_enough_free_buffer(hw)) { hw->buffer_not_ready++; return 0; } + hw->not_run_ready = 0; hw->buffer_not_ready = 0; if (vdec->parallel_dec == 1) @@ -2022,6 +2252,9 @@ static int ammvdec_mpeg4_probe(struct platform_device *pdev) } memset(hw, 0, sizeof(struct vdec_mpeg4_hw_s)); + /* the ctx from v4l2 driver. */ + hw->v4l2_ctx = pdata->private; + pdata->private = hw; pdata->dec_status = dec_status; /* pdata->set_trickmode = set_trickmode; */ @@ -2052,7 +2285,6 @@ static int ammvdec_mpeg4_probe(struct platform_device *pdev) hw->platform_dev = pdev; hw->blkmode = pdata->canvas_mode; - if (pdata->sys_info) { hw->vmpeg4_amstream_dec_info = *pdata->sys_info; if ((hw->vmpeg4_amstream_dec_info.height != 0) && @@ -2071,6 +2303,8 @@ static int ammvdec_mpeg4_probe(struct platform_device *pdev) hw->vmpeg4_amstream_dec_info.width, hw->vmpeg4_amstream_dec_info.height, hw->vmpeg4_amstream_dec_info.rate); + hw->is_used_v4l = (((unsigned long) + hw->vmpeg4_amstream_dec_info.param & 0x80) >> 7); } if (vmmpeg4_init(hw) < 0) { @@ -2083,6 +2317,7 @@ static int ammvdec_mpeg4_probe(struct platform_device *pdev) pdata->dec_status = NULL; return -ENODEV; } + if (pdata->parallel_dec == 1) vdec_core_request(pdata, CORE_MASK_VDEC_1); else { @@ -2092,7 +2327,6 @@ static int ammvdec_mpeg4_probe(struct platform_device *pdev) mmpeg4_debug_print(DECODE_ID(hw), 0, "%s end.\n", __func__); - return 0; } @@ -2216,6 +2450,10 @@ MODULE_PARM_DESC(pre_decode_buf_level, module_param(udebug_flag, uint, 0664); MODULE_PARM_DESC(udebug_flag, "\n ammvdec_mpeg4 udebug_flag\n"); + +module_param(without_display_mode, uint, 0664); +MODULE_PARM_DESC(without_display_mode, "\n ammvdec_mpeg4 without_display_mode\n"); + module_init(ammvdec_mpeg4_driver_init_module); module_exit(ammvdec_mpeg4_driver_remove_module); diff --git a/drivers/frame_provider/decoder/utils/Makefile b/drivers/frame_provider/decoder/utils/Makefile index ee7dbf4..07edbe3 100644 --- a/drivers/frame_provider/decoder/utils/Makefile +++ b/drivers/frame_provider/decoder/utils/Makefile @@ -4,4 +4,5 @@ decoder_common-objs += decoder_mmu_box.o decoder_bmmu_box.o decoder_common-objs += config_parser.o secprot.o vdec_profile.o decoder_common-objs += amstream_profile.o decoder_common-objs += frame_check.o amlogic_fbc_hook.o +decoder_common-objs += vdec_v4l2_buffer_ops.o diff --git a/drivers/frame_provider/decoder/utils/vdec.c b/drivers/frame_provider/decoder/utils/vdec.c index 44f0934..54f9051 100644 --- a/drivers/frame_provider/decoder/utils/vdec.c +++ b/drivers/frame_provider/decoder/utils/vdec.c @@ -2544,8 +2544,10 @@ static irqreturn_t vdec_isr(int irq, void *dev_id) vdec = NULL; } - if (vdec) + if (vdec) { atomic_set(&vdec->inirq_flag, 1); + vdec->isr_ns = local_clock(); + } if (c->dev_isr) { ret = c->dev_isr(irq, c->dev_id); goto isr_done; @@ -2598,8 +2600,15 @@ static irqreturn_t vdec_thread_isr(int irq, void *dev_id) vdec = NULL; } - if (vdec) + if (vdec) { + u32 isr2tfn = 0; atomic_set(&vdec->inirq_thread_flag, 1); + vdec->tfn_ns = local_clock(); + isr2tfn = vdec->tfn_ns - vdec->isr_ns; + if (isr2tfn > 10000000) + pr_err("!!!!!!! %s vdec_isr to %s took %uns !!!\n", + vdec->vf_provider_name, __func__, isr2tfn); + } if (c->dev_threaded_isr) { ret = c->dev_threaded_isr(irq, c->dev_id); goto thread_isr_done; diff --git a/drivers/frame_provider/decoder/utils/vdec.h b/drivers/frame_provider/decoder/utils/vdec.h index 18d7cd1..80fa8dc 100644 --- a/drivers/frame_provider/decoder/utils/vdec.h +++ b/drivers/frame_provider/decoder/utils/vdec.h @@ -262,6 +262,8 @@ struct vdec_s { atomic_t inirq_thread_flag; atomic_t inirq_flag; int parallel_dec; + volatile u64 isr_ns; + volatile u64 tfn_ns; }; /* common decoder vframe provider name to use default vfm path */ diff --git a/drivers/frame_provider/decoder/utils/vdec_input.c b/drivers/frame_provider/decoder/utils/vdec_input.c index d819885..74bbaa7 100644 --- a/drivers/frame_provider/decoder/utils/vdec_input.c +++ b/drivers/frame_provider/decoder/utils/vdec_input.c @@ -58,6 +58,18 @@ static struct vframe_block_list_s * ulong phy_addr, int size); +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 copy_from_user_to_phyaddr(void *virts, const char __user *buf, u32 size, ulong phys, u32 pading, bool is_mapped) { @@ -68,7 +80,7 @@ static int copy_from_user_to_phyaddr(void *virts, const char __user *buf, u8 *p = virts; if (is_mapped) { - if (copy_from_user(p, buf, size)) + if (aml_copy_from_user(p, buf, size)) return -EFAULT; if (pading) @@ -85,7 +97,7 @@ static int copy_from_user_to_phyaddr(void *virts, const char __user *buf, if (!p) return -1; - if (copy_from_user(p, buf + i * span, span)) { + if (aml_copy_from_user(p, buf + i * span, span)) { codec_mm_unmap_phyaddr(p); return -EFAULT; } @@ -103,7 +115,7 @@ static int copy_from_user_to_phyaddr(void *virts, const char __user *buf, if (!p) return -1; - if (copy_from_user(p, buf + span, remain)) { + if (aml_copy_from_user(p, buf + span, remain)) { codec_mm_unmap_phyaddr(p); return -EFAULT; } @@ -753,7 +765,6 @@ int vdec_input_add_chunk(struct vdec_input_s *input, const char *buf, struct vframe_chunk_s *chunk; struct vdec_s *vdec = input->vdec; struct vframe_block_list_s *block; - int need_pading_size = MIN_FRAME_PADDING_SIZE; if (vdec_secure(vdec)) { @@ -998,11 +1009,26 @@ EXPORT_SYMBOL(vdec_input_next_input_chunk); void vdec_input_release_chunk(struct vdec_input_s *input, struct vframe_chunk_s *chunk) { + struct vframe_chunk_s *p; + u32 chunk_valid = 0; unsigned long flags; struct vframe_block_list_s *block = chunk->block; struct vframe_block_list_s *tofreeblock = NULL; flags = vdec_input_lock(input); + list_for_each_entry(p, &input->vframe_chunk_list, list) { + if (p == chunk) { + chunk_valid = 1; + break; + } + } + /* 2 threads go here, the other done the deletion,so return*/ + if (chunk_valid == 0) { + vdec_input_unlock(input, flags); + pr_err("%s chunk is deleted,so return.\n", __func__); + return; + } + list_del(&chunk->list); input->have_frame_num--; ATRACE_COUNTER(MEM_NAME, input->have_frame_num); diff --git a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c new file mode 100644 index 0000000..763d62e --- a/dev/null +++ b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c @@ -0,0 +1,131 @@ +#include <linux/file.h> +#include <linux/anon_inodes.h> +#include "vdec_v4l2_buffer_ops.h" + +const struct file_operations v4l2_file_fops = {}; + +static int is_v4l2_buf_file(struct file *file) +{ + return file->f_op == &v4l2_file_fops; +} + +static int vdec_v4l_alloc_fd(void) +{ + int fd; + struct file *file = NULL; + + fd = get_unused_fd_flags(O_CLOEXEC); + if (fd < 0) { + pr_err("v4l: get unused fd fail\n"); + return fd; + } + + file = anon_inode_getfile("v4l2_meta_file", &v4l2_file_fops, NULL, 0); + if (IS_ERR(file)) { + put_unused_fd(fd); + pr_err("v4l: get file faill\n"); + return PTR_ERR(file); + } + + fd_install(fd, file); + + pr_info("v4l: fd %d, file %p, data %p\n", + fd, file, file->private_data); + + return fd; +} + +static int vdec_v4l_fd_install_data(int fd, void *data) +{ + struct file *file; + + file = fget(fd); + + if (!file) { + pr_info("v4l: fget fd %d fail!, comm %s, pid %d\n", + fd, current->comm, current->pid); + return -EBADF; + } + + if (!is_v4l2_buf_file(file)) { + pr_info("v4l: v4l2 check fd fail!\n"); + return -EBADF; + } + + file->private_data = data; + + return 0; +} + +int vdec_v4l_binding_fd_and_vf(ulong v4l_handle, void *vf) +{ + int ret = 0, fd = -1; + struct vdec_v4l2_buffer *v4l_buf = + (struct vdec_v4l2_buffer *) v4l_handle; + + if (v4l_buf->m.vf_fd > 0) + return 0; + + fd = vdec_v4l_alloc_fd(); + if (fd < 0) { + pr_err("v4l: alloc fd fail %d.\n", fd); + return fd; + } + + ret = vdec_v4l_fd_install_data(fd, vf); + if (ret < 0) { + put_unused_fd(fd); + pr_err("v4l: fd install data fail %d.\n", ret); + return ret; + } + + v4l_buf->m.vf_fd = fd; + + return 0; +} +EXPORT_SYMBOL(vdec_v4l_binding_fd_and_vf); + +int vdec_v4l_get_buffer(struct aml_vcodec_ctx *ctx, + struct vdec_v4l2_buffer **out) +{ + int ret = 0; + + if (ctx->drv_handle == 0) + return -EIO; + + ret = ctx->dec_if->get_param(ctx->drv_handle, + GET_PARAM_FREE_FRAME_BUFFER, out); + + return ret; +} +EXPORT_SYMBOL(vdec_v4l_get_buffer); + +int vdec_v4l_set_pic_infos(struct aml_vcodec_ctx *ctx, + struct aml_vdec_pic_infos *info) +{ + int ret = 0; + + if (ctx->drv_handle == 0) + return -EIO; + + ret = ctx->dec_if->set_param(ctx->drv_handle, + SET_PARAM_PIC_INFO, info); + + return ret; +} +EXPORT_SYMBOL(vdec_v4l_set_pic_infos); + +int vdec_v4l_write_frame_sync(struct aml_vcodec_ctx *ctx) +{ + int ret = 0; + + if (ctx->drv_handle == 0) + return -EIO; + + ret = ctx->dec_if->set_param(ctx->drv_handle, + SET_PARAM_WRITE_FRAME_SYNC, NULL); + + return ret; +} +EXPORT_SYMBOL(vdec_v4l_write_frame_sync); + diff --git a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h new file mode 100644 index 0000000..6227a8b --- a/dev/null +++ b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h @@ -0,0 +1,22 @@ +#ifndef _AML_VDEC_V4L2_BUFFER_H_ +#define _AML_VDEC_V4L2_BUFFER_H_ + +#include "../../../amvdec_ports/vdec_drv_base.h" +#include "../../../amvdec_ports/aml_vcodec_adapt.h" + +int vdec_v4l_get_buffer( + struct aml_vcodec_ctx *ctx, + struct vdec_v4l2_buffer **out); + +int vdec_v4l_set_pic_infos( + struct aml_vcodec_ctx *ctx, + struct aml_vdec_pic_infos *info); + +int vdec_v4l_write_frame_sync( + struct aml_vcodec_ctx *ctx); + +int vdec_v4l_binding_fd_and_vf( + ulong v4l_handle, + void *vf); + +#endif diff --git a/drivers/frame_provider/decoder/vp9/vvp9.c b/drivers/frame_provider/decoder/vp9/vvp9.c index b0dd586..076d00d 100644 --- a/drivers/frame_provider/decoder/vp9/vvp9.c +++ b/drivers/frame_provider/decoder/vp9/vvp9.c @@ -57,9 +57,7 @@ #include "../utils/config_parser.h" #include "../utils/firmware.h" #include "../../../common/chips/decoder_cpu_ver_info.h" -#include "../../../amvdec_ports/vdec_drv_base.h" - - +#include "../utils/vdec_v4l2_buffer_ops.h" #define MIX_STREAM_SUPPORT @@ -149,7 +147,6 @@ #ifdef MULTI_INSTANCE_SUPPORT #define MAX_DECODE_INSTANCE_NUM 9 #define MULTI_DRIVER_NAME "ammvdec_vp9" - static unsigned int max_decode_instance_num = MAX_DECODE_INSTANCE_NUM; static unsigned int decode_frame_count[MAX_DECODE_INSTANCE_NUM]; @@ -393,6 +390,8 @@ static u32 udebug_pause_val; static u32 udebug_pause_decode_idx; +static u32 without_display_mode; + #define DEBUG_REG #ifdef DEBUG_REG void WRITE_VREG_DBG2(unsigned int adr, unsigned int val) @@ -515,6 +514,7 @@ struct PIC_BUFFER_CONFIG_s { int stream_offset; u32 pts; u64 pts64; + u64 timestamp; uint8_t error_mark; /**/ int slice_idx; @@ -926,7 +926,6 @@ struct BuffInfo_s { struct buff_s rpm; struct buff_s lmem; } BuffInfo_t; - #ifdef MULTI_INSTANCE_SUPPORT #define DEC_RESULT_NONE 0 #define DEC_RESULT_DONE 1 @@ -939,6 +938,7 @@ struct BuffInfo_s { #define DEC_RESULT_GET_DATA_RETRY 8 #define DEC_RESULT_EOS 9 #define DEC_RESULT_FORCE_EXIT 10 +#define DEC_V4L2_CONTINUE_DECODING 18 #define DEC_S1_RESULT_NONE 0 #define DEC_S1_RESULT_DONE 1 @@ -1179,8 +1179,10 @@ struct VP9Decoder_s { bool pic_list_init_done2; bool is_used_v4l; void *v4l2_ctx; + bool v4l_params_parsed; int frameinfo_enable; struct vframe_qos_s vframe_qos; + u32 mem_map_mode; }; static int vp9_print(struct VP9Decoder_s *pbi, @@ -1219,15 +1221,8 @@ static int is_oversize(int w, int h) return false; } -static int v4l_get_fb(struct aml_vcodec_ctx *ctx, struct vdec_fb **out) -{ - int ret = 0; - - ret = ctx->dec_if->get_param(ctx->drv_handle, - GET_PARAM_FREE_FRAME_BUFFER, out); - - return ret; -} +static int config_pic(struct VP9Decoder_s *pbi, + struct PIC_BUFFER_CONFIG_s *pic_config); static void resize_context_buffers(struct VP9Decoder_s *pbi, struct VP9_Common_s *cm, int width, int height) @@ -1238,10 +1233,30 @@ static void resize_context_buffers(struct VP9Decoder_s *pbi, pbi->vp9_first_pts_ready = 0; pbi->duration_from_pts_done = 0; } - cm->width = width; - cm->height = height; pr_info("%s (%d,%d)=>(%d,%d)\r\n", __func__, cm->width, cm->height, width, height); + + if (pbi->is_used_v4l) { + struct PIC_BUFFER_CONFIG_s *pic = &cm->cur_frame->buf; + + /* resolution change happend need to reconfig buffs if true. */ + if (pic->y_crop_width != width || pic->y_crop_height != height) { + int i; + for (i = 0; i < pbi->used_buf_num; i++) { + pic = &cm->buffer_pool->frame_bufs[i].buf; + pic->y_crop_width = width; + pic->y_crop_height = height; + if (!config_pic(pbi, pic)) + set_canvas(pbi, pic); + else + vp9_print(pbi, 0, + "v4l: reconfig buff fail.\n"); + } + } + } + + cm->width = width; + cm->height = height; } /* *if (cm->cur_frame->mvs == NULL || @@ -1337,6 +1352,9 @@ static int setup_frame_size( #else /* porting */ ybf = get_frame_new_buffer(cm); + if (!ybf) + return -1; + ybf->y_crop_width = width; ybf->y_crop_height = height; ybf->bit_depth = params->p.bit_depth; @@ -1491,6 +1509,9 @@ static int setup_frame_size_with_refs( #else /* porting */ ybf = get_frame_new_buffer(cm); + if (!ybf) + return -1; + ybf->y_crop_width = width; ybf->y_crop_height = height; ybf->bit_depth = params->p.bit_depth; @@ -1530,6 +1551,15 @@ static int vp9_print_cont(struct VP9Decoder_s *pbi, static void trigger_schedule(struct VP9Decoder_s *pbi) { + if (pbi->is_used_v4l) { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(pbi->v4l2_ctx); + + if (ctx->param_sets_from_ucode && + !pbi->v4l_params_parsed) + vdec_v4l_write_frame_sync(ctx); + } + if (pbi->vdec_cb) pbi->vdec_cb(hw_to_vdec(pbi), pbi->vdec_cb_arg); } @@ -2112,11 +2142,13 @@ static void fb_reset_core(struct vdec_s *vdec, u32 mask) #endif +static void init_pic_list_hw(struct VP9Decoder_s *pbi); static int get_free_fb(struct VP9Decoder_s *pbi) { struct VP9_Common_s *const cm = &pbi->common; struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; + struct PIC_BUFFER_CONFIG_s *pic = NULL; int i; unsigned long flags; @@ -2130,11 +2162,21 @@ static int get_free_fb(struct VP9Decoder_s *pbi) } } for (i = 0; i < pbi->used_buf_num; ++i) { + pic = &frame_bufs[i].buf; if ((frame_bufs[i].ref_count == 0) && - (frame_bufs[i].buf.vf_ref == 0) && - (frame_bufs[i].buf.index != -1) - ) + (pic->vf_ref == 0) && (pic->index != -1)) { + if (pbi->is_used_v4l && !pic->cma_alloc_addr) { + pic->y_crop_width = pbi->frame_width; + pic->y_crop_height = pbi->frame_height; + if (!config_pic(pbi, pic)) { + set_canvas(pbi, pic); + init_pic_list_hw(pbi); + } else + i = pbi->used_buf_num; + } + break; + } } if (i != pbi->used_buf_num) { frame_bufs[i].ref_count = 1; @@ -2276,6 +2318,7 @@ int vp9_bufmgr_process(struct VP9Decoder_s *pbi, union param_u *params) struct VP9_Common_s *const cm = &pbi->common; struct BufferPool_s *pool = cm->buffer_pool; struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs; + struct PIC_BUFFER_CONFIG_s *pic = NULL; int i; int ret; @@ -2539,9 +2582,13 @@ int vp9_bufmgr_process(struct VP9Decoder_s *pbi, union param_u *params) } } - get_frame_new_buffer(cm)->bit_depth = cm->bit_depth; - get_frame_new_buffer(cm)->color_space = cm->color_space; - get_frame_new_buffer(cm)->slice_type = cm->frame_type; + pic = get_frame_new_buffer(cm); + if (!pic) + return -1; + + pic->bit_depth = cm->bit_depth; + pic->color_space = cm->color_space; + pic->slice_type = cm->frame_type; if (pbi->need_resync) { pr_err @@ -2598,14 +2645,16 @@ void swap_frame_buffers(struct VP9Decoder_s *pbi) pbi->hold_ref_buf = 0; cm->frame_to_show = get_frame_new_buffer(cm); - /*if (!pbi->frame_parallel_decode || !cm->show_frame) {*/ - lock_buffer_pool(pool, flags); - --frame_bufs[cm->new_fb_idx].ref_count; - /*pr_info("[MMU DEBUG 8] dec ref_count[%d] : %d\r\n", cm->new_fb_idx, - * frame_bufs[cm->new_fb_idx].ref_count); - */ - unlock_buffer_pool(pool, flags); - /*}*/ + if (cm->frame_to_show) { + /*if (!pbi->frame_parallel_decode || !cm->show_frame) {*/ + lock_buffer_pool(pool, flags); + --frame_bufs[cm->new_fb_idx].ref_count; + /*pr_info("[MMU DEBUG 8] dec ref_count[%d] : %d\r\n", cm->new_fb_idx, + * frame_bufs[cm->new_fb_idx].ref_count); + */ + unlock_buffer_pool(pool, flags); + /*}*/ + } /*Invalidate these references until the next frame starts.*/ for (ref_index = 0; ref_index < 3; ref_index++) @@ -2637,6 +2686,10 @@ int vp9_get_raw_frame(struct VP9Decoder_s *pbi, struct PIC_BUFFER_CONFIG_s *sd) if (!cm->show_frame) return ret; + /* may not be get buff in v4l2 */ + if (!cm->frame_to_show) + return ret; + pbi->ready_for_new_data = 1; *sd = *cm->frame_to_show; @@ -2704,7 +2757,6 @@ int vp9_bufmgr_init(struct VP9Decoder_s *pbi, struct BuffInfo_s *buf_spec_i, return 0; } - int vp9_bufmgr_postproc(struct VP9Decoder_s *pbi) { struct VP9_Common_s *cm = &pbi->common; @@ -4617,8 +4669,8 @@ static int config_pic(struct VP9Decoder_s *pbi, { int ret = -1; int i; - int pic_width = pbi->init_pic_w; - int pic_height = pbi->init_pic_h; + int pic_width = pbi->is_used_v4l ? pbi->frame_width : pbi->init_pic_w; + int pic_height = pbi->is_used_v4l ? pbi->frame_height : pbi->init_pic_h; int lcu_size = 64; /*fixed 64*/ int pic_width_64 = (pic_width + 63) & (~0x3f); int pic_height_32 = (pic_height + 31) & (~0x1f); @@ -4646,7 +4698,9 @@ static int config_pic(struct VP9Decoder_s *pbi, int mc_buffer_size_u_v = 0; int mc_buffer_size_u_v_h = 0; int dw_mode = get_double_write_mode_init(pbi); - struct vdec_fb *fb = NULL; + int pic_width_align = 0; + int pic_height_align = 0; + struct vdec_v4l2_buffer *fb = NULL; pbi->lcu_total = lcu_total; @@ -4670,6 +4724,11 @@ static int config_pic(struct VP9Decoder_s *pbi, /*64k alignment*/ buf_size = ((mc_buffer_size_u_v_h << 16) * 3); buf_size = ((buf_size + 0xffff) >> 16) << 16; + + if (pbi->is_used_v4l) { + pic_width_align = ALIGN(pic_width_dw, 32); + pic_height_align = ALIGN(pic_height_dw, 32); + } } if (mc_buffer_size & 0xffff) /*64k alignment*/ @@ -4677,7 +4736,6 @@ static int config_pic(struct VP9Decoder_s *pbi, if ((!pbi->mmu_enable) && ((dw_mode & 0x10) == 0)) buf_size += (mc_buffer_size_h << 16); - if (pbi->mmu_enable) { pic_config->header_adr = decoder_bmmu_box_get_phy_addr( pbi->bmmu_box, HEADER_BUFFER_IDX(pic_config->index)); @@ -4697,9 +4755,9 @@ static int config_pic(struct VP9Decoder_s *pbi, #endif if (buf_size > 0) { if (pbi->is_used_v4l) { - ret = v4l_get_fb(pbi->v4l2_ctx, &fb); + ret = vdec_v4l_get_buffer(pbi->v4l2_ctx, &fb); if (ret) { - vp9_print(pbi, PRINT_FLAG_ERROR, + vp9_print(pbi, PRINT_FLAG_V4L_DETAIL, "[%d] get fb fail.\n", ((struct aml_vcodec_ctx *) (pbi->v4l2_ctx))->id); @@ -4707,8 +4765,7 @@ static int config_pic(struct VP9Decoder_s *pbi, } pbi->m_BUF[i].v4l_ref_buf_addr = (ulong)fb; - pic_config->cma_alloc_addr = - virt_to_phys(fb->base_y.va); + pic_config->cma_alloc_addr = fb->m.mem[0].addr; vp9_print(pbi, PRINT_FLAG_V4L_DETAIL, "[%d] %s(), v4l ref buf addr: 0x%x\n", ((struct aml_vcodec_ctx *) @@ -4751,9 +4808,27 @@ static int config_pic(struct VP9Decoder_s *pbi, pic_config->mc_canvas_y = pic_config->index; pic_config->mc_canvas_u_v = pic_config->index; if (dw_mode & 0x10) { - pic_config->dw_y_adr = y_adr; - pic_config->dw_u_v_adr = y_adr + - ((mc_buffer_size_u_v_h << 16) << 1); + if (pbi->is_used_v4l) { + if (fb->num_planes == 1) { + fb->m.mem[0].bytes_used = + pic_width_align * pic_height_align; + pic_config->dw_y_adr = y_adr; + pic_config->dw_u_v_adr = y_adr + + fb->m.mem[0].bytes_used; + } else if (fb->num_planes == 2) { + fb->m.mem[0].bytes_used = + pic_width_align * pic_height_align; + fb->m.mem[1].bytes_used = + fb->m.mem[1].size; + pic_config->dw_y_adr = y_adr; + pic_config->dw_u_v_adr = y_adr + + fb->m.mem[0].bytes_used; + } + } else { + pic_config->dw_y_adr = y_adr; + pic_config->dw_u_v_adr = y_adr + + ((mc_buffer_size_u_v_h << 16) << 1); + } pic_config->mc_canvas_y = (pic_config->index << 1); @@ -4813,7 +4888,6 @@ static int vvp9_frame_mmu_map_size(struct VP9Decoder_s *pbi) return (MAX_FRAME_4K_NUM * 4); } - static void init_pic_list(struct VP9Decoder_s *pbi) { int i; @@ -4848,19 +4922,22 @@ static void init_pic_list(struct VP9Decoder_s *pbi) pic_config->y_canvas_index = -1; pic_config->uv_canvas_index = -1; } - if (config_pic(pbi, pic_config) < 0) { - if (debug) - pr_info("Config_pic %d fail\n", - pic_config->index); - pic_config->index = -1; - break; - } pic_config->y_crop_width = pbi->init_pic_w; pic_config->y_crop_height = pbi->init_pic_h; pic_config->double_write_mode = get_double_write_mode(pbi); - if (pic_config->double_write_mode) { - set_canvas(pbi, pic_config); + if (!pbi->is_used_v4l) { + if (config_pic(pbi, pic_config) < 0) { + if (debug) + pr_info("Config_pic %d fail\n", + pic_config->index); + pic_config->index = -1; + break; + } + + if (pic_config->double_write_mode) { + set_canvas(pbi, pic_config); + } } } for (; i < pbi->used_buf_num; i++) { @@ -4875,7 +4952,6 @@ static void init_pic_list(struct VP9Decoder_s *pbi) } pr_info("%s ok, used_buf_num = %d\n", __func__, pbi->used_buf_num); - } static void init_pic_list_hw(struct VP9Decoder_s *pbi) @@ -5149,7 +5225,7 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) pic_config->lcu_total * lcu_size*lcu_size/2; int mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16;/*64k alignment*/ - + struct aml_vcodec_ctx * v4l2_ctx = pbi->v4l2_ctx; if (get_double_write_mode(pbi)) { WRITE_VREG(HEVC_SAO_Y_START_ADDR, pic_config->dw_y_adr); @@ -5177,7 +5253,7 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) data32 = READ_VREG(HEVC_SAO_CTRL1); data32 &= (~0x3000); /*[13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32*/ - data32 |= (mem_map_mode << 12); + data32 |= (pbi->mem_map_mode << 12); data32 &= (~0x3); data32 |= 0x1; /* [1]:dw_disable [0]:cm_disable*/ WRITE_VREG(HEVC_SAO_CTRL1, data32); @@ -5191,14 +5267,14 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); data32 &= (~0x30); /*[5:4] address_format 00:linear 01:32x32 10:64x32*/ - data32 |= (mem_map_mode << 4); + data32 |= (pbi->mem_map_mode << 4); WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); #else /*m8baby test1902*/ data32 = READ_VREG(HEVC_SAO_CTRL1); data32 &= (~0x3000); /*[13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32*/ - data32 |= (mem_map_mode << 12); + data32 |= (pbi->mem_map_mode << 12); data32 &= (~0xff0); /*data32 |= 0x670;*/ /*Big-Endian per 64-bit*/ data32 |= 0x880; /*.Big-Endian per 64-bit */ @@ -5216,7 +5292,7 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); data32 &= (~0x30); /*[5:4] address_format 00:linear 01:32x32 10:64x32*/ - data32 |= (mem_map_mode << 4); + data32 |= (pbi->mem_map_mode << 4); data32 &= (~0xF); data32 |= 0x8; /*Big-Endian per 64-bit*/ WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); @@ -5224,7 +5300,7 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) #else data32 = READ_VREG(HEVC_SAO_CTRL1); data32 &= (~0x3000); - data32 |= (mem_map_mode << + data32 |= (pbi->mem_map_mode << 12); /* [13:12] axi_aformat, 0-Linear, @@ -5251,6 +5327,28 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) data |= ((0x1 << 8) |(0x1 << 9)); WRITE_VREG(HEVC_DBLK_CFGB, data); } + + /* swap uv */ + if (pbi->is_used_v4l) { + if ((v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21) || + (v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21M)) + data32 &= ~(1 << 8); /* NV21 */ + else + data32 |= (1 << 8); /* NV12 */ + } + + /* + * [31:24] ar_fifo1_axi_thred + * [23:16] ar_fifo0_axi_thred + * [15:14] axi_linealign, 0-16bytes, 1-32bytes, 2-64bytes + * [13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32 + * [11:08] axi_lendian_C + * [07:04] axi_lendian_Y + * [3] reserved + * [2] clk_forceon + * [1] dw_disable:disable double write output + * [0] cm_disable:disable compress output + */ WRITE_VREG(HEVC_SAO_CTRL1, data32); if (get_double_write_mode(pbi) & 0x10) { @@ -5277,11 +5375,30 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); data32 &= (~0x30); /* [5:4] -- address_format 00:linear 01:32x32 10:64x32 */ - data32 |= (mem_map_mode << + data32 |= (pbi->mem_map_mode << 4); data32 &= (~0xF); data32 |= 0xf; /* valid only when double write only */ /*data32 |= 0x8;*/ /* Big-Endian per 64-bit */ + + /* swap uv */ + if (pbi->is_used_v4l) { + if ((v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21) || + (v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21M)) + data32 |= (1 << 12); /* NV21 */ + else + data32 &= ~(1 << 12); /* NV12 */ + } + + /* + * [3:0] little_endian + * [5:4] address_format 00:linear 01:32x32 10:64x32 + * [7:6] reserved + * [9:8] Linear_LineAlignment 00:16byte 01:32byte 10:64byte + * [11:10] reserved + * [12] CbCr_byte_swap + * [31:13] reserved + */ WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); #endif } @@ -6284,6 +6401,8 @@ static int vp9_local_init(struct VP9Decoder_s *pbi) pbi->vvp9_amstream_dec_info.height : pbi->work_space_buf->max_height)); + pbi->mem_map_mode = mem_map_mode ? mem_map_mode : 0; + /* video is not support unaligned with 64 in tl1 ** vdec canvas mode will be linear when dump yuv is set */ @@ -6293,9 +6412,9 @@ static int vp9_local_init(struct VP9Decoder_s *pbi) (pbi->vvp9_amstream_dec_info.width % 64) != 0)) { if (hw_to_vdec(pbi)->canvas_mode != CANVAS_BLKMODE_LINEAR) - mem_map_mode = 2; + pbi->mem_map_mode = 2; else { - mem_map_mode = 0; + pbi->mem_map_mode = 0; pr_info("vdec blkmod linear, force mem_map_mode 0\n"); } } @@ -6417,7 +6536,7 @@ static void set_canvas(struct VP9Decoder_s *pbi, struct vdec_s *vdec = hw_to_vdec(pbi); int canvas_w = ALIGN(pic_config->y_crop_width, 64)/4; int canvas_h = ALIGN(pic_config->y_crop_height, 32)/4; - int blkmode = mem_map_mode; + int blkmode = pbi->mem_map_mode; /*CANVAS_BLKMODE_64X32*/ if (pic_config->double_write_mode) { canvas_w = pic_config->y_crop_width / @@ -6427,7 +6546,7 @@ static void set_canvas(struct VP9Decoder_s *pbi, get_double_write_ratio(pbi, pic_config->double_write_mode); - if (mem_map_mode == 0) + if (pbi->mem_map_mode == 0) canvas_w = ALIGN(canvas_w, 32); else canvas_w = ALIGN(canvas_w, 64); @@ -6538,7 +6657,8 @@ static struct vframe_s *vvp9_vf_get(void *op_arg) if (kfifo_get(&pbi->display_q, &vf)) { struct vframe_s *next_vf; uint8_t index = vf->index & 0xff; - if (index < pbi->used_buf_num) { + if (index < pbi->used_buf_num || + (vf->type & VIDTYPE_V4L_EOS)) { pbi->vf_get_count++; if (debug & VP9_DEBUG_BUFMGR) pr_info("%s type 0x%x w/h %d/%d, pts %d, %lld\n", @@ -6743,6 +6863,13 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi, if (pbi->is_used_v4l) { vf->v4l_mem_handle = pbi->m_BUF[pic_config->BUF_index].v4l_ref_buf_addr; + if (pbi->mmu_enable) { + if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) { + vp9_print(pbi, PRINT_FLAG_V4L_DETAIL, + "v4l: binding vf fail.\n"); + return -1; + } + } vp9_print(pbi, PRINT_FLAG_V4L_DETAIL, "[%d] %s(), v4l mem handle: 0x%lx\n", ((struct aml_vcodec_ctx *)(pbi->v4l2_ctx))->id, @@ -6753,6 +6880,7 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi, if (vdec_frame_based(hw_to_vdec(pbi))) { vf->pts = pic_config->pts; vf->pts_us64 = pic_config->pts64; + vf->timestamp = pic_config->timestamp; if (vf->pts != 0 || vf->pts_us64 != 0) { pts_valid = 1; pts_us64_valid = 1; @@ -6977,8 +7105,11 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi, vdec_count_info(gvs, 0, stream_offset); #endif hw_to_vdec(pbi)->vdec_fps_detec(hw_to_vdec(pbi)->id); - vf_notify_receiver(pbi->provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + if (without_display_mode == 0) { + vf_notify_receiver(pbi->provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } else + vvp9_vf_put(vvp9_vf_get(pbi), pbi); } else { pbi->stat |= VP9_TRIGGER_FRAME_DONE; hevc_source_changed(VFORMAT_VP9, 196, 196, 30); @@ -6996,7 +7127,7 @@ static int notify_v4l_eos(struct vdec_s *vdec) struct VP9Decoder_s *hw = (struct VP9Decoder_s *)vdec->private; struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); struct vframe_s *vf = NULL; - struct vdec_fb *fb = NULL; + struct vdec_v4l2_buffer *fb = NULL; if (hw->is_used_v4l && hw->eos) { if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) { @@ -7006,11 +7137,12 @@ static int notify_v4l_eos(struct vdec_s *vdec) return -1; } - if (v4l_get_fb(hw->v4l2_ctx, &fb)) { + if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) { pr_err("[%d] get fb fail.\n", ctx->id); return -1; } + vf->type |= VIDTYPE_V4L_EOS; vf->timestamp = ULONG_MAX; vf->v4l_mem_handle = (unsigned long)fb; vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; @@ -7243,6 +7375,7 @@ int continue_decoding(struct VP9Decoder_s *pbi) if (pbi->chunk) { cur_pic_config->pts = pbi->chunk->pts; cur_pic_config->pts64 = pbi->chunk->pts64; + cur_pic_config->timestamp = pbi->chunk->timestamp; } #endif } @@ -8020,9 +8153,33 @@ static irqreturn_t vvp9_isr_thread_fn(int irq, void *data) } } - continue_decoding(pbi); - pbi->postproc_done = 0; - pbi->process_busy = 0; + if (pbi->is_used_v4l) { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(pbi->v4l2_ctx); + + pbi->frame_width = vp9_param.p.width; + pbi->frame_height = vp9_param.p.height; + if (ctx->param_sets_from_ucode && !pbi->v4l_params_parsed) { + struct aml_vdec_pic_infos info; + + info.visible_width = pbi->frame_width; + info.visible_height = pbi->frame_height; + info.coded_width = ALIGN(pbi->frame_width, 32); + info.coded_height = ALIGN(pbi->frame_height, 32); + info.dpb_size = pbi->used_buf_num; + pbi->v4l_params_parsed = true; + vdec_v4l_set_pic_infos(ctx, &info); + } + } + + if (pbi->is_used_v4l) { + pbi->dec_result = DEC_V4L2_CONTINUE_DECODING; + vdec_schedule_work(&pbi->work); + } else { + continue_decoding(pbi); + pbi->postproc_done = 0; + pbi->process_busy = 0; + } #ifdef MULTI_INSTANCE_SUPPORT if (pbi->m_ins_flag) @@ -9070,6 +9227,8 @@ static int amvdec_vp9_remove(struct platform_device *pdev) pr_info("pts missed %ld, pts hit %ld, duration %d\n", pbi->pts_missed, pbi->pts_hit, pbi->frame_dur); #endif + mem_map_mode = 0; + vfree(pbi); mutex_unlock(&vvp9_mutex); @@ -9200,6 +9359,25 @@ static void vp9_work(struct work_struct *work) return; } + if (pbi->dec_result == DEC_V4L2_CONTINUE_DECODING) { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(pbi->v4l2_ctx); + + if (ctx->param_sets_from_ucode) { + reset_process_time(pbi); + if (wait_event_interruptible_timeout(ctx->wq, + ctx->v4l_codec_ready, + msecs_to_jiffies(500)) < 0) + return; + } + + continue_decoding(pbi); + pbi->postproc_done = 0; + pbi->process_busy = 0; + + return; + } + if (((pbi->dec_result == DEC_RESULT_GET_DATA) || (pbi->dec_result == DEC_RESULT_GET_DATA_RETRY)) && (hw_to_vdec(pbi)->next_status != @@ -9406,6 +9584,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) size, (pbi->need_cache_size >> PAGE_SHIFT), (int)(get_jiffies_64() - pbi->sc_start_time) * 1000/HZ); } + #ifdef SUPPORT_FB_DECODING if (pbi->used_stage_buf_num > 0) { if (mask & CORE_MASK_HEVC_FRONT) { @@ -9461,7 +9640,18 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) ret = CORE_MASK_HEVC; else ret = CORE_MASK_VDEC_1 | CORE_MASK_HEVC; - } + } + + if (pbi->is_used_v4l) { + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *)(pbi->v4l2_ctx); + + if (ctx->param_sets_from_ucode && + !ctx->v4l_codec_ready && + pbi->v4l_params_parsed) + ret = 0; /*the params has parsed.*/ + } + if (ret) not_run_ready[pbi->index] = 0; else @@ -9764,15 +9954,58 @@ static void run(struct vdec_s *vdec, unsigned long mask, #endif } +static void init_frame_bufs(struct VP9Decoder_s *pbi) +{ + struct vdec_s *vdec = hw_to_vdec(pbi); + struct VP9_Common_s *const cm = &pbi->common; + struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs; + int i; + + for (i = 0; i < pbi->used_buf_num; ++i) { + frame_bufs[i].ref_count = 0; + frame_bufs[i].buf.vf_ref = 0; + frame_bufs[i].buf.decode_idx = 0; + } + + if (vdec->parallel_dec == 1) { + for (i = 0; i < FRAME_BUFFERS; i++) { + vdec->free_canvas_ex + (pbi->common.buffer_pool->frame_bufs[i].buf.y_canvas_index, + vdec->id); + vdec->free_canvas_ex + (pbi->common.buffer_pool->frame_bufs[i].buf.uv_canvas_index, + vdec->id); + } + } +} + static void reset(struct vdec_s *vdec) { struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)vdec->private; - vp9_print(pbi, - PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__); + cancel_work_sync(&pbi->work); + if (pbi->stat & STAT_VDEC_RUN) { + amhevc_stop(); + pbi->stat &= ~STAT_VDEC_RUN; + } + if (pbi->stat & STAT_TIMER_ARM) { + del_timer_sync(&pbi->timer); + pbi->stat &= ~STAT_TIMER_ARM; + } + pbi->dec_result = DEC_RESULT_NONE; + reset_process_time(pbi); + dealloc_mv_bufs(pbi); + vp9_local_uninit(pbi); + if (vvp9_local_init(pbi) < 0) + vp9_print(pbi, 0, "%s local_init failed \r\n", __func__); + init_frame_bufs(pbi); + + pbi->eos = 0; + + vp9_print(pbi, PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__); } static irqreturn_t vp9_irq_cb(struct vdec_s *vdec, int irq) @@ -10119,10 +10352,14 @@ static int ammvdec_vp9_probe(struct platform_device *pdev) pbi->is_used_v4l = (((unsigned long) pbi->vvp9_amstream_dec_info.param & 0x80) >> 7); if (pbi->is_used_v4l) { - pbi->double_write_mode = 0x10; - pbi->mmu_enable = 0; - pbi->max_pic_w = 1920; - pbi->max_pic_h = 1080; + pbi->mmu_enable = (((unsigned long) + pbi->vvp9_amstream_dec_info.param & 0x100) >> 8); + if (!pbi->mmu_enable) + pbi->double_write_mode = 0x10; + + pbi->mmu_enable = 1; + pbi->max_pic_w = 4096; + pbi->max_pic_h = 2304; } vp9_print(pbi, 0, @@ -10237,6 +10474,8 @@ static int ammvdec_vp9_remove(struct platform_device *pdev) pr_info("pts missed %ld, pts hit %ld, duration %d\n", pbi->pts_missed, pbi->pts_hit, pbi->frame_dur); #endif + mem_map_mode = 0; + /* devm_kfree(&pdev->dev, (void *)pbi); */ vfree((void *)pbi); return 0; @@ -10553,6 +10792,9 @@ MODULE_PARM_DESC(udebug_pause_val, "\n udebug_pause_val\n"); module_param(udebug_pause_decode_idx, uint, 0664); MODULE_PARM_DESC(udebug_pause_decode_idx, "\n udebug_pause_decode_idx\n"); +module_param(without_display_mode, uint, 0664); +MODULE_PARM_DESC(without_display_mode, "\n without_display_mode\n"); + module_init(amvdec_vp9_driver_init_module); module_exit(amvdec_vp9_driver_remove_module); diff --git a/drivers/frame_sink/encoder/h264/encoder.c b/drivers/frame_sink/encoder/h264/encoder.c index 1d2b96e..7b83dd2 100644 --- a/drivers/frame_sink/encoder/h264/encoder.c +++ b/drivers/frame_sink/encoder/h264/encoder.c @@ -94,6 +94,11 @@ static u32 no_timeout; static int nr_mode = -1; static u32 qp_table_debug; +#ifdef H264_ENC_SVC +static u32 svc_enable = 0; /* Enable sac feature or not */ +static u32 svc_ref_conf = 0; /* Continuous no reference numbers */ +#endif + static u32 me_mv_merge_ctl = (0x1 << 31) | /* [31] me_merge_mv_en_16 */ (0x1 << 30) | /* [30] me_merge_small_mv_en_16 */ @@ -1684,7 +1689,6 @@ static void avc_prot_init(struct encode_wq_s *wq, (wq->cbr_info.block_h << 0)); } #endif - WRITE_HREG(HCODEC_QDCT_VLC_QUANT_CTL_0, (0 << 19) | /* vlc_delta_quant_1 */ (i_pic_qp << 13) | /* vlc_quant_1 */ @@ -2278,7 +2282,6 @@ static void avc_prot_init(struct encode_wq_s *wq, (v3_left_small_max_ie_sad << 0)); } WRITE_HREG(HCODEC_IE_DATA_FEED_BUFF_INFO, 0); - WRITE_HREG(HCODEC_CURR_CANVAS_CTRL, 0); data32 = READ_HREG(HCODEC_VLC_CONFIG); data32 = data32 | (1 << 0); /* set pop_coeff_even_all_zero */ @@ -2814,11 +2817,32 @@ void amvenc_avc_start_cmd(struct encode_wq_s *wq, (request->cmd == ENCODER_IDR) ? true : false); avc_init_assit_buffer(wq); enc_pr(LOG_INFO, - "begin to new frame, request->cmd: %d, ucode mode: %d, wq:%p.\n", + "begin to new frame, request->cmd: %d, ucode mode: %d, wq:%p\n", request->cmd, request->ucode_mode, (void *)wq); } if ((request->cmd == ENCODER_IDR) || (request->cmd == ENCODER_NON_IDR)) { +#ifdef H264_ENC_SVC + /* encode non reference frame or not */ + if (request->cmd == ENCODER_IDR) + wq->pic.non_ref_cnt = 0; //IDR reset counter + if (wq->pic.enable_svc && wq->pic.non_ref_cnt) { + enc_pr(LOG_INFO, + "PIC is NON REF cmd %d cnt %d value 0x%x\n", + request->cmd, wq->pic.non_ref_cnt, + ENC_SLC_NON_REF); + WRITE_HREG(H264_ENC_SVC_PIC_TYPE, ENC_SLC_NON_REF); + } else { + enc_pr(LOG_INFO, + "PIC is REF cmd %d cnt %d val 0x%x\n", + request->cmd, wq->pic.non_ref_cnt, + ENC_SLC_REF); + WRITE_HREG(H264_ENC_SVC_PIC_TYPE, ENC_SLC_REF); + } +#else + /* if FW defined but not defined SVC in driver here*/ + WRITE_HREG(H264_ENC_SVC_PIC_TYPE, ENC_SLC_REF); +#endif avc_init_dblk_buffer(wq->mem.dblk_buf_canvas); avc_init_reference_buffer(wq->mem.ref_buf_canvas); } @@ -3266,15 +3290,49 @@ static long amvenc_avc_ioctl(struct file *file, u32 cmd, ulong arg) wq->pic.pic_order_cnt_lsb = 2; wq->pic.frame_number = 1; } else if (amrisc_cmd == ENCODER_NON_IDR) { +#ifdef H264_ENC_SVC + /* only update when there is reference frame */ + if (wq->pic.enable_svc == 0 || wq->pic.non_ref_cnt == 0) { + wq->pic.frame_number++; + enc_pr(LOG_INFO, "Increase frame_num to %d\n", + wq->pic.frame_number); + } +#else wq->pic.frame_number++; +#endif + wq->pic.pic_order_cnt_lsb += 2; if (wq->pic.frame_number > 65535) wq->pic.frame_number = 0; } +#ifdef H264_ENC_SVC + /* only update when there is reference frame */ + if (wq->pic.enable_svc == 0 || wq->pic.non_ref_cnt == 0) { + amrisc_cmd = wq->mem.dblk_buf_canvas; + wq->mem.dblk_buf_canvas = wq->mem.ref_buf_canvas; + /* current dblk buffer as next reference buffer */ + wq->mem.ref_buf_canvas = amrisc_cmd; + enc_pr(LOG_INFO, + "switch buffer enable %d cnt %d\n", + wq->pic.enable_svc, wq->pic.non_ref_cnt); + } + if (wq->pic.enable_svc) { + wq->pic.non_ref_cnt ++; + if (wq->pic.non_ref_cnt > wq->pic.non_ref_limit) { + enc_pr(LOG_INFO, "Svc clear cnt %d conf %d\n", + wq->pic.non_ref_cnt, + wq->pic.non_ref_limit); + wq->pic.non_ref_cnt = 0; + } else + enc_pr(LOG_INFO,"Svc increase non ref counter to %d\n", + wq->pic.non_ref_cnt ); + } +#else amrisc_cmd = wq->mem.dblk_buf_canvas; wq->mem.dblk_buf_canvas = wq->mem.ref_buf_canvas; /* current dblk buffer as next reference buffer */ wq->mem.ref_buf_canvas = amrisc_cmd; +#endif break; case AMVENC_AVC_IOC_READ_CANVAS: get_user(argV, ((u32 *)arg)); @@ -3580,6 +3638,15 @@ struct encode_wq_s *create_encode_work_queue(void) encode_work_queue->pic.idr_pic_id = 0; encode_work_queue->pic.frame_number = 0; encode_work_queue->pic.pic_order_cnt_lsb = 0; +#ifdef H264_ENC_SVC + /* Get settings from the global*/ + encode_work_queue->pic.enable_svc = svc_enable; + encode_work_queue->pic.non_ref_limit = svc_ref_conf; + encode_work_queue->pic.non_ref_cnt = 0; + enc_pr(LOG_INFO, "svc conf enable %d, duration %d\n", + encode_work_queue->pic.enable_svc, + encode_work_queue->pic.non_ref_limit); +#endif encode_work_queue->ucode_index = UCODE_MODE_FULL; #ifdef H264_ENC_CBR @@ -4445,6 +4512,13 @@ MODULE_PARM_DESC(nr_mode, "\n nr_mode option\n"); module_param(qp_table_debug, uint, 0664); MODULE_PARM_DESC(qp_table_debug, "\n print qp table\n"); +#ifdef H264_ENC_SVC +module_param(svc_enable, uint, 0664); +MODULE_PARM_DESC(svc_enable, "\n svc enable\n"); +module_param(svc_ref_conf, uint, 0664); +MODULE_PARM_DESC(svc_ref_conf, "\n svc reference duration config\n"); +#endif + #ifdef MORE_MODULE_PARAM module_param(me_mv_merge_ctl, uint, 0664); MODULE_PARM_DESC(me_mv_merge_ctl, "\n me_mv_merge_ctl\n"); diff --git a/drivers/frame_sink/encoder/h264/encoder.h b/drivers/frame_sink/encoder/h264/encoder.h index e47fa39..0008fb3 100644 --- a/drivers/frame_sink/encoder/h264/encoder.h +++ b/drivers/frame_sink/encoder/h264/encoder.h @@ -42,6 +42,8 @@ #define HCODEC_IRQ_MBOX_CLR HCODEC_ASSIST_MBOX2_CLR_REG #define HCODEC_IRQ_MBOX_MASK HCODEC_ASSIST_MBOX2_MASK +#define H264_ENC_SVC + /* M8: 2550/10 = 255M GX: 2000/10 = 200M */ #define HDEC_L0() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \ (2 << 25) | (1 << 16) | (1 << 24) | \ @@ -300,6 +302,11 @@ struct encode_picinfo_s { u32 log2_max_pic_order_cnt_lsb; u32 log2_max_frame_num; u32 init_qppicture; +#ifdef H264_ENC_SVC + u32 enable_svc; + u32 non_ref_limit; + u32 non_ref_cnt; +#endif }; struct encode_cbr_s { @@ -433,6 +440,13 @@ extern s32 destroy_encode_work_queue(struct encode_wq_s *encode_work_queue); #define H264_ENC_CBR_PREV_BYTES HCODEC_HENC_SCRATCH_J #define H264_ENC_CBR_REGION_SIZE HCODEC_HENC_SCRATCH_J +/* for SVC */ +#define H264_ENC_SVC_PIC_TYPE HCODEC_HENC_SCRATCH_K + +/* define for PIC header */ +#define ENC_SLC_REF 0x8410 +#define ENC_SLC_NON_REF 0x8010 + /* --------------------------------------------------- */ /* ENCODER_STATUS define */ /* --------------------------------------------------- */ diff --git a/drivers/stream_input/amports/amstream.c b/drivers/stream_input/amports/amstream.c index 8c9ef11..51fd4b7 100644 --- a/drivers/stream_input/amports/amstream.c +++ b/drivers/stream_input/amports/amstream.c @@ -555,6 +555,9 @@ static void port_set_inited(struct port_priv_s *priv) struct vdec_s *vdec = priv->vdec; vdec->port_flag |= PORT_FLAG_INITED; + port->flag |= PORT_FLAG_INITED; + pr_info("vdec->port_flag=0x%x, port_flag=0x%x\n", + vdec->port_flag, port->flag); } else port->flag |= PORT_FLAG_INITED; } @@ -716,23 +719,35 @@ static int audio_port_reset(struct stream_port_s *port, struct stream_buf_s *pbuf) { int r; - + mutex_lock(&amstream_mutex); if ((port->flag & PORT_FLAG_AFORMAT) == 0) { pr_err("aformat not set\n"); + mutex_unlock(&amstream_mutex); + return 0; + } + + pr_info("audio port reset, flag:0x%x\n", port->flag); + if ((port->flag & PORT_FLAG_INITED) == 0) { + pr_info("audio port not inited,return\n"); + mutex_unlock(&amstream_mutex); return 0; } + pr_info("audio_port_reset begin\n"); pts_stop(PTS_TYPE_AUDIO); stbuf_release(pbuf, false); r = stbuf_init(pbuf, NULL, false); - if (r < 0) + if (r < 0) { + mutex_unlock(&amstream_mutex); return r; + } r = adec_init(port); if (r < 0) { audio_port_release(port, pbuf, 2); + mutex_unlock(&amstream_mutex); return r; } @@ -755,6 +770,8 @@ static int audio_port_reset(struct stream_port_s *port, r = pts_start(PTS_TYPE_AUDIO); + pr_info("audio_port_reset done\n"); + mutex_unlock(&amstream_mutex); return r; } diff --git a/drivers/stream_input/parser/esparser.c b/drivers/stream_input/parser/esparser.c index 1e45893..1cc3ac9 100644 --- a/drivers/stream_input/parser/esparser.c +++ b/drivers/stream_input/parser/esparser.c @@ -272,6 +272,11 @@ static ssize_t _esparser_write_s(const char __user *buf, /*pr_info("write wp 0x%x, count %d, start 0x%x, end 0x%x\n", * wp, (u32)count, buf_start, buf_end);*/ if (wp + count > buf_end) { + if (wp == buf_end) { + wp = buf_start; + set_buf_wp(type, wp); + return -EAGAIN; + } vaddr = codec_mm_phys_to_virt(wp); ret = copy_from_user(vaddr, p, buf_end - wp); if (ret > 0) { diff --git a/drivers/stream_input/parser/hw_demux/aml_demod_gt.h b/drivers/stream_input/parser/hw_demux/aml_demod_gt.h index 966e66b..7d8ae11 100644 --- a/drivers/stream_input/parser/hw_demux/aml_demod_gt.h +++ b/drivers/stream_input/parser/hw_demux/aml_demod_gt.h @@ -35,6 +35,11 @@ struct amlfe_demod_config { int i2c_addr; int reset_gpio; int reset_value; + int ts_out_mode; //serial or parallel; 0:serial, 1:parallel + int tuner0_i2c_addr; + int tuner1_i2c_addr; + int tuner0_code; + int tuner1_code; }; /* For configure different tuners */ @@ -91,6 +96,11 @@ static inline struct dvb_frontend* si2168_attach (const struct amlfe_demod_confi return NULL; } +static inline struct dvb_frontend* si2168_attach_1 (const struct amlfe_demod_config *config) +{ + return NULL; +} + static inline struct dvb_frontend* avl6762_attach (const struct amlfe_demod_config *config) { return NULL; diff --git a/drivers/stream_input/parser/hw_demux/aml_dmx.c b/drivers/stream_input/parser/hw_demux/aml_dmx.c index b82984f..286b922 100644 --- a/drivers/stream_input/parser/hw_demux/aml_dmx.c +++ b/drivers/stream_input/parser/hw_demux/aml_dmx.c @@ -4872,22 +4872,22 @@ int aml_dmx_hw_set_source(struct dmx_demux *demux, dmx_source_t src) case DMX_SOURCE_FRONT0: hw_src = (dvb->ts[0].mode == - AM_TS_SERIAL) ? (dvb->ts[0].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS0; + AM_TS_SERIAL) ? (AM_TS_SRC_S_TS0) : AM_TS_SRC_TS0; break; case DMX_SOURCE_FRONT1: hw_src = (dvb->ts[1].mode == - AM_TS_SERIAL) ? (dvb->ts[1].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS1; + AM_TS_SERIAL) ? (AM_TS_SRC_S_TS1) : AM_TS_SRC_TS1; break; case DMX_SOURCE_FRONT2: hw_src = (dvb->ts[2].mode == - AM_TS_SERIAL) ? (dvb->ts[2].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS2; + AM_TS_SERIAL) ? (AM_TS_SRC_S_TS2) : AM_TS_SRC_TS2; break; case DMX_SOURCE_FRONT3: hw_src = (dvb->ts[3].mode == - AM_TS_SERIAL) ? (dvb->ts[3].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS3; + AM_TS_SERIAL) ? (AM_TS_SRC_S_TS3) : AM_TS_SRC_TS3; break; case DMX_SOURCE_DVR0: hw_src = AM_TS_SRC_HIU; @@ -4938,22 +4938,22 @@ int aml_stb_hw_set_source(struct aml_dvb *dvb, dmx_source_t src) case DMX_SOURCE_FRONT0: hw_src = (dvb->ts[0].mode == - AM_TS_SERIAL) ? (dvb->ts[0].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS0; + AM_TS_SERIAL) ? (AM_TS_SRC_S_TS0) : AM_TS_SRC_TS0; break; case DMX_SOURCE_FRONT1: hw_src = (dvb->ts[1].mode == - AM_TS_SERIAL) ? (dvb->ts[1].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS1; + AM_TS_SERIAL) ? (AM_TS_SRC_S_TS1) : AM_TS_SRC_TS1; break; case DMX_SOURCE_FRONT2: hw_src = (dvb->ts[2].mode == - AM_TS_SERIAL) ? (dvb->ts[2].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS2; + AM_TS_SERIAL) ? (AM_TS_SRC_S_TS2) : AM_TS_SRC_TS2; break; case DMX_SOURCE_FRONT3: hw_src = (dvb->ts[3].mode == - AM_TS_SERIAL) ? (dvb->ts[3].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS3; + AM_TS_SERIAL) ? (AM_TS_SRC_S_TS3) : AM_TS_SRC_TS3; break; case DMX_SOURCE_DVR0: hw_src = AM_TS_SRC_HIU; @@ -5120,19 +5120,19 @@ int aml_tso_hw_set_source(struct aml_dvb *dvb, dmx_source_t src) switch (src) { case DMX_SOURCE_FRONT0: hw_src = (dvb->ts[0].mode == AM_TS_SERIAL) - ? (dvb->ts[0].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS0; + ? (AM_TS_SRC_S_TS0) : AM_TS_SRC_TS0; break; case DMX_SOURCE_FRONT1: hw_src = (dvb->ts[1].mode == AM_TS_SERIAL) - ? (dvb->ts[1].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS1; + ? (AM_TS_SRC_S_TS1) : AM_TS_SRC_TS1; break; case DMX_SOURCE_FRONT2: hw_src = (dvb->ts[2].mode == AM_TS_SERIAL) - ? (dvb->ts[2].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS2; + ? (AM_TS_SRC_S_TS2) : AM_TS_SRC_TS2; break; case DMX_SOURCE_FRONT3: hw_src = (dvb->ts[3].mode == AM_TS_SERIAL) - ? (dvb->ts[3].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS3; + ? (AM_TS_SRC_S_TS3) : AM_TS_SRC_TS3; break; case DMX_SOURCE_DVR0: hw_src = AM_TS_SRC_HIU; diff --git a/drivers/stream_input/parser/hw_demux/aml_dvb.c b/drivers/stream_input/parser/hw_demux/aml_dvb.c index e2306be..1a5e174 100644 --- a/drivers/stream_input/parser/hw_demux/aml_dvb.c +++ b/drivers/stream_input/parser/hw_demux/aml_dvb.c @@ -65,6 +65,7 @@ typedef enum __demod_type DEMOD_ATBM8881, DEMOD_SI2168, DEMOD_AVL6762, + DEMOD_SI2168_1, DEMOD_MAX_NUM }demod_type; @@ -2465,6 +2466,35 @@ static int aml_dvb_probe(struct platform_device *pdev) pr_error("reset_value error\n"); goto error_fe; } + memset(buf, 0, 32); + snprintf(buf, sizeof(buf), "fe%d_tuner0_i2c_addr",i); + ret = of_property_read_u32(pdev->dev.of_node, buf,&config.tuner0_i2c_addr); + if (ret) { + pr_error("no tuner0 i2c_addr define\n"); + } + memset(buf, 0, 32); + snprintf(buf, sizeof(buf), "fe%d_tuner1_i2c_addr",i); + ret = of_property_read_u32(pdev->dev.of_node, buf,&config.tuner1_i2c_addr); + if (ret) { + pr_error("no tuner1 addr define\n"); + } + memset(buf, 0, 32); + snprintf(buf, sizeof(buf), "fe%d_tuner0_code",i); + ret = of_property_read_u32(pdev->dev.of_node, buf,&config.tuner0_code); + if (ret) { + pr_error("no tuner0_code define\n"); + } + memset(buf, 0, 32); + snprintf(buf, sizeof(buf), "fe%d_tuner1_code",i); + ret = of_property_read_u32(pdev->dev.of_node, buf,&config.tuner1_code); + if (ret) { + pr_error("no tuner1_code define\n"); + } + if (advb->ts[config.ts].mode == AM_TS_PARALLEL) { + config.ts_out_mode = 1; + } else { + config.ts_out_mode = 0; + } if (!strcmp(name,"Atbm8881")) { frontend[i] = dvb_attach(atbm8881_attach,&config); @@ -2486,6 +2516,16 @@ static int aml_dvb_probe(struct platform_device *pdev) s_demod_type[i] = DEMOD_SI2168; } } + if (!strcmp(name,"Si2168-1")) { + frontend[i] = dvb_attach(si2168_attach_1,&config); + if (frontend[i] == NULL) { + pr_error("dvb attach demod error\n"); + goto error_fe; + } else { + pr_inf("si2168_1 dtvdemod attatch sucess\n"); + s_demod_type[i] = DEMOD_SI2168_1; + } + } if (!strcmp(name,"Avl6762")) { frontend[i] = dvb_attach(avl6762_attach,&config); if (frontend[i] == NULL) { @@ -2520,6 +2560,10 @@ error_fe: dvb_detach(si2168_attach); frontend[i] = NULL; s_demod_type[i] = DEMOD_INVALID; + }else if (s_demod_type[i] == DEMOD_SI2168_1) { + dvb_detach(si2168_attach_1); + frontend[i] = NULL; + s_demod_type[i] = DEMOD_INVALID; }else if (s_demod_type[i] == DEMOD_AVL6762) { dvb_detach(avl6762_attach); frontend[i] = NULL; @@ -2581,6 +2625,8 @@ static int aml_dvb_remove(struct platform_device *pdev) dvb_detach(atbm8881_attach); }else if (s_demod_type[i] == DEMOD_SI2168) { dvb_detach(si2168_attach); + }else if (s_demod_type[i] == DEMOD_SI2168_1) { + dvb_detach(si2168_attach_1); }else if (s_demod_type[i] == DEMOD_AVL6762) { dvb_detach(avl6762_attach); } diff --git a/drivers/stream_input/parser/hw_demux/aml_dvb.h b/drivers/stream_input/parser/hw_demux/aml_dvb.h index 50ad862..604be3a 100644 --- a/drivers/stream_input/parser/hw_demux/aml_dvb.h +++ b/drivers/stream_input/parser/hw_demux/aml_dvb.h @@ -92,6 +92,7 @@ enum aml_ts_source_t { AM_TS_SRC_S_TS0, AM_TS_SRC_S_TS1, AM_TS_SRC_S_TS2, + AM_TS_SRC_S_TS3, AM_TS_SRC_HIU, AM_TS_SRC_HIU1, diff --git a/firmware/h264_enc.bin b/firmware/h264_enc.bin index 27c54d6..d8bc73d 100644 --- a/firmware/h264_enc.bin +++ b/firmware/h264_enc.bin @@ -1,19 +1,19 @@ -KCAP -x +KCAP +x ` x @* @^x - + x
-H -H -! +H +H +! @@HR`
@!
-@@HR`
Ob `
I +@@HR`
Ob `
I w vJH @@ -23,18 +23,19 @@ vJH @ -ax +bx - + @@HR`
-@@HR`
+@@HR`
J" + w v n n n nH - + @ @ @@ -50,7 +51,7 @@ v n n n nH @ -MMG @O +MMG @O @ 9
@@ -70,11 +71,11 @@ QP@ʢ H@I@I"@ H@ -Р +Р 6
"@ -I -6
+I +6
6
H@I"@ @@ -85,7 +86,7 @@ H@I@I"@ K@ J QPPCK -" +" aM8cMH@"@ @c @@ -117,7 +118,7 @@ QP@ʢ w J
K
L
M
x Ā " -Ȁ +Ȁ 6
H@JB@ @@ -126,8 +127,8 @@ w xHH -@ -H" %~ +@ +H" $~ J2I 4 9 @@ -140,8 +141,8 @@ J2I @ H J JH ->O~ -JO@~ +>O~ +JO@~ JG @@ -170,20 +171,20 @@ E @@ -a 3
-!
!
+a 3
+!
!
-@@HR`
!
+@@HR`
!
-@@HR`
Ob I +@@HR`
Ob I -a 3
-!
@!
+a 3
+!
@!
@@HR`
@@HR`
OH". -b I +b I 4M @@ -219,7 +220,7 @@ E - + x ` x @@ -434,7 +435,7 @@ E - + x ` x diff --git a/firmware/video_ucode.bin b/firmware/video_ucode.bin index cd6b03c..6ef6866 100755..100644 --- a/firmware/video_ucode.bin +++ b/firmware/video_ucode.bin @@ -1,5064 +1,22 @@ -[ ;n$Y_!&GLn㵩A\{{jc}EfdRӪ-/aЯ杗:'9>ѷ&W%YSN O*<SX?<d~0.kZXUc@m6*ܬ%X,ę˨b(p\ְq#O2T;>A+=g^ ,ZRo"/%J,]Utx!E45 -KCAP - - x -B< - -@ -? -C -# --0 - - -ɑ @|zI -GL - - -&xP - -Sx@Ox - - - - - -) - -J@ -
J -.8 - -GI , -O -I@ -I - -o -I@ -=Lʀ -I - bp - - - - -Q RPPCL - -@J -A -A -& -% -( -\ -!p! - -J - - - - -LJ - - - -@xR -a -A - -@xJ e -B -a -xH -: - H G -G@ -` -x
ǂ` - -x
- -x}G` -@x -y - QL -FL@LBLȂ@ - -G - - -q@ - - - - - - t - - - - -IJ -Iʁ - - - - -Lʥ -% -B@Ȃ - - - - - - - - -G - -GI -I -d - -` - - -$ - - - -@x$@ -W(Ǥ -*e@-UU -\!@xU@-U -¢V - -@TeP W| NB -EE@ -BV -@@xAՀe -&N U -TeP W| NB -U@%$U@x$&) -bV -`aV0 -&N U'$ - - -$` - - - - - u V,E -@ - - -B -@A
Ǡ - -A - - -@@x -NNN@ - - -@@ II24 A" - - Iɐ ɐ @ I - -I SI - -@I@ -I - -K -K -< -` -xJ - -xIǀ! -< -J - -xJ -xJ -G2 -H" - - -2 -xJ -3@ -G4 - - -~ $ -H -! - -N,@x @ - -@x - -c - x.I,J) -` -,@ -I -,@Ȅ@ -,
- -@ǠA+,- - - -G -;H -% -< -@ I - -@ H -H@a - -H - -;I - - - - -GǑ@ʡ - -GH;ȡ@ʡ - - -G @@@ - -G - -G @@ - -G @ -I; -B - J -J - -J9 -@b -; - - - - -!sstG -@b - -GuuG - -@b - -x - - -~ - - -o - - -H - $ɀ -@Ip p QIs Q #G)!D G)d - -P;! - - - - - - - - - -G,",@a -QI - - -Q -? -R - - -ȼo - - -@ -G - - - -+ -! * -x, - -*I - -G# -# -q@)#q s -s s @ -' -L! o -!*! -G) -))Wx@Ix -))@%xx -G) -))OxAx -))x -G$) - - -$ -@o - - - -'x 'LI! &'()) a ' 'LI! H$ a ' CI#x%>?L> @ -#LGB0 -@ -@ -* - - - @o -I@ -((#LB0 o - - A R K -(@xGB -%B -G -H - -` -x - - - -&xI* -S@& NI HB -@ -N @o -@N @n -$m - -G$) - -' -'x 'LI! &') a ' 'LI! H$ a '#%$ -o - -!L"L%'Le! ,a -* -$ʀ - - - -( -%&&&r !G%@ -G - -S& -@o - -* - -$ @o -&I@u&@x* H"P !&% - - -, - --xB - -G - --J -Fa - - - -+ - - -g -J+J - - -Q -? -RP --L@L+" -@#\ a -L+L -C - -x, -I - - ,DŽP -Ʉ@ @ -I@ ` - I,Db -@x --J - - +-G% -! - --J+ - -x -! - + - @a - -x - b@ʢ c -$"L2@ - - - -CALc -AA K)` -! - - -@ -a $a ' - N, -?G)á -,@ǠA+ -+?aǠA+PCG - - - -ߏN LJ -J2x -@Ȇ - -0 -` - - -@v~ -
@j#LJ - - - - -r - -
I - - -D#G@H
Q -xH@B H@ -Q -Q - -Q -4#@4#G@Q -GG@Q -@ - / -B @ - //G@Q - -@'#G@Q - -;p ; - -GС@ʡ - -G@@!x - - -G -!I@ -R B@h - H -H:
B G) -@!D # -G -G - G -GB G -G - -xQ - -;Gp ; - -GБ@ʡ - - ;R` G)"j ! (! )I - - -@ - -Ϡ -Aaa - -@G1 -N - -I - - -@ -G -Ϡ -Aaa -@ -@ - - - -@x - - - -H - -t - - - -B -sV#sRP G)"j ! - - ( -B @R#BH Q#BP B @ s@IGr @ G - H - - -a -G@GA -I -I - - @ -D#"@ -@x "@ - - -G @?#@A - -G"@ - - x -B< - -@ -? -C -# --0 - - -ɑ |zI -GL - - -&xP - -Sx@Ox - - - - - -) - -J@ -
J -.8 - -GI , -O -I@ -I - -o -I@ -=Lʀ -I - bp - - - - -Q RPPCL - -@J -A -A -& -% -( -\ -!p! - -J - - - - -LJ - - - -@xR -a -A - -@xJ e -B -a -xH -: - H G -G@ -` -xɂ` - -x
- -x}G` -@x - QL -FL@LBLȂ@ - -G - - -q@ - - - - - - t - - - - -IJ -Iʁ - - - - -Lʥ -% -B@Ȃ - - - - - - - - -G - -GI -I -d - -` - - -)I -$ - -@1x - -x$@ -V' -V)` --GI` -W -*e@-UU -\!@xU@-U -¢V - -@TeP W| NB -EE@ -BV -@@xAՀe -&N U -TeP W| NB -U@%$U@x$&) -bV -`aV0 -&N U'$ - - -$` - - - - - u V,E -@ - - -B -@A
Ǡ - -A - - -@@x -NNN@ - - -@@ II24 A" - - Iɐ ɐ @ I - - - - -K -K -< -` -xJ - -xIǀ! -< -J - -xJ -xJ -G2 -H" - - -2 -xJ -3@ -G4 - -@x.I,J) -` -,@ -I -,@Ȅ@ -, -@ǠA+,- - - -G -;H -% -< -@ I - -@ H -H@a - -H - -;I - - - - -GǑ@ʡ - -GH;ȡ@ʡ - - -G @@@ - -G - -G @@ - -G @ -I; -B - J -J - -J9 -@b -; - - - - -!sstG -@b - -GuuG - -@b - -x - - -~ - - -o - - -H - $ɀ -@Ip p QIs Q #G)!D G)c - -P;! - - - - - - - - - -G,",@a -QI - - -Q -? -R - - -ȼo - - -@ -G - - - -+ -! * -x, - -*I - - @c@r -G# -# -q@)#q s -s s -' -L! o -!*! -G) -))Wx@Ix -))@%xx -G) -))OxAx -))x -G$) - - -$ -@o - - - -'x 'LI! &'()) a ' 'LI! H$ a ' CI#x%>?L> @ -#LGB0 -@ -@ -* - - - @o -I@ -((#LB0 o - - A R K -(@xGB -%B -G -H - -` -x - - - - -S@& NI HB -@ -N @o -@N @n -$m - -G$) - -' -'x 'LI! &') a ' 'LI! H$ a '#%$ -o - -!L"L%'Le! ,a -* -$ʀ - - - -( -%&& -G - -S& - - -* - -$ @o -&I@@`&@x* H"P !&% - - -, - --xB - -G - --J -Fa - - - -+ - - -g -J+J - - -Q -? -RP --L@L+" -@#\ a -L+L -. - -x, -I - - ,DŽP -Ʉ@ @ -I@ ` - @~I,Db -@x --J - - +-G% -! - --J+ - -x -! - + -! - - -@ -a $a ' - N, -?G)á -,@ǠA+ -+?aǠA+PCG - - - -@x -
-I@S -x - x
# @d -LC@ - x
# -LC@ S @x
C C@ S - @GS @x
C C@ S @GS
f - - - -LC@ -
- - C@$ - - -ߏN LJ -J2x -@Ȇ - -0 -` - - -@v~ -
@j#LJ - - - - -r - -
I - - -D#G@H
Q -xH@B H@ -Q -Q - -Q -4#@4#G@Q -GG@Q -@ - / -B - //G@Q - -@'#G@Q - -;p ; - -GС@ʡ - -G@@!x - - -G -!I@ -R B@h - H -H:
B G) -@!D # -G -G - G -GB G -G - -xQ - -;Gp ; - -GБ@ʡ - - ;R` G)"j ! (! )I - - -@ - -Ϡ -Aaa - -@G1 -N - -I - - -@ -G -Ϡ -Aaa -@ -@ - - - -@x - - - -H - -t - - - -B -sV#sRP G)"j ! - -B @R#BH Q#BP B @ s@IGr @ G - H - - -a -G@GA -I -I - - @ -D#"@ -x B - - -G @@@?#@ - -G"@ ;# - - - - - - - - - - - - x -B< - -@ -? -C -# --0 - - -ɑ @|zI -GL - - -&xP - -Sx@Ox - - - - - -) - -J@ -
J -.8 - -GI , -O -I@ -I - -o -I@ -=Lʀ -I - bp - - - - -Q RPPCL - -@J -A -A -& -% -( -\ -!p! - -J - - - - -LJ -@k - - -@xR -a -A - -@xJ e -B -a -xH -9 - H G -G@ -` -x
ǂ` - -x
- -x}G` -@x -y - QL -FL@LBLȂ@ - -G - - -q@ - - - - - - t - - - - -IJ -Iʁ - - - - -B@Ȃ - - - - - - - - -G - -GI -I -d - -` - - -$ - - - -@x$@ -W(Ǥ -*e@-UU -\!@xU@-U -¢V - -@TeP W| NB -EE@ -BV -@@xAՀe -&N U -TeP W| NB -U@%$U@x$&) -bV -`aV0 -&N U'$ - - -$` - - - - - u V,E -@ - - -B -@A
Ǡ - -A - - -@@x -NNN@ - - -@@ II24 A" - - Iɐ ɐ @ I - -I SI - -@I@ -I - -K -K -< -` -xJ - -xIǀ! -< -J - -xJ -xJ -G2 -H" - - -2 -xJ -3@ -G4 - - -~ $ -H -! - -N,@x @ - -@x - -c - x.I,J) -` -,@ -I -,@Ȅ@ -,
- -@ǠA+,- -@ - -G -;H -% -< - - - -H@a - -H - -;I - - - - -GǑ@ʡ - -GH;ȡ@ʡ - - -G @@ - -G - -G @ - -G @ -I; -B - J -J - -J9 -@b -; - - - - -!sstG -@b - -GuuG - -@b - -x - - -~ - -~ -o - - -H - $ɀ -@Ip p QIs Q #G)!D G)d - -P;! - - - - - -~ - - - -G,",@a -QI - - -Q -? -R - - -ȼo - - -@ -G - - - -+ -! * -x, - -*I - -G# -# -q@)#q s -s s @ -' -L! o -!*! -G) -))Wx@Ix -))@%xx -G) -))OxAx -))x -G$) - - -$ -@o - - - -'x 'LI! &'()) a ' 'LI! H$ a ' CI#x%>?L> @ -#LGB0 -@ -@ -* - - - @o -I@ -((#LB0 o - - A R K -(@xGB -%B -G -H - -` -x - - - -&xI* -S@& NI HB -@ -N @o -@N @n -$m - -G$) - -' -'x 'LI! &') a ' 'LI! H$ a '#%$ -o - -!L"L%'Le! ,a -* -$ʀ - - - -( -%&&&r !G%@ -G - -S& -n - -* - -$ @o -&I@t&@x* H"P !&% - - -, - --xB - -G - --J -Fa - - - -+ - - -g -J+J - - -Q -? -RP --L@L+" -@#\ a -L+L - - -x, -I - - ,DŽP -Ʉ@ @ -I@ ` - -I,Db -@x --J - - +-G% -! - --J+ - -x -! - + - @a - -x - b@ʢ c -$"L2@ - - - -CALc -AA K)` -! - - -@ -a $a ' - N, -?G)á -,@ǠA+ -+?aǠA+PCG - - - -ߏN LJ -J2x -@Ȇ - -0 -` - - -@v~ -
@j#LJ - - - - -r - -
I - - -D#G@H
Q -xH@B H@ -Q -Q - -Q -4#@4#G@Q -GG@Q -@ - / -B @ - //G@Q - -@'#G@Q - -;p ; - -GС@ʡ - -G@@!x - - -G -!I@ -R B@h - H -H:
B G) -@!D # -G -G - G -GB G -G - -xQ - -;Gp ; - -GБ@ʡ - - ;R` G)"j ! (! )I - - -@ - -Ϡ -Aaa - -@G1 -N - -I - - -@ -G -Ϡ -Aaa -@ -@ - - - -@x - - - -H - -t - - - -B -sV#sRP G)"j ! - -B @R#BH Q#BP B @ s@IGr @ G - H - - -a -G@GA -I -I - - @ -D#"@ -@x "@ - - -G @?#@A - -G"@ - - x -B< - -@ -? -C -# --0 - - -ɑ |zI -GL - - -&xP - -Sx@Ox - - - - - -) - -J@ -
J -.8 - -GI , -O -I@ -I - -o -I@ -=Lʀ -I - bp - - - - -Q RPPCL - -@J -A -A -& -% -( -\ -!p! - -J - - - - -LJ - - - -@xR -a -A - -@xJ e -B -a -xH -: - H G -G@ -` -xɂ` - -x
- -x}G` -@x - QL -FL@LBLȂ@ - -G - - -q@ - - - - - - t - - - - -IJ -Iʁ - - - - -Lʥ -% -B@Ȃ - - - - - - - - -G - -GI -I -d - -` - - -)I -$ - -@1x - -x$@ -V' -V)` --GI` -W -*e@-UU -\!@xU@-U -¢V - -@TeP W| NB -EE@ -BV -@@xAՀe -&N U -TeP W| NB -U@%$U@x$&) -bV -`aV0 -&N U'$ - - -$` - - - - - u V,E -@ - - -B -@A
Ǡ - -A - - -@@x -NNN@ - - -@@ II24 A" - - Iɐ ɐ @ I - - - - -K -K -< -` -xJ - -xIǀ! -< -J - -xJ -xJ -G2 -H" - - -2 -xJ -3@ -G4 - -@x.I,J) -` -,@ -I -,@Ȅ@ -, -@ǠA+,- - - -G -;H -% -< -@ I - -@ H -H@a - -H - -;I - - - - -GǑ@ʡ - -GH;ȡ@ʡ - - -G @@@ - -G - -G @@ - -G @ -I; -B - J -J - -J9 -@b -; - - - - -!sstG -@b - -GuuG - -@b - -x - - -~ - - -o - - -H - $ɀ -@Ip p QIs Q #G)!D G)c - -P;! - - - - - - - - - -G,",@a -QI - - -Q -? -R - - -ȼo - - -@ -G - - - -+ -! * -x, - -*I - - @c@r -G# -# -q@)#q s -s s -' -L! o -!*! -G) -))Wx@Ix -))@%xx -G) -))OxAx -))x -G$) - - -$ -@o - - - -'x 'LI! &'()) a ' 'LI! H$ a ' CI#x%>?L> @ -#LGB0 -@ -@ -* - - - @o -I@ -((#LB0 o - - A R K -(@xGB -%B -G -H - -` -x - - - - -S@& NI HB -@ -N @o -@N @n -$m - -G$) - -' -'x 'LI! &') a ' 'LI! H$ a '#%$ -o - -!L"L%'Le! ,a -* -$ʀ - - - -( -%&& -G - -S& - - -* - -$ @o -&I@@`&@x* H"P !&% - - -, - --xB - -G - --J -Fa - - - -+ - - -g -J+J - - -Q -? -RP --L@L+" -@#\ a -L+L -. - -x, -I - - ,DŽP -Ʉ@ @ -I@ ` - @~I,Db -@x --J - - +-G% -! - --J+ - -x -! - + -! - - -@ -a $a ' - N, -?G)á -,@ǠA+ -+?aǠA+PCG - - - -@x -
-I@S -x - x
# @d -LC@ - x
# -LC@ S @x
C C@ S - @GS @x
C C@ S @GS
f - - - -LC@ -
- - C@$ - - -ߏN LJ -J2x -@Ȇ - -0 -` - - -@v~ -
@j#LJ - - - - -r - -
I - - -D#G@H
Q -xH@B H@ -Q -Q - -Q -4#@4#G@Q -GG@Q -@ - / -B - //G@Q - -@'#G@Q - -;p ; - -GС@ʡ - -G@@!x - - -G -!I@ -R B@h - H -H:
B G) -@!D # -G -G - G -GB G -G - -xQ - -;Gp ; - -GБ@ʡ - - ;R` G)"j ! (! )I - - -@ - -Ϡ -Aaa - -@G1 -N - -I - - -@ -G -Ϡ -Aaa -@ -@ - - - -@x - - - -H - -t - - - -B -sV#sRP G)"j ! - -B @R#BH Q#BP B @ s@IGr @ G - H - - -a -G@GA -I -I - - @ -D#"@ -x B - - -G @@@?#@ - -G"@ ;# - - x -B< - -@ -? -C -# --0 - - -ɑ @|zI -GL - - -&xP - -Sx@Ox - - - - - -) - -J@ -
J -.8 - -GI , -O -I@ -I - -o -I@ -=Lʀ -I - bp - - - - -Q RPPCL - -@J -A -A -& -% -( -\ -!p! - -J - - - - -LJ - - - -@xR -a -A - -@xJ e -B -a -xH -: - H G -G@ -` -x
ǂ` - -x
- -x}G` -@x -y - QL -FL@LBLȂ@ - -G - - -q@ - - - - - - t - - - - -IJ -Iʁ - - - - -Lʥ -% -B@Ȃ - - - - - - - - -G - -GI -I -d - -` - - -$ - - - -@x$@ -W(Ǥ -*e@-UU -\!@xU@-U -¢V - -@TeP W| NB -EE@ -BV -@@xAՀe -&N U -TeP W| NB -U@%$U@x$&) -bV -`aV0 -&N U'$ - - -$` - - - - - u V,E -@ - - -B -@A
Ǡ - -A - - -@@x -NNN@ - - -@@ II24 A" - - Iɐ ɐ @ I - -I SI - -@I@ -I - -K -K -< -` -xJ - -xIǀ! -< -J - -xJ -xJ -G2 -H" - - -2 -xJ -3@ -G4 - - -~ $ -H -! - -N,@x @ - -@x - -c - x.I,J) -` -,@ -I -,@Ȅ@ -,
- -@ǠA+,- - - -G -;H -% -< -@ I - -@ H -H@a - -H - -;I - - - - -GǑ@ʡ - -GH;ȡ@ʡ - - -G @@@ - -G - -G @@ - -G @ -I; -B - J -J - -J9 -@b -; - - - - -!sstG -@b - -GuuG - -@b - -x - - -~ - - -o - - -H - $ɀ -@Ip p QIs Q #G)!D G)d - -P;! - - - - - - - - - -G,",@a -QI - - -Q -? -R - - -ȼo - - -@ -G - - - -+ -! * -x, - -*I - -G# -# -q@)#q s -s s @ -' -L! o -!*! -G) -))Wx@Ix -))@%xx -G) -))OxAx -))x -G$) - - -$ -@o - - - -'x 'LI! &'()) a ' 'LI! H$ a ' CI#x%>?L> @ -#LGB0 -@ -@ -* - - - @o -I@ -((#LB0 o - - A R K -(@xGB -%B -G -H - -` -x - - - -&xI* -S@& NI HB -@ -N @o -@N @n -$m - -G$) - -' -'x 'LI! &') a ' 'LI! H$ a '#%$ -o - -!L"L%'Le! ,a -* -$ʀ - - - -( -%&&&r !G%@ -G - -S& -@o - -* - -$ @o -&I@u&@x* H"P !&% - - -, - --xB - -G - --J -Fa - - - -+ - - -g -J+J - - -Q -? -RP --L@L+" -@#\ a -L+L -C - -x, -I - - ,DŽP -Ʉ@ @ -I@ ` - I,Db -@x --J - - +-G% -! - --J+ - -x -! - + - @a - -x - b@ʢ c -$"L2@ - - - -CALc -AA K)` -! - - -@ -a $a ' - N, -?G)á -,@ǠA+ -+?aǠA+PCG - - - -ߏN LJ -J2x -@Ȇ - -0 -` - - -@v~ -
@j#LJ - - - - -r - -
I - - -D#G@H
Q -xH@B H@ -Q -Q - -Q -4#@4#G@Q -GG@Q -@ - / -B @ - //G@Q - -@'#G@Q - -;p ; - -GС@ʡ - -G@@!x - - -G -!I@ -R B@h - H -H:
B G) -@!D # -G -G - G -GB G -G - -xQ - -;Gp ; - -GБ@ʡ - - ;R` G)"j ! (! )I - - -@ - -Ϡ -Aaa - -@G1 -N - -I - - -@ -G -Ϡ -Aaa -@ -@ - - - -@x - - - -H - -t - - - -B -sV#sRP G)"j ! - - ( -B @R#BH Q#BP B @ s@IGr @ G - H - - -a -G@GA -I -I - - @ -D#"@ -@x "@ - - -G @?#@A - -G"@ - -+@+@ - - - - - -I - -@ - - -H -AH2: - -h OI -x - -H - II - IAH2: ` - - -AH0 AH! I - -J -AH> ` -xAH> -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -4 - -HB6 - -4 - -HB6 - -4 - -HB6 - - - a - @a - -` - -I - -OAI - n - p - r t O - - -@K2 - - -@ -AH> J -H -` -` - - -A - -ʣ @x - MA@ - - - -H0 - -I - - - -H0 - - -H - -a - @a -H ` - - -" -AAAH o -H J -2X O -b -HAAAH o - - -H @ -Hb -"| AAAH @m - -B@ - - -xHAAAH o - -HAAAH o - - -OAHH -O JB@ - - - -H - - -H -J -OA -"T O -HAAAH o - -H"HAAAH o - - -HAAAH o - - - -AAAH o - - - -
_
-
- -9A - - -9J2@ɗ :H - - - - - -H2@ 2 - -J` JJ` -I -I - -OAH - -O - -H @ - ȇ $H
@d -
c - - - - - -@ - -h O@a - -@AH0 AH( I b - -
J OAJb@ O -# - - - -H": ` -2` O - -*CAf -#G - - -I -
- - - KKa
AK@/ - -IH2 - -xJ
" -$ - - -A1 -@ -~~ -((+@Q R PPCH - - -2@@I -@ F> -o - - -xJ -- - -?AH0 ˂@ɂ@ ʀ -` - --AH> - - - -?AH0 ˂@ɂ@ -
x - - -V AHb4 b@ bH H2 P T B - -@AH> -F AH"< "B AH> @ 2l ˷ aF - - - - - -? - -? - - -? - -? -@ - -` - - - - - -H @H - I -@xI - -@a - I -b -IB -@ - -` - - - - - -H2@"@H -` - -P/@G -H@ - -H0 - - -H0 - -H? "P -J -bI@@ -@bA˷ aF - -b -+" -+.[ - -a .
AB+@+@ - -@U - - -!+A/ - - - -,@l! - - -o - - 00 - -0 -x1! - - - -J` JJ` - -+@+@ - - - - y - -I - -@ - - -H -AH2: -h OI -@x - -H - II - IAH2: ` - - -AH0 AH! I - -J -AH> ` -xAH> -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -4 - -HB6 - -4 - -HB6 - -4 - -HB6 - - - a - @a - -` - -I - -OAI - n - p - r t O@ - - -@ -AH> J -H -` -` - - -A@ - -ʣ @x - MA - - - -H0 - -I - - - -H0 - - -H - -a - @a -H ` - - -" -AAAH o -H J -2X O -b -HAAAH o - - -H @ -Hb -"| AAAH @m - -B@ - - -xHAAAH o - -HAAAH o - - -OAHH -O JB@ - - - -H - - -H -J -OA -"T O -HAAAH o - -H"HAAAH o - - -HAAAH o - - - -AAAH o - - - -
-
- -9A - - -9J2@ɗ :H - - - - - -H2@ 2 - -J` JJ` -I -I - -OAH - -O - -H @ - ȇ $H
f -
@f - - - - - - - -h O@a - -AH0 AH( I b - -
J OAJb@ O -# - - - -H": ` -2` O - -*CAf -#G - - -I -
- - - KKa
AK@/@ - -IH2 - -xJ
" -$ - - -A1 -@ -|~ -((+@Q R PPCH - - -2@@I -@ F> -o - - -xJ -- - -?AH0 ˂@ɂ@ ʀ -` - --AH> - - - -?AH0 ˂@ɂ@ -
x - - -V AHb4 b@ bH H2 P T B - -@AH> -F AH"< "B AH> @ 2l ˷ aF - - - - - -? - -? - - -? - -? -@ - -` - - - - - -H @H - I -@xI - -@a - I -b -IB -@ - -` - - - - - -H2@"@H -` - -P/: -H@ - -H0 - - -H0 - -H? "P -@bA˷ aF - -b -+.[ - -a .
AB+@+@ - -a - - -!+A/ - - - -,@l! - - -o - - 00 - -0 -x1! - - - -J` JJ` - -+@+@ - - - - - -I - -@ - - -H -AH2: # -h OI -x - -H - II - IAH2: ` - - -AH0 AH! I - -J -AH> ` -xAH> -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -4 - -HB6 - -4 - -HB6 - -4 - -HB6 - - - a - @a - -` - -I - -OAI - n - p - r t O - - -@K2 - - -@ -AH> J -H -` -` - - -A - -ʣ @x - MA@ - - - -H0 - -I - - - -H0 - - -H - -a - @a -H ` - - -" -AAAH o -H J -2X O -b -HAAAH o - - -H @ -Hb -"| AAAH @m - -B@ - - -xHAAAH o - -HAAAH o - - -OAHH -O JB@ - - - -H - - -H -J -OA -"T O -HAAAH o - -H"HAAAH o - - -HAAAH o - - - -AAAH o - - - -
@_
-
- -9A - - -9J2@ɗ :H - - - - - -H2@ 2 - -J` JJ` -I -I - -OAH - -O - -H @ - ȇ $H
f -
@f - - - - - - - -h O@a - -@AH0 AH( I b - -
J OAJb@ O -# - - - -H": ` -2` O - -*CAf -#G - - -I -
- - - KKa
AK@/@ - -IH2 - -xJ
" -$ - - -A1 -@ -@|~ -((+@Q R PPCH - - -2@@I -@ F> -o - - -xJ -- - -?AH0 ˂@ɂ@ ʀ -` - --AH> - - - -?AH0 ˂@ɂ@ -
x - - -V AHb4 b@ bH H2 P T B - -@AH> -F AH"< "B AH> @ 2l ˷ aF - - - - - -? - -? - - -? - -? -@ - -` - - - - - -H @H - I -@xI - -@a - I -b -IB -@ - -` - - - - - -H2@"@H -` - -P/: -H@ - -H0 - - -H0 - -H? "P -@bA˷ aF - -b -+.[ - -a .
AB+@+@ - -a - - -!+A/ - - - -,@l! - - -o - - 00 - -0 -x1! - - - -J` JJ` - -+@+@ - - - - y - -I - -@ - - -H -AH2: -h OI -@x - -H - II - IAH2: ` - - -AH0 AH! I - -J -AH> ` -xAH> -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -4 - -HB6 - -4 - -HB6 - -4 - -HB6 - - - a - @a - -` - -I - -OAI - n - p - r t O@ - - -@ -AH> J -H -` -` - - -A@ - -ʣ @x - MA - - - -H0 - -I - - - -H0 - - -H - -a - @a -H ` - - -" -AAAH o -H J -2X O -b -HAAAH o - - -H @ -Hb -"| AAAH @m - -B@ - - -xHAAAH o - -HAAAH o - - -OAHH -O JB@ - - - -H - - -H -J -OA -"T O -HAAAH o - -H"HAAAH o - - -HAAAH o - - - -AAAH o - - - -
-
- -9A - - -9J2@ɗ :H - - - - - -H2@ 2 - -J` JJ` -I -I - -OAH - -O - -H @ - ȇ $H
f -
@f - - - - - - - -h O@a - -AH0 AH( I b - -
J OAJb@ O -# - - - -H": ` -2` O - -*CAf -#G - - -I -
- - - KKa
AK@/@ - -IH2 - -xJ
" -$ - - -A1 -@ -|~ -((+@Q R PPCH - - -2@@I -@ F> -o - - -xJ -- - -?AH0 ˂@ɂ@ ʀ -` - --AH> - - - -?AH0 ˂@ɂ@ -
x - - -V AHb4 b@ bH H2 P T B - -@AH> -F AH"< "B AH> @ 2l ˷ aF - - - - - -? - -? - - -? - -? -@ - -` - - - - - -H @H - I -@xI - -@a - I -b -IB -@ - -` - - - - - -H2@"@H -` - -P/: -H@ - -H0 - - -H0 - -H? "P -@bA˷ aF - -b -+.[ - -a .
AB+@+@ - -a - - -!+A/ - - - -,@l! - - -o - - 00 - -0 -x1! - - - -J` JJ` - -+@+@ - - - -y - -I - -@ - - -H -AH2: @" -h OI -x - -H - II - IAH2: ` - - -AH0 AH! I - -J -AH> ` -xAH> -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -4 - -HB6 - -4 - -HB6 - -4 - -HB6 - - - a - @a - -` - -I - -OAI - n - p - r t O - - -@ -AH> J -H -` -` - - -A - -ʣ @x - MA@ - - - -H0 - -I - - - -H0 - - -H - -a - @a -H ` - - -" -AAAH o -H J -2X O -b -HAAAH o - - -H @ -Hb -"| AAAH @m - -B@ - - -xHAAAH o - -HAAAH o - - -OAHH -O JB@ - - - -H - - -H -J -OA -"T O -HAAAH o - -H"HAAAH o - - -HAAAH o - - - -AAAH o - - - -
@_
-
- -9A - - -9J2@ɗ :H - - - - - -H2@ 2 - -J` JJ` -I -I - -OAH - -O - -H @ - ȇ $H
f -
@f - - - - - - - -h O@a - -AH0 AH( I b - -
J OAJb@ O -# - - - -H": ` -2` O@ - -*CAf -#G - - -I -
- - - KKa
AK@/@ - -IH2 - -xJ
" -$ - - -A1 -@ -}~ -((+@Q R PPCH - - -2@@I -@ F> -o - - -xJ -- - -?AH0 ˂@ɂ@ ʀ -` - --AH> - - - -?AH0 ˂@ɂ@ -
x - - -V AHb4 b@ bH H2 P T B - -@AH> -F AH"< "B AH> @ 2l ˷ aF - - - - - -? - -? - - -? - -? -@ - -` - - - - - -H @H - I -@xI - -@a - I -b -IB -@ - -` - - - - - -H2@"@H -` - -P/: -H@ - -H0 - - -H0 - -H? "P -@bA˷ aF - -b -+.[ - -a .
AB+@+@ - -a - - -!+A/ - - - -,@l! - - -o - - 00 - -0 -x1! - - - -J` JJ` - -+@+@ - - - -y - -I - -@ - - -H -AH2: ) -h OI -x - -H - II - IAH2: ` - - -AH0 AH! I - -J -AH> ` -xAH> -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -4 - -HB6 - -4 - -HB6 - -4 - -HB6 - - - a - @a - -` - -I - -OAI - n - p - r t O - - -@K2 - - -@ -AH> J -H -` -` - - -A - -ʣ @x - MA - - - -H0 - -I - - - -H0 - - -H - -a - @a -H ` - - -" -AAAH o -H J -2X O -b -HAAAH o - - -H @ -Hb -"| AAAH @m - -B@ - - -xHAAAH o - -HAAAH o - - -OAHH -O JB@ - - - -H - - -H -J -OA -"T O -HAAAH o - -H"HAAAH o - - -HAAAH o - - - -AAAH o - - - -
-
- -9A - - -9J2@ɗ :H - - - - - -H2@ 2 - -J` JJ` -I -I - -OAH - -O - -H @ - ȇ $H
-
` - - - - - - -h O@a - -AH0 AH( I b - -
J OAJb@ O -# - - - -H": ` -2` O@ - -*CAf -#G - - -I -
- - - KKa
AK@/ - -IH2 - -xJ
" -$ - - -A1 -@ -~ -((+@Q R PPCH - - -2@@I -@ F> -o - - -xJ -- - -?AH0 ˂@ɂ@ ʀ -` - --AH> - - - -?AH0 ˂@ɂ@ -
x - - -V AHb4 b@ bH H2 P T B - -@AH> -F AH"< "B AH> @ 2l ˷ aF - - - - - -? - -? - - -? - -? -@ - -` - - - - - -H @H - I -@xI - -@a - I -b -IB -@ - -` - - - - - -H2@"@H -` - -P/@G -H@ - -H0 - - -H0 - -H? "P -J -bI@@ -@bA˷ aF - -b -+" -+.[ - -a .
AB+@+@ - -@U - - -!+A/ - - - -,@l! - - -o - - 00 - -0 -x1! - - - -J` JJ` - -+@+@ - - - - - -I - -@ - - -H -AH2: # -h OI -x - -H - II - IAH2: ` - - -AH0 AH! I - -J -AH> ` -xAH> -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -0 - -Hb2 - -4 - -HB6 - -4 - -HB6 - -4 - -HB6 - - - a - @a - -` - -I - -OAI - n - p - r t O - - -@K2 - - -@ -AH> J -H -` -` - - -A - -ʣ @x - MA@ - - - -H0 - -I - - - -H0 - - -H - -a - @a -H ` - - -" -AAAH o -H J -2X O -b -HAAAH o - - -H @ -Hb -"| AAAH @m - -B@ - - -xHAAAH o - -HAAAH o - - -OAHH -O JB@ - - - -H - - -H -J -OA -"T O -HAAAH o - -H"HAAAH o - - -HAAAH o - - - -AAAH o - - - -
@_
-
- -9A - - -9J2@ɗ :H - - - - - -H2@ 2 - -J` JJ` -I -I - -OAH - -O - -H @ - ȇ $H
f -
@f - - - - - - - -h O@a - -@AH0 AH( I b - -
J OAJb@ O -# - - - -H": ` -2` O - -*CAf -#G - - -I -
- - - KKa
AK@/@ - -IH2 - -xJ
" -$ - - -A1 -@ -@|~ -((+@Q R PPCH - - -2@@I -@ F> -o - - -xJ -- - -?AH0 ˂@ɂ@ ʀ -` - --AH> - - - -?AH0 ˂@ɂ@ -
x - - -V AHb4 b@ bH H2 P T B - -@AH> -F AH"< "B AH> @ 2l ˷ aF - - - - - -? - -? - - -? - -? -@ - -` - - - - - -H @H - I -@xI - -@a - I -b -IB -@ - -` - - - - - -H2@"@H -` - -P/: -H@ - -H0 - - -H0 - -H? "P -@bA˷ aF - -b -+.[ - -a .
AB+@+@ - -a - - -!+A/ - - - -,@l! - - -o - - 00 - -0 -x1! - - - -J` JJ` +*wSж!whs9+Π7"*.:k.-.ipj1
9No3y5DF_GOi8T }T{ȏ^"Ōҝ7#SKqSA<~u +j T4sƨ({V08a>5kxtΛŸnŁأ~ۮ0_5`3@Ï04P"##LdWKCAP + @ I` - -y# -x - - -" - -Cc -)L - - -@y +@y` +@y$ + + +@! + + +Cd +)L + + +%% -GGG>%&&&C -D@f -&Lo - - - - +GGG%&&&r !@ G @@ -5079,84 +37,63 @@ GGG>%&&&C Gd J - + Q ? -RP - -C. - - +RP + + ? NI HB -@GA -GACHH -D@b -C - - - - - +@GAǀ +Gr@@>HH + + + o G#LB0 o A R LI - -%£ -H -c -C - -G -@c -&Lo - - -G - - -&Lo - - -Z` - + +% +H +` + + + -@? NI HB +@? NI HB @ - - + +I + + + LJ - -Da -@a - -I - - + + L - - -I -, - - + +L?! + +LJ +J ʧ +q +, +@ +l + l - -x +x +x @ - - -@ -Da -C@ - + q @@ -5164,8 +101,8 @@ x G -A -@#G +1@@u + \ @@ -5174,12 +111,7 @@ H - - -@ -Da -C@ - + q!G` xZ @x @@ -5188,8 +120,8 @@ H G -A -@#G +q] +@#G \ @@ -5215,63 +147,54 @@ GA` @x G - - + + x -I# +I# Hx !#(HH5a @x - -I@ - + QLFLAIH p "@ȁ CL@ -@L@ +@L@ H -a @ - +a + + G - - -ID ` -@~ - -@x@ -I@ - - - -@ - -@a -G -H - - -@ - -@ʢ + + + +x@ +I x + + + + +H + + A Q@ -G +G Z` @ @ -I@@x @@ +I@@x @@ @x - + aH @ - -mmi + +m`@ @a J @@ -5281,7 +204,7 @@ x @ a GLLa H - + x @d @@ -5301,51 +224,47 @@ Q RPPCL @
-L - - - -Da -C@ - -J - -J - b -x @ R - +L +J + r + + GB @x G -@ -C` +@ @x s s - + L! o - -H - + +H + - - - - - - -x -Ct - - + +ǁ +V +GL@H + + +1= + +x +Ct +.GLK.H + +'~ + +P P !x - + /ǣ -Pd@QQ +Pd@QQ ¢R @ BR @@ -5354,25 +273,25 @@ Pd@QQ Q@Q@ bR `a -N D +N D @ Q@Q& - + x/Ǡ t 4T - + B @A
/Ǡ P@PP4@a - - + + I| - I + Iz "p "h bp @@ -5395,13 +314,13 @@ I@ 8 /$ @ -!a "a # Λ +!a "a # Λ ? ?aǠAPCG - - + + -ȁ +ȁ Q @@ -5416,7 +335,7 @@ RP#LG . -miZ +`Z . @@ -5462,35 +381,40 @@ Z Xш PH Ȉ X -H - -H - - - - - - +H +*I*d *AL+CLh j@ j - + + + +2 ! , +x3 + + @ I` - -x# - - - - - -Cc -)L - - -sy +=y` +9y# +x + +@U +" + +Cd +)L + + +% -GGG%&&&r !@ +GGG>%&&&C +D@f +&Lo + + + + G @@ -5511,63 +435,85 @@ GGG%&&&r !@ Gd J - + Q ? -RP@ - - +RPX + +C. + + ? NI HB -@GAǀ -Gr@@HH - - +@GA +GA@gHH +D@b +C + + + + + + + o G#LB0 o A R LI - -% -H -` - - - + +%£ +H +c +C + +G +@c +&Lo + + +G + + +&Lo + + +Z` + -? NI HB +@? NI HB @ - -I - - - + + LJ -@ - + +Da +@a + +I + + L - -L?! - -LJ -J ʧ - - -I -, - - + q + +@ +l + l -x -x +y +x @ - + + +@ +Da +C@ + q @@ -5575,8 +521,8 @@ x G -A - +1@ +@#G \ @@ -5585,7 +531,12 @@ H - + + +@ +Da +C@ + q!G` xZ @x @@ -5594,8 +545,8 @@ H G -A -#G +q +#G \ @@ -5621,53 +572,65 @@ GA` @x G - - + + x -I +I Hx !#(HH5a @x -e# +# +I@ + QLFLAIH p "@ȁ CL@ -@L@ @w +@L@ @ H -a - - +a + G - - - - -I - - - -H - - + + +ID ` +~x + +I@ + + + +@ + +@a +G +H + + + + +@ + +@ʢ A Q@ -G +G Z` @ @ -I@@x @@ +I@@x @@ + @x - + aH @ - -W + +--p @a J @@ -5677,7 +640,7 @@ x @ a GLLa H - + x @d @@ -5697,42 +660,56 @@ Q RPPCL @
-L - +L + + + +Da +C@ + +J + +J b - - +@x @ R + GB @x G -@ +@ +C` @x s s - +@ L! o - -H - + +H + - - - - - -x -Ct -U~ - -P + +ǁ +{ + +GL@H + + +1` + +x +Ct +.GLK.H + +} + P !x - + /ǣ -Pd@QQ +Pd@QQ ¢R @ BR @@ -5741,25 +718,25 @@ Pd@QQ Q@Q@ bR `a -N D +N D @ Q@Q& - + x/Ǡ t 4T - + B @A
/Ǡ P@PP4@a - - + + I| - Iz + I "p "h bp @@ -5782,13 +759,13 @@ I@ 8 /$ @ -!a "a # Λ +!a "a # Λ ? ?aǠAPCG - - + + -ȁ +ȁ Q @@ -5803,7 +780,7 @@ RP#LG . -WZ +-pZ . @@ -5849,25 +826,41 @@ Z Xш PH Ȉ X -H +H + +H + + + + + + +*I*d *AL+CLh j@ j - + + + +2 ! , +x3 + + + @ I` -@x` - - - -@ - -@tyo -Cc -)L - - - +
y` + y$ + + + + + +Cd +)L + + +% GGG%&&&r !@ G @@ -5894,13 +887,14 @@ Gd Q ? -RP +RP* ? NI HB @GAǀ -Gr@
HH - +Gr@;HH + + o G#LB0 o @@ -5911,37 +905,41 @@ G#LB0 o H ` - - + + -? NI HB +@? NI HB @ - + I - - + + LJ - - +@ + L - - -I -, - - + +L?! + +LJ +J ʧ +q +, +@ +l + l -x -x + +x @ - + q @@ -5949,8 +947,8 @@ x G -A -@#G +1@r +#G \ @@ -5959,7 +957,7 @@ H - + q!G` xZ @x @@ -5968,8 +966,8 @@ H G -A - +q +#G \ @@ -5995,52 +993,53 @@ GA` @x G - + x -I@n#n +I Hx !#(HH5a @x -a#@b +# QLFLAIH p "@ȁ CL@ -@L@ s +@L@ @ H -a +a @ G - - - - -I - - - -H - - + + + +x@ +I x + + + + +H + + A Q@ -G +G Z` @ @ -I@@x @@ +I@@x @@ @x - + aH @ - -W + +m`@ @a J @@ -6050,7 +1049,7 @@ x @ a GLLa H - + x @d @@ -6070,11 +1069,11 @@ Q RPPCL @
-L - - b - - +L +J + r + + GB @@ -6084,21 +1083,26 @@ G @ @x s s - +@ L! o - -H - + +H + - - - - - - -x -Ct -Y~ + +ǁ +U + +GL@H + + +1 + +x +Ct +.GLK.H + +@(~ P !x @@ -6176,7 +1180,7 @@ RP#LG . -WZ +`Z . @@ -6222,25 +1226,33 @@ Z Xш PH Ȉ X -H +H +*I*d *AL+CLh j@ j - + + + +2 ! , +x3 + + + @ I` -@x` - - - - - -@vyo -Cc -)L - - - +
y` + y$ + + + + + +Cd +)L + + +% GGG%&&&r !@ G @@ -6267,13 +1279,14 @@ Gd Q ? -RP +RP* ? NI HB @GAǀ -Gr@HH - +Gr@;HH + + o G#LB0 o @@ -6284,23 +1297,23 @@ G#LB0 o H ` - - + + -? NI HB +@? NI HB @ - + I - - + + LJ - - +@ + L @@ -6308,18 +1321,17 @@ H LJ J ʧ - - -I -, - - +q +, +@ +l + l -x -x + +x @ - + q @@ -6327,8 +1339,8 @@ x G -A -#G +1@r +#G \ @@ -6337,7 +1349,7 @@ H - + q!G` xZ @x @@ -6346,8 +1358,8 @@ H G -A -@#G +q +#G \ @@ -6373,53 +1385,53 @@ GA` @x G - + x -Io# +I Hx !#(HH5a @x - +# QLFLAIH p "@ȁ CL@ -@L@ t +@L@ @ H -a @ +a @ G - - - I - - -I - - - -H - - + + + +x@ +I x + + + + +H + + A Q@ -G +G Z` @ @ -I@@x @@ +I@@x @@ @x - + aH @ - -W + +m`@ @a J @@ -6429,7 +1441,7 @@ x @ a GLLa H - + x @d @@ -6449,11 +1461,11 @@ Q RPPCL @
-L - - b - - +L +J + r + + GB @@ -6463,21 +1475,26 @@ G @ @x s s - +@ L! o - -H - + +H + - - - - - - -x -Ct -V~ + +ǁ +U + +GL@H + + +1 + +x +Ct +.GLK.H + +@(~ P !x @@ -6555,7 +1572,7 @@ RP#LG . -WZ +`Z . @@ -6601,25 +1618,33 @@ Z Xш PH Ȉ X -H +H +*I*d *AL+CLh j@ j - + + + +2 ! , +x3 + + + @ I` -@x` - - - - - -@vyo -Cc -)L - - - +y` +y$ + + + + + +Cd +)L + + +%% GGG%&&&r !@ G @@ -6646,13 +1671,14 @@ Gd Q ? -RP +RP@' ? NI HB @GAǀ -Gr@HH - +Gr@8HH + + o G#LB0 o @@ -6663,42 +1689,36 @@ G#LB0 o H ` - - + + -? NI HB +@? NI HB @ - + I - - + +@ LJ - - + + L - -L?! - -LJ -J ʧ - - -I -, - - + q +, +@ +l + l -x -x + +x @ - + q @@ -6706,8 +1726,8 @@ x G -A -#G +1@q +@#G \ @@ -6716,7 +1736,7 @@ H - + q!G` xZ @x @@ -6725,8 +1745,8 @@ H G -A -@#G +qY +#G \ @@ -6752,53 +1772,53 @@ GA` @x G - + x -Io# +I#@ Hx !#(HH5a @x - +@# QLFLAIH p "@ȁ CL@ -@L@ t +@L@ H -a @ +a G - - - I - - -I - - - -H - - + + + +x@ +I x + + + + +H + + A Q@ -G +G Z` @ @ -I@@x @@ +I@@x @@ @x - + aH @ - -W + +m` @a J @@ -6808,7 +1828,7 @@ x @ a GLLa H - + x @d @@ -6828,11 +1848,11 @@ Q RPPCL @
-L - - b - - +L +J + r +x @ R + GB @@ -6842,21 +1862,26 @@ G @ @x s s - + L! o - -H - + +H + - - - - - - -x -Ct -V~ + +ǁ +U + +GL@H + + +1 + +x +Ct +.GLK.H + ++~ P !x @@ -6934,7 +1959,7 @@ RP#LG . -WZ +`Z . @@ -6980,25 +2005,33 @@ Z Xш PH Ȉ X -H +H +*I*d *AL+CLh j@ j - + + + +2 ! , +x3 + + + @ I` - -x# - - - - - -Cc -)L - - -sy +@y` +@y$ + + +@! + + +Cd +)L + + +%% GGG%&&&r !@ G @@ -7025,13 +2058,14 @@ Gd Q ? -RP@ +RP ? NI HB @GAǀ -Gr@@HH - +Gr@@>HH + + o G#LB0 o @@ -7042,23 +2076,23 @@ G#LB0 o H ` - - + + -? NI HB +@? NI HB @ - + I - - + + LJ -@ - + + L @@ -7066,18 +2100,17 @@ H LJ J ʧ - - -I -, - - +q +, +@ +l + l -x -x +x +x @ - + q @@ -7085,8 +2118,8 @@ x G -A - +1@@u + \ @@ -7095,7 +2128,7 @@ H - + q!G` xZ @x @@ -7104,8 +2137,8 @@ H G -A -#G +q] +@#G \ @@ -7131,53 +2164,54 @@ GA` @x G - + x -I +I# Hx !#(HH5a @x -e# + QLFLAIH p "@ȁ CL@ -@L@ @w +@L@ H -a +a G - - - - -I - - - -H - - + + + +x@ +I x + + + + +H + + A Q@ -G +G Z` @ @ -I@@x @@ +I@@x @@ @x - + aH @ - -W + +m`@ @a J @@ -7187,7 +2221,7 @@ x @ a GLLa H - + x @d @@ -7207,11 +2241,11 @@ Q RPPCL @
-L - - b - - +L +J + r + + GB @@ -7221,20 +2255,25 @@ G @ @x s s - + L! o - -H - + +H + - - - - - -x -Ct -U~ + +ǁ +V +GL@H + + +1= + +x +Ct +.GLK.H + +'~ P P @@ -7313,7 +2352,7 @@ RP#LG . -WZ +`Z . @@ -7359,4334 +2398,43 @@ Z Xш PH Ȉ X -H +H +*I*d *AL+CLh j@ j - - -x -@x - - - - - - - - - - - - -` -@ -xI -Ib - - - - -H -H@ - -@Jo - - - -@x - A - -x -@x - - - - -H.. -!H..xH&Hb -'h&@]x - -I# - -#F #-FH - - - - - -` - - - - -E E "` I "d -- ` - BX I- Bx -. -/I/` '( - - - - - - /-" -@x@H -@ - - -I/H -@@@ - - @K -H01DH -HR n - -/@a -I# -@ - - - -~ - - - -@a - @ -> ~ @M@
@LÀ -J -> ~ @M@
@LÀL - - - - -"Ab -!H! -Z -_ I# - -@
x - + -@ -@ - - - - -r - - -.H2 - - -x -x.I -! - -! -J J -@xBX H` -xBP ` - -! -JH H@ -JH -JH JH -A1 - - - xI -@ -ɀ -A - ` -x -"J@ - xI -@ -ɀ -A - ` -x -!"J@ -@@ -@H3
@ -@@ -@"@I -@ -K -K - - - - - -K -3@ - - - - - -3@ - - - -@ "x -I@J@ -B` H I "| -I@J@ -Bh H %G @ B D
"H G "@ I "H "P D @ I B D "@ I "D -HH0HII@HHIHII - -H H -#I H -# H -#ɐ H -$ H -H+I H -+ H -(ɑ H -H( H -H,I H - -R0 - - - -2@@I - - - - -@ - 0 - - 0I 0 -J@ɑ A H@M -@ - -I/2@-@ -@ -n - F> -m - - -/^a Ѐ -J; -bI@@ -%A#$AdIA -# -@#A - -$ @M - - -@3x -$@# -$ -$9#I - - - - - - -W - - - - -$$f -$"x - -%>` - x%` -@)x%> ! d& -d -% -@x -$$$$$ - - -$A$> $ -#Dc/ - -c -d! - -Q f9@ -@xe<&a -d)e -xIa -de -@ x$@@$) a -#: @c@ -c% -fH - - -#$ -d@ -# -f!x& -c -@ -e - - -%` - - -i2 $$$$$ -d - - -f!$e -$< -d&I@ -i2 -d - - -f $$<@ - - - -hr -# - -C@ - -`B -@ -`B - - -( -! '* - -(@o - - - - - - -x
GK` - - - -@A -C -C @ -C O -C C - -` - - -J -@ -ʀ - - -xNCh @xNC@ xNCH @xNCP -K@ - x
@ x
x
@2I - -K@ - -` -JB@Jb@H - -@xNb@ -N@#I - - -\ - -A> - -@b - - -xM@Q -S$S$AL -S - -@@AH> - - - - - -I@ P -IIbIIIb@ -IIRIIIR -I - - -@|s@ -JAHR0 AH! IAH! AHB8 AH0 @ - -A@ -J> -AAAAJ< -A"@@@AH> ` - - - - - -AH> -@I -H -bs@} -} - -[s@ -Jc -s@AHR0 AH! IAH! AAH0 @ - -A@ -J> -AAAAJ< -A"@@@I - -Q s@@I@ a #AH> - - - - - -I - -AH> -^ - - - - - -@ -AH0 H. @AH> H< H: - -@s@} - -AH! AH! AH> -H< AH> @ -H$ IH AH6 @ - -@x -A ` - -A ` -xAH! AH! AH! AH! IAH> - -J -` -x -A> @ -AH0 AHR6 H4 HR* AHB8 HB0 -AHB8 AHR6 HR, HR" -\} - -@ -b - - - -s@JHB -J -s@AH> IH< H26 H4 H2 IS - - - -xFHE!AH> I @ - - - - - -# $I$@x$AH> #H< a - $9I$@9$AH> b - - - - - -*} - - ? -Hr - - - - -s@ -s@ - s@JHB -J -s@% -&@xI&H@ - -J@ɑ H&& -Nx -ȁ &@ -I - a - -J@ɑ H'AH> @a -
@ -@x -@ - -x -H!I A! !A@x A IB -J@ɑ AH> AH> -@I - -( - -AAH> b -bT (` - - - -/I - -Al - )I @ - -@a -I - -((I - - I{DH2@ - - - - - -+ - - $+I$+$x ,AH> a -++ - -H(@a -+ -@x -H#` -@x,,@ -I - -@ AH -@H% -@I - -BH/ - - - -:I& ` -& - - -C - -@ -x -x - - - - - - - - - - - - -` -@ -xI -Ib - - - - -H -H@ - -@Jo - - - -@x - A -@ -x -@x - -@Jx - - -H.. -!H..xH&Hb -'@h&Vx - -I# - - - - -` - -I I L F -ɗ ɗ a -- a .. a - -ER - - -E "` I "d -- ` ~ ..` -ȇ -/I/` '( - - - - - - /-" -@x@H -@ - - -I/H -@@@ - - @K -H01DH -HR n - -/@a -I# -@ - - - -~ - - - -@a - @ -> ~ @M@
@LÀ -J -> ~ @M@
@LÀL - - - - -"Ab -!H! -Z -_ I# - -@
x - + -@ -@ - - - - -@h - - -.H2 - - -x -x.I -! - -! -J J -@xBX H` -xBP ` - -! -JH H@ -JH -JH JH -A1 - - - xI -@ -ɀ -A - ` -x -"J@ - xI -@ -ɀ -A - ` -x -!"J@ -@@ -@H3
@ -@@ -@"@I -@ -K -K - - - - -K -3@ - - - - - -3@ - - - -@ "x -I@J@ -B` H I "| -I@J@ -Bh H %G @ B D
"H G "@ I "H "P D @ I B D "@ I "D -HH0HII@HHIHII - -H H -#I H -# H -#ɐ H -$ H -H+I H -+ H -(ɑ H -H( H -H,I H - -R0 - - - -2@@I - - - - -@ - 0 - - 0I 0 -J@ɑ A H@M -@ - - -/^a Ѐ -$@ -Y@hB&i - -%A#$AdIA -# -@#A - -$ - - - -$@# -$ -$9#I - - - - - - - -W - - - - -$$f -$"x - -%>` - x%` -@)x%> ! d& -d -% -@x -$$$$$ - - -$A$> $ -#Dc/ - -c -d! - -Q f9@ -@xe<&a -d)e -xIa -de -@ x$@@$) a -#: @c@ -c% -fH - - -#$ -d@ -# -f!x& -c -@ -e - - -%` - - -i2 $$$$$ -d - - -f!$e -$< -d&I@ -i2 -d - - -f $$<@ - - - -hr -# - -C@ - -`B -@ -`B - - -( -! '* - -(@o - - - - - - -x
GK` - - - -@A -C -C @ -C O -C C - -` - - -J -@ -ʀ - - -xNCh @xNC@ xNCH @xNCP -K@ - x
@ x
x
<I - -K@ - -` -JB@Jb@H - -@xNb@ -N@ - - -\ - -A> - -@b - - -xM@Q -S$S$AL -S - -@@AH> - - - - - -I@ P -IIbIIIb@ -IIRIIIR -I - - -s@ -JAHR0 AH! IAH! AHB8 AH0 @ - -A@ -J> -AAAAJ< -A"@@@AH> ` - - - - - -AH> -I -H -@ms@@} - - - -J -s@AHR0 AH! IAH! AAH0 @ - -A@ -J> -AAAAJ< -A"@@@@I - - - FI> o - - - - - - -I - -AH> -@] - - - - - -@ -AH0 H. @AH> H< H: - -@%s@} - -AH! AH! AH> -H< AH> @ -H$ IH AH6 @ - -@ -A ` - -A ` -xAH! AH! AH! AH! IAH> - -J -` -x -A> @ -AH0 AHR6 H4 HR* AHB8 HB0 -AHB8 AHR6 HR, HR" -e} - -@ s@@c -b - - - -s@JHB -J -s@AH> IH< H26 H4 H2 I\ - - - -x -@ - - - - -# $I$@x$AH> #H< a - $ - - - -@s@5} - -2} - - ? -Hr - - - - -s@! -s@ - s@JHB -J -s@% -&@xI&H@ - -J@ɑ H&& -Lx -ȁ -I - a - -J@ɑ H'AH> @a -
@@ -@x -@ - -x -H!I A! !A@x A IB -J@ɑ AH> AH> -I - -( - -AAH> b -bT (` - -@((I - -/I - -Al - )I @ - -@a -I - -((I - - I { - -@* + AH* -+ - - $+I$+$x ,AH> a -++@ ,#@ - -H(@a -+ -@x -H#` -@x - - -@ AH -@H% -I - -F> o - - - - -:I& ` -& - - -@ - -x -@x - - - - - - - - - - - - -` -@ -xI -Ib - - - - -H -H@ - -@Jo - - - -@x - A - -x -@x - - - - -H.. -!H..xH&Hb -'h&@]x - -I# - -#F #-FH - - - - - -` - - - - -E E "` I "d -- ` - bT I- bt -. -/I/` '( - - - - - - /-" -@x@H -@ - - -I/H -@@@ - - @K -H01DH -HR n - -/@a -I# -@ - - - -~ - - - -@a - @ -> ~ @M@
@LÀ -J -> ~ @M@
@LÀL - - - - -"Ab -!H! -Z -_ I# - -@
x - + -@ -@ - - - - -r - - -.H2 - - -x -x.I -! - -! -J J -@xBX H` -xBP ` - -! -JH H@ -JH -JH JH -A1 - - - xI -@ -ɀ -A - ` -x -"J@ - xI -@ -ɀ -A - ` -x -!"J@ -@@ -@H3
@ -@@ -@"@I -@ -K -K - - - - - -K -3@ - - - - - -3@ - - - -@ "x -I@J@ -B` H I "| -I@J@ -Bh H %G @ B D
"H G "@ I "H "P D @ I B D "@ I "D -HH0HII@HHIHII - -H H -#I H -# H -#ɐ H -$ H -H+I H -+ H -(ɑ H -H( H -H,I H - -R0 - - - -2@@I - - - - -@ - 0 - - 0I 0 -J@ɑ A H@M -@ - -I/2@-@ -@ -n - F> -m - - -/^a Ѐ -J; -bI@@ -%A#$AdIA -# -@#A - -$ @M - - -@3x -$@# -$ -$9#I - - - - - - -W - - - - -$$f -$"x - -%>` - x%` -@)x%> ! d& -d -% -@x -$$$$$ - - -$A$> $ -#Dc/ - -c -d! - -Q f9@ -@xe<&a -d)e -xIa -de -@ x$@@$) a -#: @c@ -c% -fH - - -#$ -d@ -# -f!x& -c -@ -e - - -%` - - -i2 $$$$$ -d - - -f!$e -$< -d&I@ -i2 -d - - -f $$<@ - - - -hr -# - -C@ - -`B -@ -`B - - -( -! '* - -(@o - - - - - - -x
GK` - - - -@A -C -C @ -C O -C C - -` - - -J -@ -ʀ - - -xNCh @xNC@ xNCH @xNCP -K@ - x
@ x
x
@2I - -K@ - -` -JB@Jb@H - -@xNb@ -N@#I - - -\ - -A> - -@b - - -xM@Q -S$S$AL -S - -@@AH> - - - - - -I@ P -IIbIIIb@ -IIRIIIR -I - - -@|s@ -JAHR0 AH! IAH! AHB8 AH0 @ - -A@ -J> -AAAAJ< -A"@@@AH> ` - - - - - -AH> -@I -H -bs@} -} - -[s@ -Jc -s@AHR0 AH! IAH! AAH0 @ - -A@ -J> -AAAAJ< -A"@@@I - -Q s@@I@ a #AH> - - - - - -I - -AH> -^ - - - - - -@ -AH0 H. @AH> H< H: - -@s@} - -AH! AH! AH> -H< AH> @ -H$ IH AH6 @ - -@x -A ` - -A ` -xAH! AH! AH! AH! IAH> - -J -` -x -A> @ -AH0 AHR6 H4 HR* AHB8 HB0 -AHB8 AHR6 HR, HR" -\} - -@ -b - - - -s@JHB -J -s@AH> IH< H26 H4 H2 IS - - - -xFHE!AH> I @ - - - - - -# $I$@x$AH> #H< a - $9I$@9$AH> b - - - - - -*} - - ? -Hr - - - - -s@ -s@ - s@JHB -J -s@% -&@xI&H@ - -J@ɑ H&& -Nx -ȁ &@ -I - a - -J@ɑ H'AH> @a -
@ -@x -@ - -x -H!I A! !A@x A IB -J@ɑ AH> AH> -@I - -( - -AAH> b -bT (` - - - -/I - -Al - )I @ - -@a -I - -((I - - I{DH2@ - - - - - -+ - - $+I$+$x ,AH> a -++ - -H(@a -+ -@x -H#` -@x,,@ -I - -@ AH -@H% -@I - -BH/ - - - -:I& ` -& - - -C -y - - -x -x -@x - - - - - - - - - - -` -@ -xI -Ib - - - - -H -H@ - -@Jo - - - -@x - A - -x -@x - - - - -H.. -!H..xH&Hb -' - -I# - -@c -@ - - - -` - -I I L F -ɗ ɗ a -- a .. a - -ER - - -
- I H --- ` /J/J` HR@ -- -@ -ȇ -/I/` '( - - - - - - /-" -@x@H -@ - - -I/H -@@@ - - @K -H01DH -HR n - -/@a -I# - - - - - - - - -@a - @ -> ~ @M@
@LÀ -J -> ~ @M@
@LÀL - - - - - b -H - - - -: -"Ab -!H! - -_ I# - -x - + -@ -@@ - - - - - -@u - - -.H2 - - -x -x.I -! - -! -J J -@xBX H` -xBP ` - -! -JH H@ -JH -JH JH -A1 - - - xI -@ -ɀ -A - ` -x -"J@ - xI -@ -ɀ -A - ` -x -!"J@ -@@ -@H3
@ -@@ -@"@I -@ -K -K - - - - -K -3@ - - - - - -3@ - - - -@ "x -I@J@ -B` H I "| -I@J@ -Bh H %G @ B D
"H G "@ I "H "P D @ I B D "@ I "D -HH0HII@HHIHII - -H H -#I H -# H -#ɐ H -$ H -H+I H -+ H -(ɑ H -H( H -H,I H - -R0 - - - -2@@I - - - - -@ - 0 - - 0I 0 -J@ɑ A H@M -@ - - -/^a Ѐ -$@ -Y@hB&i - - -J; -bI@ -%A#$AdIA -# -@#A - -$ - - - -$@# -$ -$9#I - - - - - - - -W - - - - -$$f -$"x - -%>` - x%` -@)x%> ! d& -d -% -@x -$$$$$ - - -$A$> $ -#Dc/ - -c -d! - -Q f9@ -@xe<&a -d)e -xIa -de -@ x$@@$) a -#: @c@ -c% -fH - - -#$ -d@ -# -f!x& -c -@ -e - - -%` - - -i2 $$$$$ -d - - -f!$e -$< -d&I@ -i2 -d - - -f $$<@ - - - -hr -# - -C@ - -`B -@ -`B - - -( -! '* -@ - - - - - -x
GK` - - - -@A -C -C @ -C O -C C - -` - - -J -@ -ʀ - - -xNCh @xNC@ xNCH @xNCP -K@ - x
@ x
x
@7I - -K@ - -` -JB@Jb@H - -@xNb@ -N@(I - - -\ - -A> - -@b - - -xM@Q -S$S$AL -S - -@@AH> - - - - - -I@ P -IIbIIIb@ -IIRIIIR -I - - -@@CHg@@ - - - -@s@ -JAHR0 AH! IAH! AHB8 AH0 @ - -A@ -J> -AAAAJ< -A"@@@AH> ` - - - - - -AH> -@I -H - -} - -s@ -J' -s@AHR0 AH! IAH! AAH0 @ - -A@ -J> -AAAAJ< -A"@@@I - - s@@I~@~ a #A R - FI> o - - - - - -@s -I - -AH> -@ - - - - - -P -AH0 H. @AH> H< H: - - - -AH! AH! AH> -H< AH> @ -H$ IH AH6 @ - -9 -A ` - -A ` -xAH! AH! AH! AH! IAH> -,I -J -` -x -A> @ -AH0 AHR6 H4 HR* AHB8 HB0 -AHB8 AHR6 HR, HR" -@} - - -b - - -@M -s@JHB -J@E -s@AH> IH< H26 H4 H2 I - - - -xH!AH> I @ - - - - - -# $I$@x$AH> #H< a - $I$ - - - - - -@~} - - ? -Hr - - - - -s@r -s@ -
s@JHB -J -s@% -&@xI&H@ - -J@ɑ H&& -Lx -ȁ c&@ -I - a - -J@ɑ H'AH> @a -
@@1 -@x -@ - -x -H!I A! !A@x A IB -J@ɑ AH> AH> - - -( - -AAH> b -bT (` - ->((I - -/I @T - -Al - )I @ - -@a -I - -((I - - I { - -'*@' + AH* -+ - - $+I$+$x ,AH> a -+@+ ,#@ - -H(@a -+ -@x -H#` -@x,,@ -I - -@ AH -@H% - - -F> o - - - - -:I& ` -& - - - -A@ - - - - -E -Q -@ -R -@ -P -PCJ -Q -@ -R -@ -P -PCJ -SC -o - -A - - HNB - - - -T "< K - -ɢ -h "< - -ɢ( ɢ ʢ - -@ -T -2@K
- - -B -AaJ` - -" -"0 -r Ҡ - -r2 Ҡ - r Ҡ - r2 Ҡ - - -@ - - -
K -
K
3 -
- D H - D - D Ȁ - -H - - - - - - - - - -x -@x - - - - - - - - - - - - -` -@ -xI -Ib - - - - -H -H@ - -@Jo - - - -@x - A - -x -@x - - - - -H.. -!H..xH&Hb -'h&@]x - -I# - -#F #-FH - - - - - -` - - - - -E E "` I "d -- ` - BX I- Bx -. -/I/` '( - - - - - - /-" -@x@H -@ - - -I/H -@@@ - - @K -H01DH -HR n - -/@a -I# -@ - - - -~ - - - -@a - @ -> ~ @M@
@LÀ -J -> ~ @M@
@LÀL - - - - -"Ab -!H! -Z -_ I# - -@
x - + -@ -@ - - - - -r - - -.H2 - - -x -x.I -! - -! -J J -@xBX H` -xBP ` - -! -JH H@ -JH -JH JH -A1 - - - xI -@ -ɀ -A - ` -x -"J@ - xI -@ -ɀ -A - ` -x -!"J@ -@@ -@H3
@ -@@ -@"@I -@ -K -K - - - - - -K -3@ - - - - - -3@ - - - -@ "x -I@J@ -B` H I "| -I@J@ -Bh H %G @ B D
"H G "@ I "H "P D @ I B D "@ I "D -HH0HII@HHIHII - -H H -#I H -# H -#ɐ H -$ H -H+I H -+ H -(ɑ H -H( H -H,I H - -R0 - - - -2@@I - - - - -@ - 0 - - 0I 0 -J@ɑ A H@M -@ - -I/2@-@ -@ -n - F> -m - - -/^a Ѐ -J; -bI@@ -%A#$AdIA -# -@#A - -$ @M - - -@3x -$@# -$ -$9#I - - - - - - -W - - - - -$$f -$"x - -%>` - x%` -@)x%> ! d& -d -% -@x -$$$$$ - - -$A$> $ -#Dc/ - -c -d! - -Q f9@ -@xe<&a -d)e -xIa -de -@ x$@@$) a -#: @c@ -c% -fH - - -#$ -d@ -# -f!x& -c -@ -e - - -%` - - -i2 $$$$$ -d - - -f!$e -$< -d&I@ -i2 -d - - -f $$<@ - - - -hr -# - -C@ - -`B -@ -`B - - -( -! '* - -(@o - - - - - - -x
GK` - - - -@A -C -C @ -C O -C C - -` - - -J -@ -ʀ - - -xNCh @xNC@ xNCH @xNCP -K@ - x
@ x
x
@2I - -K@ - -` -JB@Jb@H - -@xNb@ -N@#I - - -\ - -A> - -@b - - -xM@Q -S$S$AL -S - -@@AH> - - - - - -I@ P -IIbIIIb@ -IIRIIIR -I - - -@|s@ -JAHR0 AH! IAH! AHB8 AH0 @ - -A@ -J> -AAAAJ< -A"@@@AH> ` - - - - - -AH> -@I -H -bs@} -} - -[s@ -Jc -s@AHR0 AH! IAH! AAH0 @ - -A@ -J> -AAAAJ< -A"@@@I - -Q s@@I@ a #AH> - - - - - -I - -AH> -^ - - - - - -@ -AH0 H. @AH> H< H: - -@s@} - -AH! AH! AH> -H< AH> @ -H$ IH AH6 @ - -@x -A ` - -A ` -xAH! AH! AH! AH! IAH> - -J -` -x -A> @ -AH0 AHR6 H4 HR* AHB8 HB0 -AHB8 AHR6 HR, HR" -\} - -@ -b - - - -s@JHB -J -s@AH> IH< H26 H4 H2 IS - - - -xFHE!AH> I @ - - - - - -# $I$@x$AH> #H< a - $9I$@9$AH> b - - - - - -*} - - ? -Hr - - - - -s@ -s@ - s@JHB -J -s@% -&@xI&H@ - -J@ɑ H&& -Nx -ȁ &@ -I - a - -J@ɑ H'AH> @a -
@ -@x -@ - -x -H!I A! !A@x A IB -J@ɑ AH> AH> -@I - -( - -AAH> b -bT (` - - - -/I - -Al - )I @ - -@a -I - -((I - - I{DH2@ - - - - - -+ - - $+I$+$x ,AH> a -++ - -H(@a -+ -@x -H#` -@x,,@ -I - -@ AH -@H% -@I - -BH/ - - - -:I& ` -& - - -C - -x -@x - - - - - - - - - - - - -` -@ -xI -Ib - - - - -H -H@ - -@Jo - - - -@x - A - -x -@x - - - - -H.. -!H..xH&Hb -'h&@]x - -I# - -#F #-FH - - - - - -` - - - - -E E "` I "d -- ` - BX I- Bx -. -/I/` '( - - - - - - /-" -@x@H -@ - - -I/H -@@@ - - @K -H01DH -HR n - -/@a -I# -@ - - - -~ - - - -@a - @ -> ~ @M@
@LÀ -J -> ~ @M@
@LÀL - - - - -"Ab -!H! -Z -_ I# - -@
x - + -@ -@ - - - - -r - - -.H2 - - -x -x.I -! - -! -J J -@xBX H` -xBP ` - -! -JH H@ -JH -JH JH -A1 - - - xI -@ -ɀ -A - ` -x -"J@ - xI -@ -ɀ -A - ` -x -!"J@ -@@ -@H3
@ -@@ -@"@I -@ -K -K - - - - - -K -3@ - - - - - -3@ - - - -@ "x -I@J@ -B` H I "| -I@J@ -Bh H %G @ B D
"H G "@ I "H "P D @ I B D "@ I "D -HH0HII@HHIHII - -H H -#I H -# H -#ɐ H -$ H -H+I H -+ H -(ɑ H -H( H -H,I H - -R0 - - - -2@@I - - - - -@ - 0 - - 0I 0 -J@ɑ A H@M -@ - -I/2@-@ -@ -n - F> -m - - -/^a Ѐ -J; -bI@@ -%A#$AdIA -# -@#A - -$ @M - - -@3x -$@# -$ -$9#I - - - - - - -W - - - - -$$f -$"x - -%>` - x%` -@)x%> ! d& -d -% -@x -$$$$$ - - -$A$> $ -#Dc/ - -c -d! - -Q f9@ -@xe<&a -d)e -xIa -de -@ x$@@$) a -#: @c@ -c% -fH - - -#$ -d@ -# -f!x& -c -@ -e - - -%` - - -i2 $$$$$ -d - - -f!$e -$< -d&I@ -i2 -d - - -f $$<@ - - - -hr -# - -C@ - -`B -@ -`B - - -( -! '* - -(@o - - - - - - -x
GK` - - - -@A -C -C @ -C O -C C - -` - - -J -@ -ʀ - - -xNCh @xNC@ xNCH @xNCP -K@ - x
@ x
x
@2I - -K@ - -` -JB@Jb@H - -@xNb@ -N@#I - - -\ - -A> - -@b - - -xM@Q -S$S$AL -S - -@@AH> - - - - - -I@ P -IIbIIIb@ -IIRIIIR -I - - -@|s@ -JAHR0 AH! IAH! AHB8 AH0 @ - -A@ -J> -AAAAJ< -A"@@@AH> ` - - - - - -AH> -@I -H -bs@} -} - -[s@ -Jc -s@AHR0 AH! IAH! AAH0 @ - -A@ -J> -AAAAJ< -A"@@@I - -Q s@@I@ a #AH> - - - - - -I - -AH> -^ - - - - - -@ -AH0 H. @AH> H< H: - -@s@} - -AH! AH! AH> -H< AH> @ -H$ IH AH6 @ - -@x -A ` - -A ` -xAH! AH! AH! AH! IAH> - -J -` -x -A> @ -AH0 AHR6 H4 HR* AHB8 HB0 -AHB8 AHR6 HR, HR" -\} - -@ -b - - - -s@JHB -J -s@AH> IH< H26 H4 H2 IS - - - -xFHE!AH> I @ - - - - - -# $I$@x$AH> #H< a - $9I$@9$AH> b - - - - - -*} - - ? -Hr - - - - -s@ -s@ - s@JHB -J -s@% -&@xI&H@ - -J@ɑ H&& -Nx -ȁ &@ -I - a - -J@ɑ H'AH> @a -
@ -@x -@ - -x -H!I A! !A@x A IB -J@ɑ AH> AH> -@I - -( - -AAH> b -bT (` - - - -/I - -Al - )I @ - -@a -I - -((I - - I{DH2@ - - - - - -+ - - $+I$+$x ,AH> a -++ - -H(@a -+ -@x -H#` -@x,,@ -I - -@ AH -@H% -@I - -BH/ - - - -:I& ` -& - - -C - -x -x - - - - - - - - - - - - -` -@ -xI -Ib - - - - -H -H@ - -@Jo - - - -@x - A - -x -N -@x - -Nx - - -H.. -!H..xH&Hb -'h&bx - -I# - -@c -@ - - - -` - -I I L F -ɗ ɗ a -- a .. a - -ER - - -E "` I "d -- ` ~ ..` -ȇ -/I/` '( - - - - - - /-" -@x@H -@ - - -I/H -@@@ - - @K -H01DH -HR n - -/@a -I# -@ - - - - - - - -@a - @ -> ~ @M@
@LÀ -J -> ~ @M@
@LÀL - - - - - b -H - - - -@9 -"Ab -!H! -Z -_ I# - -@
x - + -@ -@ - - - - -@u - - -.H2 - - -x -x.I -! - -! -J J -@xBX H` -xBP ` - -! -JH H@ -JH -JH JH -A1 - - - xI -@ -ɀ -A - ` -x -"J@ - xI -@ -ɀ -A - ` -x -!"J@ -@@ -@H3
@ -@@ -@"@I -@ -K -K - - - - -K -3@ - - - - - -3@ - - - -@ "x -I@J@ -B` H I "| -I@J@ -Bh H %G @ B D
"H G "@ I "H "P D @ I B D "@ I "D -HH0HII@HHIHII - -H H -#I H -# H -#ɐ H -$ H -H+I H -+ H -(ɑ H -H( H -H,I H - -R0 - - - -2@@I - - - - -@ - 0 - - 0I 0 -J@ɑ A H@M -@ - - -/^a Ѐ -$@ -Y@hB&i - - -J; -bI@ -%A#$AdIA -# -@#A - -$ - - - -$@# -$ -$9#I - - - - - - - -W - - - - -$$f -$"x - -%>` - x%` -@)x%> ! d& -d -% -@x -$$$$$ - - -$A$> $ -#Dc/ - -c -d! - -Q f9@ -@xe<&a -d)e -xIa -de -@ x$@@$) a -#: @c@ -c% -fH - - -#$ -d@ -# -f!x& -c -@ -e - - -%` - - -i2 $$$$$ -d - - -f!$e -$< -d&I@ -i2 -d - - -f $$<@ - - - -hr -# - -C@ - -`B -@ -`B - - -( -! '* - -(@o - - - - - - -x
GK` - - - -@A -C -C @ -C O -C C - -` - - -J -@ -ʀ - - -xNCh @xNC@ xNCH @xNCP -K@ - x
@ x
x
/I - -K@ - -` -JB@Jb@H - -@xNb@ -N@ - - -\ - -A> - -@b - - -xM@Q -S$S$AL -S - - -@@AH> - - - - - -I@ P -IIbIIIb@ -IIRIIIR -I - - -ys@ -JAHR0 AH! IAH! AHB8 AH0 @ - -A@ -J> -AAAAJ< -A"@@@AH> ` - - - - - -AH> -I -H -@`s@@} - - - -J -s@AHR0 AH! IAH! AAH0 @ - -A@ -J> -AAAAJ< -A"@@@@I - - - FI> o - - - - - - -I - -AH> -@] - - - - - -@ -AH0 H. @AH> H< H: - -@s@} - -AH! AH! AH> -H< AH> @ -H$ IH AH6 @ - -@t -A ` - -A ` -xAH! AH! AH! AH! IAH> - -J -` -x -A> @ -AH0 AHR6 H4 HR* AHB8 HB0 -AHB8 AHR6 HR, HR" -X} - -@ s@@V -b - - - -s@JHB -J -s@AH> IH< H26 H4 H2 IO - - - -x -@ - - - - -# $I$@x$AH> #H< a - $ - - - -@s@(} - -%} - - ? -Hr - - - - -s@! -s@ - s@JHB -J -s@% -&@xI&H@ - -J@ɑ H&& -Lx -ȁ -I - a - -J@ɑ H'AH> @a -
@@ -@x -@ - -x -H!I A! !A@x A IB -J@ɑ AH> AH> -I - -( - -AAH> b -bT (` - -@((I - -/I - -Al - )I @ - -@a -I - -((I - - I { - -@* + AH* -+ - - $+I$+$x ,AH> a -++@ ,#@ - -H(@a -+ -@x -H#` -@x - - -@ AH -@H% -I - -F> o - - - - -:I& ` -& - - -@ - -x -x - - - - - - - - - - - - -` -@ -xI -Ib - - - - -H -H@ - -@Jo - - - - -@x - A - -x -@x - -@Kx - - -H.. -!H..xH&Hb -'h&Wx - -I# - - - - - -` - - - - -E E "` I "d -- ` - BX I- Bx -. -/I/` '( - - - - - - /-" -@x@H -@ - - -I/H -@@@ - - @K -H01DH -HR n - -/@a -I# -@ - - - -~ - - - -@a - @ -> ~ @M@
@LÀ -J -> ~ @M@
@LÀL - - - - -"Ab -!H! -Z -_ I# - -@
x - + -@ -@ - - - - -e - - -.H2 - - -x -x.I -! - -! -J J -@xBX H` -xBP ` - -! -JH H@ -JH -JH JH -A1 - - - xI -@ -ɀ -A - ` -x -"J@ - xI -@ -ɀ -A - ` -x -!"J@ -@@ -@H3
@ -@@ -@"@I -@ -K -K - - - - -K -3@ - - - - - -3@ - - - -@ "x -I@J@ -B` H I "| -I@J@ -Bh H %G @ B D
"H G "@ I "H "P D @ I B D "@ I "D -HH0HII@HHIHII - -H H -#I H -# H -#ɐ H -$ H -H+I H -+ H -(ɑ H -H( H -H,I H - -R0 - - - -2@@I - - - - -@ - 0 - - 0I 0 -J@ɑ A H@M -@ - -I/2@-@ - - - F> -@n - - -/^a Ѐ -%A#$AdIA -# -@#A - -$ @M - - -@3x -$@# -$ -$9#I - - - - - - -W - - - - -$$f -$"x - -%>` - x%` -@)x%> ! d& -d -% -@x -$$$$$ - - -$A$> $ -#Dc/ - -c -d! - -Q f9@ -@xe<&a -d)e -xIa -de -@ x$@@$) a -#: @c@ -c% -fH - - -#$ -d@ -# -f!x& -c -@ -e - - -%` - - -i2 $$$$$ -d - - -f!$e -$< -d&I@ -i2 -d - - -f $$<@ - - - -hr -# - -C@ - -`B -@ -`B - - -( -! '* - -(@o - - - - - - -x
GK` - - - -@A -C -C @ -C O -C C - -` - - -J -@ -ʀ - - -xNCh @xNC@ xNCH @xNCP -K@ - x
@ x
x
?I - -K@ - -` -JB@Jb@H - -@xNb@ -N@0I - - -\ - -A> - -@b - - -xM@Q -S$S$AL -S - -@@AH> - - - - - -I@ P -IIbIIIb@ -IIRIIIR -I - - -s@ -JAHR0 AH! IAH! AHB8 AH0 @ - -A@ -J> -AAAAJ< -A"@@@AH> ` - - - - - -AH> -I -H - -} - -hs@ -Jp -s@AHR0 AH! IAH! AAH0 @ - -A@ -J> -AAAAJ< -A"@@@ - -^ s@I - @I@ @I AH> ` - - - - -I - -AH> -^ - - - - - - -AH0 H. @AH> H< H: - -)s@} - -AH! AH! AH> -H< AH> @ -H$ IH AH6 @ - - -A ` - -A ` -xAH! AH! AH! AH! IAH> -@xI -J -` -x -A> @ -AH0 AHR6 H4 HR* AHB8 HB0 -AHB8 AHR6 HR, HR" - - -
s@g -b - - - -s@JHB -J -s@AH> IH< H26 H4 H2 I` - - - -x -@ - - - - -# $I$@x$AH> #H< a - $ - - - -@s@:} - -7} - - ? -Hr - - - - -s@ -s@ - s@JHB -J -s@% -&@xI&H@ - -J@ɑ H&& -Nx -ȁ -I - a - -J@ɑ H'AH> @a -
@ -@x -@ - -x -H!I A! !A@x A IB -J@ɑ AH> AH> -I - -( - -AAH> b -bT (` - -@((I - -/I - -Al - )I @ - -@a -I - -((I - - I{DH2@ - - - - -@* + AH* -+ - - $+I$+$x ,AH> a -++@ ,#@ - -H(@a -+ -@x -H#` -@x - - -@ AH -@H% -I - -BH/ - - - -:I& ` -& - - -C + + + +2 ! , +x3 + + + +@x +Ȁ + +#$O +6
+ + +H + +H +@p +6
+@ + +% +x +Ȁ + + + +H + +x +@ @ I` x` @@ -11703,10 +2451,10 @@ G" +y &&& H@o@ - +
-J - +J + @Aɑ @@ -11812,12 +2560,13 @@ CL@ a Fx@b - -Sx + +Sx @ 9x8 -Ȉ +Ȉ + @(x x@ @@ -11854,20 +2603,20 @@ G GGb m6 m\ --mNLǁ@3 +-mNLǁ@3 G` - +
x" G. x r@" - + %G - + -xH +x @@ -11947,13 +2696,13 @@ I ( ( G - -x +xU +@x @@#L - + W @@!NU - + @V @c @@ -11962,7 +2711,7 @@ I Gx -2@ +2@ b I Gp G` NG G @@ -11973,11 +2722,11 @@ xI Gp G` K"\ GX NI I - + @ x x - + x @@ -12073,13 +2822,13 @@ H ` x -@x@x - -x!eJ +@x@x + +x!hJ - - +] + @@ -12089,18 +2838,18 @@ x!eJ H -H +H - - - + + + G$ -G +G , @@ -12144,7 +2893,7 @@ H&ȁ Gt Gt (I( *SI - + @@ -12174,7 +2923,7 @@ HCP
HCX
"@Ir C C @ Ir C C 3 -C C B LCH +C C B LCH @ I` x` @@ -12662,7 +3411,7 @@ HCP
HCX
"@Ir C C @ Ir C C 3 -C C B LCH +C C B LCH @ I` x` @@ -12679,10 +3428,10 @@ G" +y &&& H@o@ -
+ -J - +J + @Aɑ @@ -12788,13 +3537,12 @@ CL@ a Fx@b - -Sx + +Sx @ 9x8 -Ȉ - +Ȉ @(x x@ @@ -12831,20 +3579,20 @@ G GGb m6 m\ --mNLǁ@3 +-mNLǁ@3 G` - +
x" G. x r@" - + %G - + -x +xH @@ -12924,13 +3672,13 @@ I ( ( G -xU -@x + +x @@#L - + W @@!NU - + @V @c @@ -12939,7 +3687,7 @@ I Gx -2@ +2@ b I Gp G` NG G @@ -12950,11 +3698,11 @@ xI Gp G` K"\ GX NI I - + @ x x - + x @@ -13050,13 +3798,13 @@ H ` x -@x@x - -x!hJ +@x@x + +x!eJ -] - + + @@ -13066,18 +3814,18 @@ x!hJ H -H +H - - - + + + G$ -G +G , @@ -13121,7 +3869,7 @@ H&ȁ Gt Gt (I( *SI - + @@ -13151,7 +3899,7 @@ HCP
HCX
"@Ir C C @ Ir C C 3 -C C B LCH +C C B LCH @ I` x` @@ -13639,7 +4387,7 @@ HCP
HCX
"@Ir C C @ Ir C C 3 -C C B LCH +C C B LCH @ I` x` @@ -14127,19 +4875,426 @@ HCP
HCX
"@Ir C C @ Ir C C 3 -C C B LCH -3 - - - -ɑ zI -+ @ -I` - zɀ` -y -@&xP - ->x@<x +C C B LCH +I +v +G +@2x +Ha + +@2xU +IL + + + +x + +@
xZ +@ +G2 + + +A + + +x + + + +@ +H +. +ta +- +mx +0 +G7 +mWBl + +HR + II + + + + +@Lr@ǁ + +@x +I + + + + y + +xB ! +H@ + + +
+H + + + +] + +
A +E + +1@D!D A +1@D!H DA +1@D!L E) +, +E A E +F A G +H A EH +` +@x +$@@d x +$@d*LDA +Q + + +M3 +M
AH a t + + + +2a +-Iȁ +@L3 +Ā` +!x +U +T%H @ID +T%H @ID +T%H @ID +U +I@ +v +G +@2x +Ha + +@2xU@ +IL + + + +x + +@
xZ@ + +G2 + + +A + + +x + + + + +H +. +ta +- +px +0 +G7 +mWBl + +HR + II + + + + +@Lr@ǁ + +@x +I + + + + + +x +H@ + +@ +H + +@ + +@b + +
A +E +T +1@D!D A +1@D!H DA +1@D!L E) +, +E A +$E +4XA +F A +$G +4XFA +H A +""$EH +#4#X +` +x + +$@ +$@ +Q + + +Q + +M3 +M
AH a t + + + + +2a +-Iȁ +@L3 +Ā` +!x +U +T%H @ID +T%H @ID +T%H @ID +U +I + +v +G +@2x +Ha + +@2xU@ +IL + + + +x + +@
xZ@ + +G2 + + +A + + +x + + + + +H +. +ta +- +@nx +0 +G7 +mWBl0PmJPn + +HR + II + + + + +@Lr@ǁ + +@x +I + + + + { + +xB ! +H@ + + +
+H + + + +_ + +
A +E + +1@D!D A +1@D!H DA +1@D!L E) +, +E A E +F A G +H A EH +` +@x +$@@d!x +$@d*LDA +Q +& + +M3@ +M
AH a t + + + +2a +-Iȁ + + +Ā` +!x +U +T%H @ID +T%H @ID +T%H @ID +U +I@ + +v +G +@2x +Ha + +@2xU +IL + + + +x + +@
xZ +@ +G2 + + +A + + +x + + + + +H +. +ta +- + +0 +G7 +mWBl0PmJPn + +HR + II + + + + +@Lr@ǁ + +@x +I + + + + + +x +H@ + +@ +H + +@| + +@d + +
A +E +V +1@D!D A +1@D!H DA +1@D!L E) +, +E A +$E +4XA +F A +$G +4XFA +H A +""$EH +#4#X +` +x + +$@ +$@ +Q +&@x + +Q + +M3@ +M
AH a t + + + + +2a +-Iȁ + + +Ā` +!x +U +T%H @ID +T%H @ID +T%H @ID +U + + + + + + + + + x +B< + +@ +? +C +# +-0 + + +ɑ @}zI +GL + + + +@Rx + @@ -14149,11 +5304,11 @@ I` J@
J -.8@ +.8 GI , O -I@ +I@ I o @@ -14163,113 +5318,143 @@ I@ bp - + 4I Q RPPCL @J A -A +A & % ( \ !p! - -J + +J -LJ -@ +LJ + + + +@xR +a +A + +@xJ e +B +a +xH +: H G G@ ` -x
` +xɂ` x
-xvG` -@x@x@x +x}G` +@x QL -FLHAȂ +FL@LBLȂ@ + G - - -q@ + + +q@ + + + + + t + + - - - -B - -<B/L% L' @ 0@ + +IJ +Iʁ + + + + +Lʥ +% +B@Ȃ + + + + + + -G +G -GI -@LBLAQ -` - - -$ +GI +I +d + +` + + +)I +$@ - - -@x$@ -W(Ǥ -*e@-UU -\!@xU@-U +2x@*x' + +@x$ +V' +V)` +-GI` +W +*e@-UU +\!xU@-U ¢V -@TeP W| NB -EE@ +@TeP W| NB +EE@ BV @@xAՀe -&N U -TeP W| NB -U@%$U@x$&) +&N E +TeP W| NB +U@%$U@x$&) bV `aV0 -&N U'$ - +&N U'@$ +&U $` - + - u V,E + u V,E @ - - + + B @A
Ǡ - -A +&@@ +A @@x -NNN@ - +NNN@ + @@ II24 A" - Iɐ ɐ @ IIR + Iɐ ɐ @ I -@I@ -I + + -K -K -@@ -@ -G - -<G +K +K < ` xJ @@ -14288,187 +5473,673 @@ H" xJ 3@ G4 - - -~ $ -H -H -! - -N,x - - -sx -@ - -S - x.I,J) + +@x.I,J) ` ,@ I -,@Ȅ@ -,
- -@ǠA+,- - -G +,@Ȅ@ -, +@ǠA+,- + + +G ;H -% < - +@ I - +@ H H@a -H +H + ;I - + -GǑ@ʡ -;GR N;3 -xH;;G - -G @ +GǑ@ʡ -GH;ȡ@ʡ - - +GH;ȡ@ʡ + -G @@ +G @@ -G ; +G -G @@ -I; - - J - - +G @ + +G @ +I; +B + J +J + J9 - - -J -G!a +@b +; + - + !sstG @b - + GuuG - + @b - - x2 + +x + + +~ + + +o + + +H + $ɀ +@Ip p QIs Q #G)!D G)c + +P;! + + + + + + -< - - - -J -@b + + +G,",@a +QI + + +Q +? +R + + +ȼo + + +@ +G + + + ++ +! * +x, + +*I + + @c@r +G# +# +q@)#q s +s s @ +' +L! o +!*! +G) +))Wx@Ix +))@%xx +G) +))OxAx +))x +G$) + + +$ +@o + + + +'x 'LI! &'()) a ' 'LI! H$ a ' CI#x%>?L> @ +#LGB0 +@ +@ +* + + + @o +I@ +((#LB0 o + + A R K +(@xGB +%B +G +H + +` +x + + + + +S@& NI HB +@ +N @o +@N @n +$m + +G$) + +' +'x 'LI! &') a ' 'LI! H$ a '#%$ +o + +!L"L%'Le! ,a +* +$ʀ -. + + +( +%&& +G + +S& +@\ +* + +$ @o +&I@b&@x* H"P !&% + + +, + +-xB + +G - -J - +-J +Fa + - - - - - - - -~; - - - - -@~G . G. GGs$$ + ++D + + +Ǡ +@x + + +Q +? +RP +-L@L+" +@#\ a +L+L + + +x, +I + + ,DŽP -Ʉ@ @ +I@ ` + ~I,Db +@x +-J + + +-G% +! + +-J+ + +x +! + + +! + + +@ +a $a ' + N, +?G)á +,@ǠA+ ++?aǠA+PCG + + ++ȁ +@x +I +x + x
# @d +LC@ S + x
# +LC@ S @x
C C@ S + + + + +LC@ S +
+ + C@$ + + +ߏN LJ +J2x +@Ȇ + +0 +` + + +v~ +
j#LJ @t~ + + + + +r +@c~G@Q +
I + + + +xH@B H@ +Q +Q + +Q + +GG@Q +@ + / +B + //G@Q + +'#G@Q + +;p ; + +GС@ʡ + +G@@!x + + +G +!I@ +R B@h + H +H:
B G) +@!D # +G +G + G +GB G +G +@} +xQ + +;Gp ; + +GБ@ʡ + + ;R` G)"j ! (! )I + + +@ + +Ϡ +Aaa + +@G1 +N + +I + + +@ +G +Ϡ +Aaa +@ +@ + + + +@x + + + +H + +t@d#sRP @c#tR` G)"j ! + + + +B @\#BH [#BP B @ s@ tx +s + +B R#BH Q#BP B @ + H + + +a +G@GA +I +I + + @ +D#"@ +x B + + +G @@?# + +G"@ ;#@= + + x +B< + +@ +? +C +# +-0 + + +ɑ +GL + + + +@Rx + + + + + + +) + +J@ +
J +.8 + +GI , +O +I@ +I + +o +I@ +=Lʀ +I + bp + + + 4I + +Q RPPCL + +@J +A +A +& +% +( +\ +!p! + +J + + + + +LJ + + + +@xR +a +A + +@xJ e +B +a +xH +9 + H G +G@ +` +x
ǂ` + +x
+ +x}G` +@x + QL +FL@LBLȂ@ + +G + + +q@ + + + + + + t + + + + +IJ +Iʁ + + + + +B@Ȃ + + + + + + + + +G + +GI +I +d + +` + + +$@ + +@.x + + +W( +*e@-UU +\!xU@-U +¢V + +@TeP W| NB +EE@ +BV +@@xAՀe +&N E +TeP W| NB +U@%$U@x$&) +bV +`aV0 +&N U'@$ +&U + +$` + + + + + u V,E +@ + + +B +@A
Ǡ +&@@ +A + + +@@x +NNN@ + + +@@ II24 A" + + Iɐ ɐ @ I + +I SI + +@I@ +I + +K +K +< +` +xJ + +xIǀ! +< +J + +xJ +xJ +G2 +H" + + +2 +xJ +3@ +G4 + +@x.I,J) +` +,@ +I +,@Ȅ@ -, +@ǠA+,- + + +G +;H -% +< +@ I + +@ H +H@a + +H + +;I + + + + +GǑ@ʡ + +GH;ȡ@ʡ + + +G @@ + +G + +G @ + +G @ +I; +B + J +J + +J9 +@b +; + + + + +!sstG +@b + +GuuG + +@b + +x + + +~ + + o - - - -H - $@ -@I QIs Q #G)!D G)d + + +H + $ɀ +@Ip p QIs Q #G)!D G)d -Q;! +P;! - - - - + + + + + - - + + G,",@a -QI +QI Q ? -R@4yP,*(I0 ( +R - - -N" $ ->?L ?LIB -A - - á -H! - - à -G -IJr @ -IJ@ -` - - -Iʡ - - - -@I
ȁ -x -w -Jx - -v~ - - - - -A -b -xG - - -Gǡ@ʡ - -G - - -+ -/R - - + +ȼo + + +@ +G + + + ++ +! * +x, + +*I + G# # q@)#q s -s s +s s ' L! o !*! G) -))YxJx -))%xx +))Wx@Ix +))@%xx G) -))Qx -)) +))OxAx +))x G$) @@ -14477,16 +6148,17 @@ G$) -'x 'LI! &'()) a ' 'LI! H$ a ' CI#G D +'x 'LI! &'()) a ' 'LI! H$ a ' CI#x%>?L> @ #LGB0 @ @ -* +* @o I@ -(@(`} +((#LB0 o + A R K (@xGB %B @@ -14495,41 +6167,41 @@ H ` x - - + + -'xI* +&xI* S@& NI HB @ N @o @N @n $m - -G$) + +G$) ' -'x 'LI! &') a ' 'LI! H$ a '#G D %$ +'x 'LI! &') a ' 'LI! H$ a '#%$ o - + !L"L%'Le! ,a -* +* $ʀ -( +( %&&&r !G%@ G S& -F +Z * $ @o -&I@ +&I@`&@x* H"P !&% - + , -xB @@ -14541,35 +6213,38 @@ S& -+ - ++D + -g -J+J - +Ǡ +@x + Q ? -RP +RP +-L@L+" @#\ a L+L - -, - -@} +@. + +x, +I + + ,DŽP -Ʉ@ @ I@ ` - ~I,Db + @x -J +-G% -! +! -J+ -x -! - + +x +! + + @a x @@ -14585,147 +6260,77 @@ x @ a $a ' - N, + N, ?G)á ,@ǠA+ +?aǠA+PCG - - - -@ -G - + + ++ȁ ߏN LJ J2x @Ȇ 0 ` - - - C!?C` - - 1 -@ -M*@I -G - *,@ -@@ -M*@I - *,@ -@ -M*@I - -ql -@0 -G - ,@ -@@0 - ,@ -@0 -qp - -qp -` - -qIq - - -J -O+ -a
` -z - -."@ -o@l - -J - -O+ - -a
` -z - -."@ -o@l - -G@@ - - - - - -H -Hs - - -@r - -@ - -@ - -x - -@ -x -W~ -
@R#LJ @U~ - + + +v~ +
j#LJ @t~ + - + r -@D~G@Q -
I - -6~ -3~ M +@c~G@Q +
I + -*#G@H
Q -xH@B H@ + +xH@B H@ Q Q - - - -#@#G@Q -G@Q -@ + +Q + +GG@Q +@ / -B - / +B @ + //G@Q - +'#G@Q + ;p ; -GС@ʡ +GС@ʡ -G@!x - +G@@!x + G !I@ R B@h - ?C + H H:
B G) -@!D # +@!D # G -G -GB G -G -} +G + G +GB G +G +@} xQ - + ;Gp ; -GБ@ʡ +GБ@ʡ - ;R` G)"j ! (! )I - + ;R` G)"j ! (! )I + @ - + Ϡ Aaa @@ -14736,240 +6341,62 @@ GБ@ʡ @ -G +G Ϡ Aaa @ -@ - -I,J:9>>>G@ -@ -s@ -c@ -T@ - -G$@ -@&x - - - - - - - -G @ - I - -CJ -G:G@c -q@1@ɑ - I - - - -.x G` -xG -x -x@9 - -r,s-nuua u -qs@! -xt -~ -@@ - -@@ - -} - - - a -I -0020ȁ - - - -zJa CG - - +@ + + + +@x + + + H -t - - +t@d#sRP @c#tR` G)"j ! + + -B -s#sRP G)"j ! - -B @#BH #BP B @ s@IGr @ G +B @\#BH [#BP B @ s@ tx +s + +B R#BH Q#BP B @ H -a +a G@GA -I -I +I +I @ -#"@ - I - -@*x -@ -O - -" -x$r$ -O -, -" - -I - - +D#"@ +@x "@ + -G @@# - -G"@ # - -L - -A -pA - -B@ -p3@ - - - - -1@A @@N @@ - -@x - - - -
- -P - - - - -x@ -C - - - - -@x - - - - - - - - - C!?C` - -q - - - -K -@x -PH NL -xqMЀ LF -PJ N, -
-@xM@
Ҁ -
-@ -0q\ -J@ -@K<@Oq - -q -L@ -A@ -A@ -c@ -0Aa ,@ - -`! - - -A@ -0 - -Db -D` - - - - p T p0X -02p0 -K@ - -1L3 - - - - -0 -p -q<i -q
@ -@ - - -@ - -pF<@Op -a@ - -Q - - 2@ - -A - - - - 2@ - -A - - -q -1@ - - - 0 -0 - - - - - - - @ - -i - -3 - - - -ɑ zI -+ @ -I` - zɀ` -y -@&xP - ->x@<x +G @ + +G"@ @<#= + + x +B< + +@ +? +C +# +-0 + + +ɑ @}zI +GL + + + +@Rx + @@ -14979,11 +6406,11 @@ I` J@
J -.8@ +.8 GI , O -I@ +I@ I o @@ -14993,113 +6420,143 @@ I@ bp - + 4I Q RPPCL @J A -A +A & % ( \ !p! - -J + +J -LJ -@ +LJ + + + +@xR +a +A + +@xJ e +B +a +xH +: H G G@ ` -x` +xɂ` x
-xvG` -@x@xx +x}G` +@x QL -FLHAȂ +FL@LBLȂ@ + G - - -q@ + + +q@ + + + + + t + + - - - -B - -<B/L' @ 0@ + +IJ +Iʁ + + + + +Lʥ +% +B@Ȃ + + + + + + -G +G -GI -@LBLAQ -` - - -$ +GI +I +d + +` + + +)I +$@ - - -@x$@ -W(Ǥ -*e@-UU -\!@xU@-U +2x@*x' + +@x$ +V' +V)` +-GI` +W +*e@-UU +\!xU@-U ¢V -@TeP W| NB -EE@ +@TeP W| NB +EE@ BV @@xAՀe -&N U -TeP W| NB -U@%$U@x$&) +&N E +TeP W| NB +U@%$U@x$&) bV `aV0 -&N U'$ - +&N U'@$ +&U $` - + - u V,E + u V,E @ - - + + B @A
Ǡ - -A +&@@ +A @@x -NNN@ - +NNN@ + @@ II24 A" - Iɐ ɐ @ IIR + Iɐ ɐ @ I -@I@ -I + + -K -K -@@ -@ -G - -<GU; +K +K < ` xJ @@ -15118,187 +6575,676 @@ H" xJ 3@ G4 - - -~ $ -H -H -! - -N,x - - -sx -@ - -S - x.I,J) + +@x.I,J) ` ,@ I -,@Ȅ@ -,
- -@ǠA+,- - -G +,@Ȅ@ -, +@ǠA+,- + + +G ;H -% < - I +@ I - H +@ H H@a - +H + ;I - + -GǑ@ʡ -@;GR N;3 -xH;;G - -G +GǑ@ʡ -GH;ȡ@ʡ - - +GH;ȡ@ʡ + -G @@@ +G @@ -G +G -G @ -I; - - J - - +G @ + +G @ +I; +B + J +J + J9 - - -J -G!a +@b +; + - + !sstG @b - + GuuG - + @b - - x2 + +x + + +~ + + +o + + +H + $ɀ +@Ip p QIs Q #G)!D G)c + +P;! + + + + + + -< - - - -J -@b + + +G,",@a +QI + + +Q +? +R + + +ȼo + + +@ +G + + + ++ +! * +x, + +*I + + @c@r +G# +# +q@)#q s +s s @ +' +L! o +!*! +G) +))Wx@Ix +))@%xx +G) +))OxAx +))x +G$) + + +$ +@o + + + +'x 'LI! &'()) a ' 'LI! H$ a ' CI#x%>?L> @ +#LGB0 +@ +@ +* + + + @o +I@ +((#LB0 o + + A R K +(@xGB +%B +G +H + +` +x + + + + +S@& NI HB +@ +N @o +@N @n +$m + +G$) + +' +'x 'LI! &') a ' 'LI! H$ a '#%$ +o + +!L"L%'Le! ,a +* +$ʀ -. + + +( +%&& +G + +S& +@\ +* + +$ @o +&I@b&@x* H"P !&% + + +, + +-xB + +G - -J - +-J +Fa + - - - - - - - -@~; - - -~ - -~G . G. GGs$$ + ++D + + +Ǡ +@x + + +Q +? +RP +-L@L+" +@#\ a +L+L + + +x, +I + + ,DŽP -Ʉ@ @ +I@ ` + ~I,Db +@x +-J + + +-G% +! + +-J+ + +x +! + + +! + + +@ +a $a ' + N, +?G)á +,@ǠA+ ++?aǠA+PCG + + ++ȁ +@x +I +x + x
# @d +LC@ S + x
# +LC@ S @x
C C@ S + + + + +LC@ S +
+ + C@$ + + +ߏN LJ +J2x +@Ȇ + +0 +` + + +v~ +
j#LJ @t~ + + + + +r +@c~G@Q +
I + + + +xH@B H@ +Q +Q + +Q + +GG@Q +@ + / +B + //G@Q + +'#G@Q + +;p ; + +GС@ʡ + +G@@!x + + +G +!I@ +R B@h + H +H:
B G) +@!D # +G +G + G +GB G +G +@} +xQ + +;Gp ; + +GБ@ʡ + + ;R` G)"j ! (! )I + + +@ + +Ϡ +Aaa + +@G1 +N + +I + + +@ +G +Ϡ +Aaa +@ +@ + + + +@x + + + +H + +t@d#sRP @c#tR` G)"j ! + + + +B @\#BH [#BP B @ s@ tx +s + +B R#BH Q#BP B @ + H + + +a +G@GA +I +I + + @ +D#"@ +x B + + +G @@?# + +G"@ ;#@= +gxm_h264_multi.bin + + x +B< + +@ +? +C +# +-0 + + +ɑ +GL + + + +@Rx + + + + + + +) + +J@ +
J +.8 + +GI , +O +I@ +I + +o +I@ +=Lʀ +I + bp + + + 4I + +Q RPPCL + +@J +A +A +& +% +( +\ +!p! + +J + + + + +LJ +k + + +@xR +a +A + +@xJ e +B +a +xH +: + H G +G@ +` +x
ǂ` + +x
+ +x}G` +@x + QL +FL@LBLȂ@ + +G + + +q@ + + + + + + t + + + + +IJ +Iʁ + + + + +Lʥ +% +B@Ȃ + + + + + + + + +G + +GI +I +d + +` + + +$@ + +@.x + + +W( +*e@-UU +\!xU@-U +¢V + +@TeP W| NB +EE@ +BV +@@xAՀe +&N E +TeP W| NB +U@%$U@x$&) +bV +`aV0 +&N U'@$ +&U + +$` + + + + + u V,E +@ + + +B +@A
Ǡ +&@@ +A + + +@@x +NNN@ + + +@@ II24 A" + + Iɐ ɐ @ I + +I SI + +@I@ +I + +K +K +< +` +xJ + +xIǀ! +< +J + +xJ +xJ +G2 +H" + + +2 +xJ +3@ +G4 + +@x.I,J) +` +,@ +I +,@Ȅ@ -, +@ǠA+,- + + +G +;H -% +< + I + + H +H@a + + + +;I + + + + +GǑ@ʡ + +GH;ȡ@ʡ + + +G @@@ + +G + +G @@ + +G @ +I; +B + J +J + +J9 +@b +; + + + + +!sstG +@b + +GuuG + +@b + +x + + + + +@~ o - - - -H - $@ -@I QIs Q #G)!D G)d + + +H + $ɀ +@Ip p QIs Q #G)!D G)d -Q;! +P;! - - - -~ + + + + +@~ - - + + G,",@a -QI +QI Q ? -R5yP,*(I0 ( +R - - -N" $ ->?L ?LIB -A - - á -H! - - à -G -IJr @ -IJ@ -` - - -Iʡ - - - -@I
ȁ -x -w -Jx - -@x~ - -v~ - - -A -b -xG - - -Gǡ@ʡ -k~g#+#L -G - - -+ -/R - - + +ȼo + + +@ +G + + + ++ +! * +x, + +*I + G# # q@)#q s -s s +s s ' L! o !*! G) -))YxJx -))%xx +))Wx@Ix +))@%xx G) -))Qx -)) +))OxAx +))x G$) @@ -15307,16 +7253,17 @@ G$) -'x 'LI! &'()) a ' 'LI! H$ a ' CI#G D +'x 'LI! &'()) a ' 'LI! H$ a ' CI#x%>?L> @ #LGB0 @ @ -* +* @o I@ -(@(`} +((#LB0 o + A R K (@xGB %B @@ -15325,41 +7272,41 @@ H ` x - - + + -'xI* +&xI* S@& NI HB @ N @o @N @n $m - -G$) + +G$) ' -'x 'LI! &') a ' 'LI! H$ a '#G D %$ +'x 'LI! &') a ' 'LI! H$ a '#%$ o - + !L"L%'Le! ,a -* +* $ʀ -( +( %&&&r !G%@ G S& -@E +@[ * $ @o -&I@ +&I@a&@x* H"P !&% - + , -xB @@ -15371,36 +7318,38 @@ S& -+ - ++D + -g -J+J - +Ǡ +@x + Q ? -RP +RP +-L@L+" @#\ a L+L -@ -, - -@} + + +x, +I + + ,DŽP -Ʉ@ @ I@ ` - + ~I,Db @x -J +-G% -! +! -J+ -x -! -G - + +x +! + + @a x @@ -15416,147 +7365,77 @@ x @ a $a ' - N, + N, ?G)á ,@ǠA+ +?aǠA+PCG - - - -@ -G - + + ++ȁ ߏN LJ J2x @Ȇ 0 ` - - - C!?C` - - 1 -@ -M*@I -G - *,@ -@@ -M*@I - *,@ -@ -M*@I - -ql -@0 -G - ,@ -@@0 - ,@ -@0 -qp - -qp -` - -qIq - - -J -O+ -a
` -z - -."@ -o@l - -J - -O+ - -a
` -z - -."@ -o@l - -G@@ - - - - - -H -Hs - - -@r - -@ - -@ - -x - -@ -x -W~ -
@R#LJ @U~ - + + +v~ +
j#LJ @t~ + - + r -@D~G@Q -
I - -6~ -3~ M +@c~G@Q +
I + -*#G@H
Q -xH@B H@ + +xH@B H@ Q Q - - - -#@#G@Q -G@Q -@ + +Q + +GG@Q +@ / -B - / +B @ + //G@Q - +'#G@Q + ;p ; -GС@ʡ +GС@ʡ -G@!x - +G@@!x + G !I@ R B@h - ?C + H H:
B G) -@!D # +@!D # G -G -GB G -G -} +G + G +GB G +G +@} xQ - + ;Gp ; -GБ@ʡ +GБ@ʡ - ;R` G)"j ! (! )I - + ;R` G)"j ! (! )I + @ - + Ϡ Aaa @@ -15567,228 +7446,4445 @@ GБ@ʡ @ -G +G Ϡ Aaa @ -@ - -I,J:9>>>G@ -@ -s@ -c@ -T@ - -G$@ -@&x - - - +@ + + + +@x + + + +H + +t@d#sRP @c#tR` G)"j ! + + + +B @\#BH [#BP B @ s@ tx +s + +B R#BH Q#BP B @ s@IGr @ G + H + + +a +G@GA +I +I + + @ +D#"@ +@x "@ + + +G @ + +G"@ @<#= + + + +tl1_h264_multi.bin + + x +B< + +@ +? +C +# +-0 + + +ɑ +GL + + + +@Rx + + + + + + +) + +J@ +
J +.8 - - +GI , +O +I@ +I + +o +I@ +=Lʀ +I + bp + + + 4I + +Q RPPCL + +@J +A +A +& +% +( +\ +!p! + +J + + + + +LJ +k + + +@xR +a +A + +@xJ e +B +a +xH +: + H G +G@ +` +x
ǂ` + +x
+ +x}G` +@x + QL +FL@LBLȂ@ + +G + + +q@ + + + + + + t + + + + +IJ +Iʁ + + + + +Lʥ +% +B@Ȃ + + + + + + + + +G + +GI +I +d + +` + + +$@ + +@.x + + +W( +*e@-UU +\!xU@-U +¢V + +@TeP W| NB +EE@ +BV +@@xAՀe +&N E +TeP W| NB +U@%$U@x$&) +bV +`aV0 +&N U'@$ +&U + +$` + + + + + u V,E +@ + + +B +@A
Ǡ +&@@ +A + + +@@x +NNN@ + + +@@ II24 A" + + Iɐ ɐ @ I + +I SI + +@I@ +I + +K +K +< +` +xJ + +xIǀ! +< +J + +xJ +xJ +G2 +H" + + +2 +xJ +3@ +G4 + +@x.I,J) +` +,@ +I +,@Ȅ@ -, +@ǠA+,- + + +G +;H -% +< + I + + H +H@a + + + +;I + + + + +GǑ@ʡ + +GH;ȡ@ʡ + -G @ - I - -CJ -G:G@c -q@1@ɑ - I - - - -.x G` -xG -x -x@9 - -r,s-nuua u -qs@! -xt -~ -@@ - -@@ - -} +G @@@ + +G + +G @@ + +G @ +I; +B + J +J + +J9 +@b +; + + + + +!sstG +@b + +GuuG + +@b + +x + + + + +@~ +o + + +H + $ɀ +@Ip p QIs Q #G)!D G)d + +P;! + + + + + +@~ + + + +G,",@a +QI + + +Q +? +R + + +ȼo + + +@ +G + + + ++ +! * +x, + +*I + +G# +# +q@)#q s +s s +' +L! o +!*! +G) +))Wx@Ix +))@%xx +G) +))OxAx +))x +G$) + + +$ +@o + + + +'x 'LI! &'()) a ' 'LI! H$ a ' CI#x%>?L> @ +#LGB0 +@ +@ +* - - a -I -0020ȁ - - - -zJa CG - - + + @o +I@ +((#LB0 o + + A R K +(@xGB +%B +G +H + +` +x + + + +&xI* +S@& NI HB +@ +N @o +@N @n +$m + +G$) + +' +'x 'LI! &') a ' 'LI! H$ a '#%$ +o + +!L"L%'Le! ,a +* +$ʀ + + + +( +%&&&r !G%@ +G + +S& +@[ + +* + +$ @o +&I@a&@x* H"P !&% + + +, + +-xB + +G + +-J +Fa + + + ++D + + +Ǡ +@x + + +Q +? +RP +-L@L+" +@#\ a +L+L + + +x, +I + + ,DŽP -Ʉ@ @ +I@ ` + ~I,Db +@x +-J + + +-G% +! + +-J+ + +x +! + + + @a + +x + b@ʢ c +$"L2@ + + + +CALc +AA K)` +! + + +@ +a $a ' + N, +?G)á +,@ǠA+ ++?aǠA+PCG + + ++ȁ +ߏN LJ +J2x +@Ȇ + +0 +` + + +v~ +
j#LJ @t~ + + + + +r +@c~G@Q +
I + + + +xH@B H@ +Q +Q + +Q + +GG@Q +@ + / +B @ + //G@Q + +'#G@Q + +;p ; + +GС@ʡ + +G@@!x + + +G +!I@ +R B@h + H +H:
B G) +@!D # +G +G + G +GB G +G +@} +xQ + +;Gp ; + +GБ@ʡ + + ;R` G)"j ! (! )I + + +@ + +Ϡ +Aaa + +@G1 +N + +I + + +@ +G +Ϡ +Aaa +@ +@ + + + +@x + + + H -t - - +t@d#sRP @c#tR` G)"j ! + + -B -s#sRP G)"j ! - -B @#BH #BP B @ +B @\#BH [#BP B @ s@ tx +s + +B R#BH Q#BP B @ s@IGr @ G H -a +a G@GA -I -I +I +I @ -#"@ - I - -@*x -@ -O - -" -x$ -O -, -" - -I - - +D#"@ +@x "@ + -G @@# - -G"@ # - -L - -A -pA - -B@ -p3@ - - - - -1@A @@N @@ - -@x - - - -
- -P - - - - -x@ -C - - - - -@x - - - - - - - - - C!?C` - -q - - - -K -@x -PH NL -xqMЀ LF -PJ N, -
-@xM@
Ҁ -
-@ -0q\ -J@ -@K<@Oq - -q -L@ -A@ -A@ -c@ -0Aa ,@ - -`! - - -A@ -0 - -Db -D` - - - - p T p0X -02p0 -K@ - -1L3 - - - - -0 -p -q<i -q
@ -@ - - -@ - -pF<@Op -a@ - -Q - - 2@ - -A - - - - 2@ - -A - - -q -1@ - - - 0 -0 - - - - - - - @ - -i - +G @ + +G"@ @<#= + I ! + `xI@ C + @ +I +.x +(x +@x + + +@` + +` + +Go + +~x + + +6L k + +K +ˠ +@yxTi +Q"N + + + + + +rxa +@ +@ @qx + +@@ II24 A" + + Iɐ ɐ @ I SIH@! + +@I@ + +x@ +Iɀ +ɡ +IG# + +I +H +IA" + +I! + + +G
A Q@ +G + + + G + + Ĩ +H(H(BL Q IGv v P +GHLȁP GL G A +q@ + q@I +
Go + + +QI Q +@I + +H +H + +G@xGMG +)Lx +q@ + + + +G@ + + +d + +H + + +Gȁ ` + + + +,((LG/ + + +o + +GG + +y + +"& + + + +.@n +I + +@ #`d` + +T + + + + +H &(G` +GMG(LG@. +CG((LG/ +G +@ + +@Aa +x + + +B + +G + +Ba +G +? + +"& +G +G +` +@x; +@x, + +x + + +G + + +ǀ +2@ +EE@ +G +ǀ` +
x + +@ + + + + +GG + +@ +@ +BX J +BP +BH J + +(`xh@(C( +(( +HH +G@ +R + +x +@@ +@ +O + +MNC@ +@ xLM +O + + +@@
M@ +xMMM@
NNNNNNNQUNY +
+M@ +B +͂ +@Ixx
+ +
O +
+
O +
M@
+OO +x +MC@
+
` +@ +x
P3@@$ +x +́ +
+@x + @
NMӀ
M3@M@
X
IM
tr M# + + +G@b + +IGB + + + + +@ + +!L@ +"L @ + +£ +J +@ +A + +@xo +r +@xJ JM` + + + + +@" + + +@ + +@ +@ +xV JM` + + +@ + + + + + + + +J JY" !L MJ" !\ @ + + +J + +c +@xK` +JAb +x +ˁ +` + + +J + + + + +pIrIB + + +I @x + ,IB +ɱ@ + + @ +II @ + +x ,IB +ɱ@ + + @ +II @ +,C + +C +A + +2@ + +@} + +@ + @ x +x hx! V hx! T +U@e8hxqxU +TqxU5@ + +o8Q `8 + +e8hx% V + +ր` +xhx%@ + + U + +@!~ + +H +(G@ +, +<@ +P +XGA + + + + G@ + ! + $@ + < + HGA + x@@Gr1 + -G@ + Z + + +Gb@ +GB@ + +@x# +xI +x +$ +$Y@@ +$ +$)@S +d + +H +@ +p r +r + ÿ + + + +H + + + s +q u ILI +@I@HP U SI +I UIǁ O + +K<K4T + + + +!`xa@!C! + + + + + + I +A + + + ¥ +I + +A + +Di + + + + +G` + +x B I D` + +EG@ +ŀ +EŁx + +EG +ł +EŃ " K` +@" ` + +G` + + +EG +ń +EŅ " +EG +ņ +EŇ " + I ! + `xI@ C + @ +I +.x +(x +@x + + +@` + +` + +Go + +~x + + +6L k + +K +ˠ +@yxTi +Q"N + + + + + +rxa +@ +@ @qx + +@@ II24 A" + + Iɐ ɐ @ I SIH@! + +@I@ + +x@ +Iɀ +ɡ +IG# + +I +H +IA" + +I! + + +G
A Q@ +G + + + G + + Ĩ +H(H(BL Q IGv v P +GHLȁP GL G A +q@ + q@I +
Go + + +QI Q +@I + +H +H + +G@xGMG +)Lx +q@ + + + +G@ + + +d + +H + + +Gȁ ` + + + +,((LG/ + + +o + +GG + +y + +"& + + + +.@n +I + +@ #`d` + +T + + + + +H &(G` +GMG(LG@. +CG((LG/ +G +@ + +@Aa +x + + +B + +G + +Ba +G +? + +"& +G +G +` +@x; +@x, + +x + + +G + + +ǀ +2@ +EE@ +G +ǀ` +
x + +@ + + + + +GG + +@ +@ +BX J +BP +BH J + +(`xh@(C( +(( +HH +G@ +R + +x +@@ +@ +O + +MNC@ +@ xLM +O + + +@@
M@ +xMMM@
NNNNNNNQUNY +
+M@ +B +͂ +@Ixx
+ +
O +
+
O +
M@
+OO +x +MC@
+
` +@ +x
P3@@$ +x +́ +
+@x + @
NMӀ
M3@M@
X
IM
tr M# + + +G@b + +IGB + + + + +@ + +!L@ +"L @ + +£ +J +@ +A + +@xo +r +@xJ JM` + + + + +@" + + +@ + +@ +@ +xV JM` + + +@ + + + + + + + +J JY" !L MJ" !\ @ + + +J + +c +@xK` +JAb +x +ˁ +` + + +J + + + + +pIrIB + + +I @x + ,IB +ɱ@ + + @ +II @ + +x ,IB +ɱ@ + + @ +II @ +,C + +C +A + +2@ + +@} + +@ + @ x +x hx! V hx! T +U@e8hxqxU +TqxU5@ + +o8Q `8 + +e8hx% V + +ր` +xhx%@ + + U + +@!~ + +H +(G@ +, +<@ +P +XGA + + + + G@ + ! + $@ + < + HGA + x@@Gr1 + -G@ + Z + + +Gb@ +GB@ + +@x# +xI +x +$ +$Y@@ +$ +$)@S +d + +H +@ +p r +r + ÿ + + + +H + + + s +q u ILI +@I@HP U SI +I UIǁ O + +K<K4T + + + +!`xa@!C! + + + + + + I +A + + + ¥ +I + +A + +Di + + + + +G` + +x B I D` + +EG@ +ŀ +EŁx + +EG +ł +EŃ " K` +@" ` + +G` + + +EG +ń +EŅ " +EG +ņ +EŇ " + I ! + `xI@ C + @ +I + + +@x + + +@@` +RxL +` + +Go + + + +6L Kl + +K +ˠ + +QBN + + + + + +@xa +@ +@ + +@@ II24 A" + + Iɐ ɐ @ I SIH@! + +@I@ + +x@ +Iɀ +ɡ +IG# + +I +H +IA" + +I! + + +G
A Q@ +G + + + G + + +GHLȁP GL G A +q@ + q@I +
Go + + +@I + + +H + +GxGMG +)L +q@ + + + +G@ + + +F + + @a + +Gȁ ` + + + +B J@ +B +B B +K,@xBX I` +xBP ` + +,((LG/ + + +o + +GG + +d + +"& + + + +. +I + % +GMG +@ +G + + + +G@ + +@ +H + + +; + + + + + +@Aa +x + + +B + +G + +Ba +G + + +"& +G +@x@ + +x + + +G + + +ǀ +2@ +G +ǀ` +
x + + + + + + +GG + + + +BX J +BP +BH J + +(`xh@(C( +(( +x +@@ +@ +O + +MNC@ +@ xLM +O + + +@@
M@ +xMMM@
NNNNNNNQUNY +
+M@ +B +͂ +@Ixx
+ +
O +
+
O +
M@
+OO +x +MC@
+
` +@ +x
P3@@$ +x +́ +
+@x + @
NMӀ
M3@M@
X
IM
tr M# + + +G@b + +IGB + + + + +A@Nȁ +@ + +!L@ +"L @ + +£ +J +@ +A + +@xo +r +@xJ JM` + + + + +@" + + +@ + +@ +@ +xV JM` + + +@ + + + + + + + +J JY" !L MJ" !\ @ + + +J + +c +@xK` +JAb +x +ˁ +` + + +J + + + + +pIrIB + + +I @x + +} + +@ + @ x +x hx! V hx! T +U@e8hxqxU +TqxU5@ + +o8Q `8 + +e8hx% V + +ր` +xhx%@ + + U + +O~ + +@x# +xI +x +$ +$Y@@ +$ +$)@S +d +
" !@ " !D MH + +H + +p r +r ]B + + ÿ + + + +H +@ + + s +q L + u HRJ RT v I@ +@I@ +@HP U SI +I UIǁ O + +@ +HP SI + + + +!`xa@!C! + + + + + + I +A + + + ¥ +I + +A + +Di + + + + +G` + +x B I D` + +EG@ +ŀ +EŁx + +EG +ł +EŃ " @" ` + +G` + + + +EG +ń@ +EŅ@x +EG +ŀ +EŁ + +EG +ņ@ +EŇ@x +EG +ł +EŃ@ +` + I ! + `xI@ C + @ +I + + +@x + + +@@` +RxL +` + +Go + + + +6L Kl + +K +ˠ + +QBN + + + + + +@xa +@ +@ + +@@ II24 A" + + Iɐ ɐ @ I SIH@! + +@I@ + +x@ +Iɀ +ɡ +IG# + +I +H +IA" + +I! + + +G
A Q@ +G + + + G + + +GHLȁP GL G A +q@ + +
Go + + +@I + + +H + +GxGMG +)L +q@ + + + +G@ + + +@F + + @a + +Gȁ ` + + + +B J@ +B +B B +K,@xBX I` +xBP ` + +,((LG/ + + +o + +GG + +d + +"& + + + +. +I + % +GMG +@ +G + + + +G@ + +@ +H + + +@; + + + + + +@Aa +x + + +B + +G + +Ba +G + + +"& +G +@x + +x + + +G + + +ǀ +2@ + +G +ǀ` +
x + +@ + + + + +GG + +@ +@ +BX J +BP +BH J + +(`xh@(C( +(( +x +@@ +@ +O + +MNC@ +@ xLM +O + + +@@
M@ +xMMM@
NNNNNNNQUNY +
+M@ +B +͂ +@Ixx
+ +
O +
+
O +
M@
+OO +x +MC@
+
` +@ +x
P3@@$ +x +́ +
+@x + @
NMӀ
M3@M@
X
IM
tr M# + + +G@b + +IGB + + + + +@ + +!L@ +"L @ + +£ +J +@ +A + +@xo +r +@xJ JM` + + + + +@" + + +@ + +@ +@ +xV JM` + + +@ + + + + + + + +J JY" !L MJ" !\ @ + + +J + +c +@xK` +JAb +x +ˁ +` + + +J + + + + +pIrIB + + +I @x + +@} + +@ + @ x +x hx! V hx! T +U@e8hxqxU +TqxU5@ + +o8Q `8 + +e8hx% V + +ր` +xhx%@ + + U + + + @ +@x# +xI +x +$ +$Y@@ +$ +$)@S +d +
" !@ " !D MH + +H + +p r +r ]B + + ÿ + + + +H +@ + + s +q L + u HRJ RT v I@ +@I@ +@HP U SI +I UIǁ O + +@ +HP SI + + + +!`xa@!C! + + + + + + I +A + + + ¥ +I + +A + +Di + + + + +G` + +x B I D` + +EG@ +ŀ +EŁx + +EG +ł +EŃ " @" ` + +G` + + + +EG +ń@ +EŅ@x +EG +ŀ +EŁ + +EG +ņ@ +EŇ@x +EG +ł +EŃ@ +` + I ! + `xI@ C + @ +I +.x +(x +@x + + +@` + +` + +Go + +~x + + +6L k + +K +ˠ +@yxTi +Q"N + + + + + +rxa +@ +@ @qx + +@@ II24 A" + + Iɐ ɐ @ I SIH@! + +@I@ + +x@ +Iɀ +ɡ +IG# + +I +H +IA" + +I! + + +G
A Q@ +G + + + G + + Ĩ +H(H(BL Q IGv v P +GHLȁP GL G A +q@ + @q@I +
Go + + +QI Q +@I + +H +H + +G@xGMG +)Lx +q@ + + + +G@ + + +@e + +H + + +Gȁ ` + + + +,((LG/ + + +o + +GG + +y + +"& + + + +.@n +I + +@ #`d` + +@U + + + + +H &(G` +GMG(LG@. +CG((LG/ +G + + +@Aa +x + + +B + +G + +Ba +G +? + +"& +G +G +` +@x; +@x@- + +x + + +G + + +ǀ +2@ +G +ǀ` +
x + + + + + + +GG + + + +BX J +BP +BH J + +(`xh@(C( +(( +HH +G@ +R + +x +@@ +@ +O + +MNC@ +@ xLM +O + + +@@
M@ +xMMM@
NNNNNNNQUNY +
+M@ +B +͂ +@Ixx
+ +
O +
+
O +
M@
+OO +x +MC@
+
` +@ +x
P3@@$ +x +́ +
+@x + @
NMӀ
M3@M@
X
IM
tr M# + + +G@b + +IGB + + + + +A@Nȁ +@ + +!L@ +"L @ + +£ +J +@ +A + +@xo +r +@xJ JM` + + + + +@" + + +@ + +@ +@ +xV JM` + + +@ + + + + + + + +J JY" !L MJ" !\ @ + + +J + +c +@xK` +JAb +x +ˁ +` + + +J + + + + +pIrIB + + +I @x + ,IB +ɱ@ + + @ +II @ + +x ,IB +ɱ@ + + @ +II @ +,C + +C +A + +2@ + +} + +@ + @ x +x hx! V hx! T +U@e8hxqxU +TqxU5@ + +o8Q `8 + +e8hx% V + +ր` +xhx%@ + + U + + ~ + +H +(G@ +, +<@ +P +XGA + + + + G@ + ! + $@ + < + HGA + x@@Gr1 + -G@ + Z + + +Gb@ +GB@ + +@x# +xI +x +$ +$Y@@ +$ +$)@S +d + +H +@ +p r +r + ÿ + + + +H + + + s +q u ILI +@I@HP U SI +I UIǁ O + +K<K4T + + + +!`xa@!C! + + + + + + I +A + + + ¥ +I + +A + +Di + + + + +G` + +x B I D` + +EG@ +ŀ +EŁx + +EG +ł +EŃ " K` +@" ` + +G` + + +EG +ń +EŅ " +EG +ņ +EŇ " + I ! + `iI@ C + @ +I + + +@x + + +@@` +RxL +` + +Go + + + +6L Kl + +K +ˠ + +QBN + + + + + +@xa +@ +@ + +@@ II24 A" + + Iɐ ɐ @ I SIH@! + +@I@ + +x@ +Iɀ +ɡ +IG# + +I +H +IA" + +I! + + +G
A Q@ +G + + + G + + +GHLȁP GL G A +q@ + +
Go + + +@I + + +H + +GxGMG +)L +q@ + + + +G@ + + +@F + + @a + +Gȁ ` + + + +B J@ +B +B B +K,@xBX I` +xBP ` + +,((LG/ + + +o + +GG + +d + +"& + + + +. +I + % +GMG +@ +G + + + +G@ + +@ +H + + +@; + + + + + +@Aa +x + + +B + +G + +Ba +G + + +"& +G +@x + +x + + +G + + +ǀ +2@ + +G +ǀ` +
x + +@ + + + + +GG + +@ +@ +BX J +BP +BH J + +(`ih@(C( +(( +x +@@ +@ +O + +MNC@ +@ xLM +O + + +@@
M@ +xMMM@
NNNNNNNQUNY +
+M@ +B +͂ +@Ixx
+ +
O +
+
O +
M@
+OO +x +MC@
+
` +@ +x
P3@@$ +x +́ +
+@x + @
NMӀ
M3@M@
X
IM
tr M# + + +G@b + +IGB + + + + +@ + +!L@ +"L @ + +£ +J +@ +A + +@xo +r +@xJ JM` + + + + +@" + + +@ + +@ +@ +xV JM` + + +@ + + + + + + + +J JY" !L MJ" !\ @ + + +J + +c +@xK` +JAb +x +ˁ +` + + +J + + + + +pIrIB + + +I @x + +@} + +@ + @ x +x hi! V hi! T +U@e)hiqiU +TqiU5@ + +o)Q `) + +e)hi% V + +ր` +xhi%@ + + U + + + @ +@x# +xI +x +$ +$Y@@ +$ +$)@S +d +
" !@ " !D MH + +H + +p r +r ]B + + ÿ + + + +H +@ + + s +q L + u HRJ RT v I@ +@I@ +@HP U SI +I UIǁ O + +@ +HP SI + + + +!`ia@!C! + + + + + + I +A + + + ¥ +I + +A + +Di + + + + +G` + +x B I D` + +EG@ +ŀ +EŁx + +EG +ł +EŃ " @" ` + +G` + + + +EG +ń@ +EŅ@x +EG +ŀ +EŁ + +EG +ņ@ +EŇ@x +EG +ł +EŃ@ +` + I ! + `xI@ C + @ +I + + +@x + + +@@` +RxL +` + +Go + + + +6L Kl + +K +ˠ + +QBN + + + + + +@xa +@ +@ + +@@ II24 A" + + Iɐ ɐ @ I SIH@! + +@I@ + +x@ +Iɀ +ɡ +IG# + +I +H +IA" + +I! + + +G
A Q@ +G + + + G + + +GHLȁP GL G A +q@ + q@I +
Go + + +@I + + +H + +GxGMG +)L +q@ + + + +G@ + + +F + + @a + +Gȁ ` + + + +B J@ +B +B B +K,@xBX I` +xBP ` + +,((LG/ + + +o + +GG + +d + +"& + + + +. +I + % +GMG +@ +G + + + +G@ + +@ +H + + +; + + + + + +@Aa +x + + +B + +G + +Ba +G + + +"& +G +@x@ + +x + + +G + + +ǀ +2@ +G +ǀ` +
x + + + + + + +GG + + + +BX J +BP +BH J + +(`xh@(C( +(( +x +@@ +@ +O + +MNC@ +@ xLM +O + + +@@
M@ +xMMM@
NNNNNNNQUNY +
+M@ +B +͂ +@Ixx
+ +
O +
+
O +
M@
+OO +x +MC@
+
` +@ +x
P3@@$ +x +́ +
+@x + @
NMӀ
M3@M@
X
IM
tr M# + + +G@b + +IGB + + + + +A@Nȁ +@ + +!L@ +"L @ + +£ +J +@ +A + +@xo +r +@xJ JM` + + + + +@" + + +@ + +@ +@ +xV JM` + + +@ + + + + + + + +J JY" !L MJ" !\ @ + + +J + +c +@xK` +JAb +x +ˁ +` + + +J + + + + +pIrIB + + +I @x + +} + +@ + @ x +x hx! V hx! T +U@e8hxqxU +TqxU5@ + +o8Q `8 + +e8hx% V + +ր` +xhx%@ + + U + +O~ + +@x# +xI +x +$ +$Y@@ +$ +$)@S +d +
" !@ " !D MH + +H + +p r +r ]B + + ÿ + + + +H +@ + + s +q L + u HRJ RT v I@ +@I@ +@HP U SI +I UIǁ O + +@ +HP SI + + + +!`xa@!C! + + + + + + I +A + + + ¥ +I + +A + +Di + + + + +G` + +x B I D` + +EG@ +ŀ +EŁx + +EG +ł +EŃ " @" ` + +G` + + + +EG +ń@ +EŅ@x +EG +ŀ +EŁ + +EG +ņ@ +EŇ@x +EG +ł +EŃ@ +` + I ! + `iI@ C + @ +I +.x +(x +@x + + +@` + +` + +Go + +~x + + +6L k + +K +ˠ +@yxTi +Q"N + + + + + +rxa +@ +@ @qx + +@@ II24 A" + + Iɐ ɐ @ I SIH@! + +@I@ + +x@ +Iɀ +ɡ +IG# + +I +H +IA" + +I! + + +G
A Q@ +G + + + G + + Ĩ +H(H(BL Q IGv v P +GHLȁP GL G A +q@ + q@I +
Go + + +QI Q +@I + +H +H + +G@xGMG +)Lx +q@ + + + +G@ + + +d + +H + + +Gȁ ` + + + +,((LG/ + + +o + +GG + +y + +"& + + + +.@n +I + +@ #`d` + +T + + + + +H &(G` +GMG(LG@. +CG((LG/ +G +@ + +@Aa +x + + +B + +G + +Ba +G +? + +"& +G +G +` +@x; +@x, + +x + + +G + + +ǀ +2@ +EE@ +G +ǀ` +
x + +@ + + + + +GG + +@ +@ +BX J +BP +BH J + +(`ih@(C( +(( +HH +G@ +R + +x +@@ +@ +O + +MNC@ +@ xLM +O + + +@@
M@ +xMMM@
NNNNNNNQUNY +
+M@ +B +͂ +@Ixx
+ +
O +
+
O +
M@
+OO +x +MC@
+
` +@ +x
P3@@$ +x +́ +
+@x + @
NMӀ
M3@M@
X
IM
tr M# + + +G@b + +IGB + + + + +@ + +!L@ +"L @ + +£ +J +@ +A + +@xo +r +@xJ JM` + + + + +@" + + +@ + +@ +@ +xV JM` + + +@ + + + + + + + +J JY" !L MJ" !\ @ + + +J + +c +@xK` +JAb +x +ˁ +` + + +J + + + + +pIrIB + + +I @x + ,IB +ɱ@ + + @ +II @ + +x ,IB +ɱ@ + + @ +II @ +,C + +C +A + +2@ + +@} + +@ + @ x +x hi! V hi! T +U@e)hiqiU +TqiU5@ + +o)Q `) + +e)hi% V + +ր` +xhi%@ + + U + +@!~ + +H +(G@ +, +<@ +P +XGA + + + + G@ + ! + $@ + < + HGA + x@@Gr1 + -G@ + Z + + +Gb@ +GB@ + +@x# +xI +x +$ +$Y@@ +$ +$)@S +d + +H +@ +p r +r + ÿ + + + +H + + + s +q u ILI +@I@HP U SI +I UIǁ O + +K<K4T + + + +!`ia@!C! + + + + + + I +A + + + ¥ +I + +A + +Di + + + + +G` + +x B I D` + +EG@ +ŀ +EŁx + +EG +ł +EŃ " K` +@" ` + +G` + + +EG +ń +EŅ " +EG +ņ +EŇ " + I ! + `xI@ C + @ +I + + +@x + + +@@` +RxL +` + +Go + + + +6L Kl + +K +ˠ + +QBN + + + + + +@xa +@ +@ + +@@ II24 A" + + Iɐ ɐ @ I SIH@! + +@I@ + +x@ +Iɀ +ɡ +IG# + +I +H +IA" + +I! + + +G
A Q@ +G + + + G + + +GHLȁP GL G A +q@ + +
Go + + +@I + + +H + +GxGMG +)L +q@ + + + +G@ + + +@F + + @a + +Gȁ ` + + + +B J@ +B +B B +K,@xBX I` +xBP ` + +,((LG/ + + +o + +GG + +d + +"& + + + +. +I + % +GMG +@ +G + + + +G@ + +@ +H + + +@; + + + + + +@Aa +x + + +B + +G + +Ba +G + + +"& +G +@x + +x + + +G + + +ǀ +2@ + +G +ǀ` +
x + +@ + + + + +GG + +@ +@ +BX J +BP +BH J + +(`xh@(C( +(( +x +@@ +@ +O + +MNC@ +@ xLM +O + + +@@
M@ +xMMM@
NNNNNNNQUNY +
+M@ +B +͂ +@Ixx
+ +
O +
+
O +
M@
+OO +x +MC@
+
` +@ +x
P3@@$ +x +́ +
+@x + @
NMӀ
M3@M@
X
IM
tr M# + + +G@b + +IGB + + + + +@ + +!L@ +"L @ + +£ +J +@ +A + +@xo +r +@xJ JM` + + + + +@" + + +@ + +@ +@ +xV JM` + + +@ + + + + + + + +J JY" !L MJ" !\ @ + + +J + +c +@xK` +JAb +x +ˁ +` + + +J + + + + +pIrIB + + +I @x + +@} + +@ + @ x +x hx! V hx! T +U@e8hxqxU +TqxU5@ + +o8Q `8 + +e8hx% V + +ր` +xhx%@ + + U + + + @ +@x# +xI +x +$ +$Y@@ +$ +$)@S +d +
" !@ " !D MH + +H + +p r +r ]B + + ÿ + + + +H +@ + + s +q L + u HRJ RT v I@ +@I@ +@HP U SI +I UIǁ O + +@ +HP SI + + + +!`xa@!C! + + + + + + I +A + + + ¥ +I + +A + +Di + + + + +G` + +x B I D` + +EG@ +ŀ +EŁx + +EG +ł +EŃ " @" ` + +G` + + + +EG +ń@ +EŅ@x +EG +ŀ +EŁ + +EG +ņ@ +EŇ@x +EG +ł +EŃ@ +` + I ! + `xI@ C + @ +I +.x +(x +@x + + +@` + +` + +Go + +~x + + +6L k + +K +ˠ +@yxTi +Q"N + + + + + +rxa +@ +@ @qx + +@@ II24 A" + + Iɐ ɐ @ I SIH@! + +@I@ + +x@ +Iɀ +ɡ +IG# + +I +H +IA" + +I! + + +G
A Q@ +G + + + G + + Ĩ +H(H(BL Q IGv v P +GHLȁP GL G A +q@ + @q@I +
Go + + +QI Q +@I + +H +H + +G@xGMG +)Lx +q@ + + + +G@ + + +@e + +H + + +Gȁ ` + + + +,((LG/ + + +o + +GG + +y + +"& + + + +.@n +I + +@ #`d` + +@U + + + + +H &(G` +GMG(LG@. +CG((LG/ +G + + +@Aa +x + + +B + +G + +Ba +G +? + +"& +G +G +` +@x; +@x@- + +x + + +G + + +ǀ +2@ +G +ǀ` +
x + + + + + + +GG + + + +BX J +BP +BH J + +(`xh@(C( +(( +HH +G@ +R + +x +@@ +@ +O + +MNC@ +@ xLM +O + + +@@
M@ +xMMM@
NNNNNNNQUNY +
+M@ +B +͂ +@Ixx
+ +
O +
+
O +
M@
+OO +x +MC@
+
` +@ +x
P3@@$ +x +́ +
+@x + @
NMӀ
M3@M@
X
IM
tr M# + + +G@b + +IGB + + + + +A@Nȁ +@ + +!L@ +"L @ + +£ +J +@ +A + +@xo +r +@xJ JM` + + + + +@" + + +@ + +@ +@ +xV JM` + + +@ + + + + + + + +J JY" !L MJ" !\ @ + + +J + +c +@xK` +JAb +x +ˁ +` + + +J + + + + +pIrIB + + +I @x + ,IB +ɱ@ + + @ +II @ + +x ,IB +ɱ@ + + @ +II @ +,C + +C +A + +2@ + +} + +@ + @ x +x hx! V hx! T +U@e8hxqxU +TqxU5@ + +o8Q `8 + +e8hx% V + +ր` +xhx%@ + + U + + ~ + +H +(G@ +, +<@ +P +XGA + + + + G@ + ! + $@ + < + HGA + x@@Gr1 + -G@ + Z + + +Gb@ +GB@ + +@x# +xI +x +$ +$Y@@ +$ +$)@S +d + +H +@ +p r +r + ÿ + + + +H + + + s +q u ILI +@I@HP U SI +I UIǁ O + +K<K4T + + + +!`xa@!C! + + + + + + I +A + + + ¥ +I + +A + +Di + + + + +G` + +x B I D` + +EG@ +ŀ +EŁx + +EG +ł +EŃ " K` +@" ` + +G` + + +EG +ń +EŅ " +EG +ņ +EŇ " @4x @@ -15969,7 +12065,7 @@ n J` -J` +J` @@ -16167,493 +12263,652 @@ n J` -J` - -@x -Ȁ - -#$O -6
- - -H - -H -@p -6
-@ - -% -x -Ȁ - - - -H - -x -@ -I@ -v -G -@2x -Ha - -@2xU@ -IL - - - -x - -@
xZ@ - -G2 - - -A - - -x - - - - -H -. -ta -- -px -0 -G7 -mWBl - -HR - II - - - - -@Lr@ǁ - -@x -I - - - - - -x -H@ - -@ -H - -@ - -@b - -
A -E -T -1@D!D A -1@D!H DA -1@D!L E) -, -E A -$E -4XA -F A -$G -4XFA -H A -""$EH -#4#X -` -x - -$@ -$@ -Q - - -Q - -M3 -M
AH a t - - - - -2a --Iȁ -@L3 -Ā` -!x -U -T%H @ID -T%H @ID -T%H @ID -U -I@ - -v -G -@2x -Ha - -@2xU -IL - - - -x - -@
xZ -@ -G2 - - -A - - -x - - - - -H -. -ta -- - -0 -G7 -mWBl0PmJPn - -HR - II - - - - -@Lr@ǁ - -@x -I - - - - - -x -H@ - -@ -H - -@| - -@d - -
A -E -V -1@D!D A -1@D!H DA -1@D!L E) -, -E A -$E -4XA -F A -$G -4XFA -H A -""$EH -#4#X -` -x - -$@ -$@ -Q -&@x - -Q - -M3@ -M
AH a t - - - - -2a --Iȁ - - -Ā` -!x -U -T%H @ID -T%H @ID -T%H @ID -U -I -v -G -@2x -Ha - -@2xU -IL - - - -x - -@
xZ -@ -G2 - - -A - - -x - - - -@ -H -. -ta -- -mx -0 -G7 -mWBl - -HR - II - - - - -@Lr@ǁ - -@x -I - - - - y +J` + + + + + +G +% + +@:La + + + + +y +o +c +HCc +I +x +*L6Lǁ Q ;LH2 +H +L ` + +@@I -xB ! -H@ - - -
-H - - - -] - -
A -E - -1@D!D A -1@D!H DA -1@D!L E) -, -E A E -F A G -H A EH -` -@x -$@@d x -$@d*LDA -Q - - -M3 -M
AH a t - - - -2a --Iȁ -@L3 -Ā` -!x -U -T%H @ID -T%H @ID -T%H @ID -U -I - -v -G -@2x -Ha - -@2xU@ -IL - - - -x - -@
xZ@ - -G2 - - -A - - -x - - - - -H -. -ta -- -@nx -0 -G7 -mWBl0PmJPn - -HR - II - - - - -@Lr@ǁ - -@x -I - - - - { +x + + +@x + +2 + +(GGCG + +<L + + +B + + +BD HAd + +` + + +` + +X ȃ +, + +q@BD HH@d + +x + + +@ +HA + + + +ȃ X + +x!GG +G$Lx0!$L@$N +@ +" +N"HD 2P @x!xA! + +`@ + + +` + + +Hzo + +N + + + +GI +O +I@ +I + +o +I@ +I + Rp + + + I`O + + + + + +LJ + + +` +6xG` +G +G + + + +^ +G IGa @ +a +G + + + +` +x + +@ +@ +P @ +x +9 + IG +@ +@ +P @ +x + + +GG +B + + + +H`W@Ux +x + +HH + + + +*L6L @˂@ +@KK +I + + + +Br@@xr@ + + Gr +Gr + + +G` + + +G +b + + +o +I +H + + + +G@H +?I ȑ +I a +I I + + + + + + + + + + + +J + +xGGP !@$N +@ +" +N"HD 2P @x!xA! +GG +G +G` + +@ + +@ +H!" + + +I +xF!x +@ + +N + r + + ! RGIba IGa +a + + +"B @x@@ o + +@ +ۆ[@GLa~ ǀ + + + + +( +! (@( hQ +( +* +kè +냨 ++B + +* +* + + +! ( 銂( ( +@$("Lh +! ( 銂( hЈ0D x( D *k +Q +* +* +k +p +* + +! h (( m-^ ( ( +@$("L( ( +! h (( -^ ( (X0D ( (0D ( ( +$/"L/ / +! h (( -^ ( ( +P$("L( ( +! h (( --^ ( h؎0D ( $$("L./( + + + +! ( 銂( @$("Lh +! ( 銂( hи0D @x( * +Q x+kA +k +p +0D ( ) ( +! h (( -^ ( @$("L( ( +! h (( ( (X0D ( (0D ( ( +! h (( m-^ ( P$("L( ( +! h (( 胂 ( hؾ0D ( $$("L./(( +@#xIU + +@ x +@@x U@U5 +`a@ + +U@ + +@V + + +E NNN$"N + +xAd +V U + +E + +G +G +c + +NNN + + +@ +! +G + +ߏN Lȃ JB + +` + +, + *C(I( +,J@($,*F ( ) ("L(h! ( 튂( ( +,J@ ($("Lh! ( 튂( , +("Lh! ( 튂( + + + + + +G +% + +@:La + + + + +@y +o +c +HCc +I +x +*L6Lǁ Q ;LH2 +H +L ` + +@@I -xB ! -H@ - - -
-H - - - -_ - -
A -E - -1@D!D A -1@D!H DA -1@D!L E) -, -E A E -F A G -H A EH -` -@x -$@@d!x -$@d*LDA -Q -& - -M3@ -M
AH a t - - - -2a --Iȁ - - -Ā` -!x -U -T%H @ID -T%H @ID -T%H @ID -U - -G+ -% - @ -I` -@y` -@y$ -x +x + + +@x + +2 + +(GGCG + +<L + + +B + + +BD HAd + +` + + +` + +X ȃ +, + +q@BD HH@d + +x + + +@ +HA + + + +ȃ X + +x!GG +G$Lx0!$L@$N +@ +" +N"HD 2P @x!xA! + +`@ + + +` + + +Hzo + +N + + + +GI +O +I@ +I + +o +I@ +I + Rp + + + I`O + + + + + +LJ + + +` +6xG` +G +G + + + +^ +G IGa @ +a +G + + + +` +x + +@ +@ +P @ +x +9 + IG +@ +@ +P @ +x + + +GG +B + + + +H`W +x + +HH + + + +*L6L @˂@ +@KK +I + + + +Br@@xr@ + + Gr +Gr + + +G` + + +G +b + + +o +I +H + + + + +G@H +?I ȑ +I a +I I + + + + + + + + + + + +J + +xGGP !@$N +@ +" +N"HD 2P @x!xA! +GG +G +G` + +@ + +@ +H!" + + +I +xF!x +@ + +N + r + + ! RGIba IGa +a + + +"B @x@@ o + +@ +ۆ[@GLa~ ǀ + + + + +( +! (@( hQ +( +* +kè +냨 ++B + +* +* + + +! ( 銂( ( +@$("Lh +! ( 銂( hЈ0D x( D *k +Q +* +* +k +p +* + +! h (( m-^ ( ( +@$("L( ( +! h (( -^ ( (X0D ( (0D ( ( +$/"L/ / +! h (( -^ ( ( +P$("L( ( +! h (( --^ ( h؎0D ( $$("L./( + + + +! ( 銂( @$("Lh +! ( 銂( hи0D @x( * +Q x+kA +k +p +0D ( ) ( +! h (( -^ ( @$("L( ( +! h (( ( (X0D ( (0D ( ( +! h (( m-^ ( P$("L( ( +! h (( 胂 ( hؾ0D ( $$("L./(( +@#xIU + +@ x +@@x U@U5 +`a@ + +U@ + +@V + + +E NNN$"N + +xAd +V U + +E + +G +G +c + +NNN + + +@ +! +G + +ߏN Lȃ JB + +` + +, + *C(I( +,J@($,*F ( ) ("L(h! ( 튂( ( +,J@ ($("Lh! ( 튂( , +("Lh! ( 튂( + + + + + +G +% + @:La - - - - -*y - - - - - -, - - -B I - - - - -@ - + + + + +@y o c HCc -I +I x *L6Lǁ Q ;LH2 H L ` -@@I +@@I -xyo +x @x -2 - -(GG$$"$" +2 + +(GGCG <L - + -@B +B -@x + BD HAd - -`H + +` ` - + X ȃ -, +, q@BD HH@d - + x @@ -16663,24 +12918,23 @@ HA ȃ X - + x!GG G$Lx0!$L@$N @ " N"HD 2P @x!xA! - + `@ ` - - -HRo - - - -@x + + +Hzo + +N + GI @@ -16702,14 +12956,15 @@ I@ LJ - -1xG` -G + +` +6xG` +G G - +^ G IGa @ a G @@ -16717,67 +12972,79 @@ G ` -x - +x + @ - -P
- - - IG@ +@ +P @ +x +9 + IG @ - -P
- - +@ +P @ +x + GG -@C +B -H` -% - +H`W +x + +HH + + + +*L6L @˂@ +@KK +I + + + +Br@@xr@ + + Gr +Gr + + +G` + + +G +b + + +o +I +H + + - - -G -` -x@ -x -Br -@ - - - -x - - -HIa $ -HJIIa " -IJa ! - G -A Q@ -G - ` -I IB@HB@ - + +G@H +?I ȑ +I a +I I - + - + + + J -@xGGP !@$N +xGGP !@$N @ " -N"HD 2P @x!xA! +N"HD 2P @x!xA! GG G G` @@ -16785,7 +13052,7 @@ GG @ @ -H!" +H!" I @@ -16793,39 +13060,332 @@ I @ N - r - + r + ! RGIba IGa -a - - - @@ - +a "B @x@@ o -@ -@W~ +@ +ۆ[@GLa~ ǀ + + + ( -! (@( hQ2x( (o -( +! (@( hQ +( * kè 냨 +B * -* +* ! ( 銂( ( @$("Lh -! ( 銂( hЈ0D +! ( 銂( hЈ0D x( D *k +Q +* +* +k +p +* + +! h (( m-^ ( ( +@$("L( ( +! h (( -^ ( (X0D ( (0D ( ( +$/"L/ / +! h (( -^ ( ( +P$("L( ( +! h (( --^ ( h؎0D ( $$("L./( + + + +! ( 銂( @$("Lh +! ( 銂( hи0D @x( * +Q x+kA +k +p +0D ( ) ( +! h (( -^ ( @$("L( ( +! h (( ( (X0D ( (0D ( ( +! h (( m-^ ( P$("L( ( +! h (( 胂 ( hؾ0D ( $$("L./(( +@#xIU + +@ x +@@x U@U5 +`a@ + +U@ + +@V + + +E NNN$"N + +xAd +V U + +E + +G +G +c + +NNN + + +@ +! +G + +ߏN Lȃ JB + +` + +, + *C(I( ,J@($,*F ( ) ("L(h! ( 튂( ( ,J@ ($("Lh! ( 튂( , -("Lh! ( 튂( +("Lh! ( 튂( + + + + + +G +% + +@:La + + + + +y +o +c +HCc +I +x +*L6Lǁ Q ;LH2 +H +L ` + +@@I + +x + + +@x + +2 + +(GGCG + +<L + + +B + + +BD HAd + +` + + +` + +X ȃ +, + +q@BD HH@d + +x + + +@ +HA + + + +ȃ X + +x!GG +G$Lx0!$L@$N +@ +" +N"HD 2P @x!xA! + +`@ + + +` + + +Hzo + +N + + + +GI +O +I@ +I + +o +I@ +I + Rp + + + I`O + + + + + +LJ + + +` +6xG` +G +G + + + +^ +G IGa @ +a +G + + + +` +x + +@ +@ +P @ +x +9 + IG +@ +@ +P @ +x + + +GG +B + + + +H`W@Ux +x + +HH + + + +*L6L @˂@ +@KK +I + + + +Br@@xr@ + + Gr +Gr + + +G` + + +G +b + + +o +I +H + + + +G@H +?I ȑ +I a +I I + + + + + + + + + + + +J + +xGGP !@$N +@ +" +N"HD 2P @x!xA! +GG +G +G` + +@ + +@ +H!" + + +I +xF!x +@ + +N + r + + ! RGIba IGa +a + + +"B @x@@ o + +@ +ۆ[@GLa~ ǀ + + + + +( +! (@( hQ +( +* +kè +냨 ++B + +* +* + + +! ( 銂( ( +@$("Lh +! ( 銂( hЈ0D x( D *k +Q * * k @@ -16838,34 +13398,36 @@ p $/"L/ / ! h (( -^ ( ( P$("L( ( -! h (( --^ ( h؎0D ( $$("L./( +! h (( --^ ( h؎0D ( $$("L./( ! ( 銂( @$("Lh -! ( 銂( hи0D x( * +! ( 銂( hи0D @x( * +Q x+kA k -p +p 0D ( ) ( ! h (( -^ ( @$("L( ( ! h (( ( (X0D ( (0D ( ( ! h (( m-^ ( P$("L( ( ! h (( 胂 ( hؾ0D ( $$("L./(( -"xIU +@#xIU @ x @@x U@U5 `a@ -U@ +U@ -@V +@V -E NNN$"N - xAd -V U@U5 -x +E NNN$"N + +xAd +V U + E G @@ -16874,11 +13436,766 @@ G NNN - -@ + +@ ! G - + +ߏN Lȃ JB + +` + +, + *C(I( +,J@($,*F ( ) ("L(h! ( 튂( ( +,J@ ($("Lh! ( 튂( , +("Lh! ( 튂( + + + + + + + +:x +G
@a + +@x +@x + + +, + + + + + +! + + +J + + +,! + +G$ +` + + + +@I + +o +I@Ip v Gv v Gw p v Gv v Gw + + + +k@WW + + +r +H + +@I + ` + +G
` +x + G`HR@ +`"@ + + +b + +2x +B + + + + + + + +A + +@a + + + + + + +J` + + + + @I ^ G \ G Z +I + + + +I + +QGbɑ@I2 +QHbIb P PCIIb +@ +QRIc P PCIIG
B + +G LI B HbBx a t + + + +@^ + +GIǁ a +O +I@I + + + + +@ x + +> +@x + + +xQL FLBL +@Lr@ǁ +?I H +I HR + I Ix I I + +L +H2X + + + + + + + + + + + + +AL"CLh ޘ@ + + + + + + + + + +@xa + +I +A@_` +T@GL@~ +U + + +A@ + + + + + + +s s Eg + +a + + +L@a + + + +E@a +@ +L + +D +GIǁ +I@ + ! +<Ȁa +E<B + +B + + = +E=== E DL>L +b + +D@ @ + +@xHR& b@I"@J@Hb + + + + + + + + + +:x +G
@a + +@x + + + +, + + + +@ + +! + + +J + + +,! + +G$ +` + + + +@I + +o +I@Ip v Gv v Gw p v Gv v Gw + + + +k@W@Z + + +r +H + +@I + ` + +G
` +@x + G`HR@ +`"@ + + +b + +2x +B + + + + + + + +A + +@a + + + + + + +J` + + + + @I ^ G \ G Z +I + + + +I + +QGbɑ@I2 +QHbIb P PCIIb +@ +QRIc P PCIIG
B + +G LI B HbBx a t + + + +` + +GIǁ a +O +I@I + + + + +@ x + +> +@x + + +xQL FLBL +@Lr@ǁ +?I H +I HR + I Ix I I + +L +H2X + IH + + + + + + + + + + + + +AL"CLh ޘ@ + + + + + + + + + +@xa + +I +A@_` +T@GL~ +U + + +A@ + + + + + + +s s Eg + +a + + +L@a + + + +E@a +@ +L + +D +GIǁ +I@ + ! +<Ȁa +E<B + +B + + = +E=== E DL>L +b + +D@ @ + +@xHR& b@I"@J@Hb + + + + + + + + + +:x +G
@a + +@x +@x + + +, + + + + + +! + + +J + + +,! + +G$ +` + + + +@I + +o +I@Ip v Gv v Gw p v Gv v Gw + + + +k@WW + + +r +H + +@I + ` + +G
` +x + G`HR@ +`"@ + + +b + +2x +B + + + + + + + +A + +@a + + + + + + +J` + + + + @I ^ G \ G Z +I + + + +I + +QGbɑ@I2 +QHbIb P PCIIb +@ +QRIc P PCIIG
B + +G LI B HbBx a t + + + +@^ + +GIǁ a +O +I@I + + + + +@ x + +> +@x + + +xQL FLBL +@Lr@ǁ +?I H +I HR + I Ix I I + +L +H2X + + + + + + + + + + + + +AL"CLh ޘ@ + + + + + + + + + +@xa + +I +A@_` +T@GL@~ +U + + +A@ + + + + + + +s s Eg + +a + + +L@a + + + +E@a +@ +L + +D +GIǁ +I@ + ! +<Ȁa +E<B + +B + + = +E=== E DL>L +b + +D@ @ + +@xHR& b@I"@J@Hb + + + + + + + + + +:x +G
@a + +@x + + + +, + + + +@ + +! + + +J + + +,! + +G$ +` + + + +@I + +o +I@Ip v Gv v Gw p v Gv v Gw + + + +k@W@Z + + +r +H + +@I + ` + +G
` +@x + G`HR@ +`"@ + + +b + +2x +B + + + + + + + +A + +@a + + + + + + +J` + + + + @I ^ G \ G Z +I + + + +I + +QGbɑ@I2 +QHbIb P PCIIb +@ +QRIc P PCIIG
B + +G LI B HbBx a t + + + +` + +GIǁ a +O +I@I + + + + +@ x + +> +@x + + +xQL FLBL +@Lr@ǁ +?I H +I HR + I Ix I I + +L +H2X + IH + + + + + + + + + + + + +AL"CLh ޘ@ + + + + + + + + + +@xa + +I +A@_` +T@GL~ +U + + +A@ + + + + + + +s s Eg + +a + + +L@a + + + +E@a +@ +L + +D +GIǁ +I@ + ! +<Ȁa +E<B + +B + + = +E=== E DL>L +b + +D@ @ + +@xHR& b@I"@J@Hb + + y G@, % @@ -17196,58 +14513,74 @@ G *C(I( ,J@($,*F ( ) ("L(h! ( 튂( ( ,J@ ($("Lh! ( 튂( , -("Lh! ( 튂( - y -G@, -% +("Lh! ( 튂( + +G+ +% + @ I` - - -@x +@y` +@y$ +x @:La - - - - -@-y + + + + +*y + + + + + +, + + +B I + + + + +@ + o c HCc -I +I x *L6Lǁ Q ;LH2 H L ` -@@I +@@I -x +xyo @x -2 - -(GGCG +2 + +(GG$$"$" <L - + -B +@B @x BD HAd - + `H ` X ȃ -, +, q@BD HH@d - + x @@ -17263,15 +14596,15 @@ HA @ " N"HD 2P @x!xA! -@< + `@ ` - - -Hzo - + + +HRo + @x @@ -17296,15 +14629,14 @@ I@ LJ - -` + 1xG` -G +G G -] + G IGa @ a G @@ -17327,84 +14659,52 @@ G GG -b +B -H` -` - - - -*L6L @˂@ -@` -I -@b$ r -@I2@ -C -Br@@xr@ - - Gr -Gr - - - - - -`` - - -G -b - - -o - -H - - +H` +% + - -G + +G ` -x@ -I +x@ x Br -@ -G -I@ - - +@ + + + x HIa $ HJIIa " IJa ! - G - + G A Q@ -G - ` -@x I IB@HB@ +G + ` +I IB@HB@ - + - + J -xGGP !@$N +@xGGP !@$N @ " -N"HD 2P @x!xA! +N"HD 2P @x!xA! GG G G` @@ -17412,7 +14712,7 @@ GG @ @ -H!" +H!" I @@ -17421,7 +14721,7 @@ I N r - + ! RGIba IGa a @@ -17433,24 +14733,26 @@ I "B @x@@ o @ -T~ + ( -! (@( hQ -( +! (@( hQ2x( (o +( * kè 냨 +B * -* +* ! ( 銂( ( @$("Lh -! ( 銂( hЈ0D x( D *k -Q +! ( 銂( hЈ0D +,J@($,*F ( ) ("L(h! ( 튂( ( +,J@ ($("Lh! ( 튂( , +("Lh! ( 튂( * * k @@ -17463,36 +14765,34 @@ p $/"L/ / ! h (( -^ ( ( P$("L( ( -! h (( --^ ( h؎0D ( $$("L./( +! h (( --^ ( h؎0D ( $$("L./( ! ( 銂( @$("Lh -! ( 銂( hи0D @x( * -Q x+kA +! ( 銂( hи0D x( * k -p +p 0D ( ) ( ! h (( -^ ( @$("L( ( ! h (( ( (X0D ( (0D ( ( ! h (( m-^ ( P$("L( ( ! h (( 胂 ( hؾ0D ( $$("L./(( - +"xIU @ x @@x U@U5 `a@ -U@ +U@ -@V +@V E NNN$"N - -xAd -V U@U5 - + xAd +V U@U5 +x E G @@ -17501,71 +14801,78 @@ G NNN - -@ + +@ ! G - -ߏN Lȃ JB - -` - -, - *C(I( -,J@($,*F ( ) ("L(h! ( 튂( ( -,J@ ($("Lh! ( 튂( , -("Lh! ( 튂( - y -G@, -% + + +G+ +% + @ I` - - -@x +@y` +@y$ +x @:La - - - - -@-y + + + + +*y + + + + + +, + + +B I + + + + +@ + o c HCc -I +I x *L6Lǁ Q ;LH2 H L ` -@@I +@@I -x +xyo @x -2 - -(GGCG +2 + +(GG$$"$" <L - + -B +@B @x BD HAd - + `H ` X ȃ -, +, q@BD HH@d - + x @@ -17581,15 +14888,15 @@ HA @ " N"HD 2P @x!xA! -@< + `@ ` - - -Hzo - + + +HRo + @x @@ -17614,15 +14921,14 @@ I@ LJ - -` + 1xG` -G +G G -] + G IGa @ a G @@ -17645,84 +14951,52 @@ G GG -b +B -H` -` - - - -*L6L @˂@ -@` -I -@b$ r -@I2@ -C -Br@@xr@ - - Gr -Gr - - - - - -`` - - -G -b - - -o - -H - - +H` +% + - -G + +G ` -x@ -I +x@ x Br -@ -G -I@ - - +@ + + + x HIa $ HJIIa " IJa ! - G - + G A Q@ -G - ` -@x I IB@HB@ +G + ` +I IB@HB@ - + - + J -xGGP !@$N +@xGGP !@$N @ " -N"HD 2P @x!xA! +N"HD 2P @x!xA! GG G G` @@ -17730,7 +15004,7 @@ GG @ @ -H!" +H!" I @@ -17739,7 +15013,7 @@ I N r - + ! RGIba IGa a @@ -17751,24 +15025,26 @@ I "B @x@@ o @ -T~ + ( -! (@( hQ -( +! (@( hQ2x( (o +( * kè 냨 +B * -* +* ! ( 銂( ( @$("Lh -! ( 銂( hЈ0D x( D *k -Q +! ( 銂( hЈ0D +,J@($,*F ( ) ("L(h! ( 튂( ( +,J@ ($("Lh! ( 튂( , +("Lh! ( 튂( * * k @@ -17781,36 +15057,34 @@ p $/"L/ / ! h (( -^ ( ( P$("L( ( -! h (( --^ ( h؎0D ( $$("L./( +! h (( --^ ( h؎0D ( $$("L./( ! ( 銂( @$("Lh -! ( 銂( hи0D @x( * -Q x+kA +! ( 銂( hи0D x( * k -p +p 0D ( ) ( ! h (( -^ ( @$("L( ( ! h (( ( (X0D ( (0D ( ( ! h (( m-^ ( P$("L( ( ! h (( 胂 ( hؾ0D ( $$("L./(( - +"xIU @ x @@x U@U5 `a@ -U@ +U@ -@V +@V E NNN$"N - -xAd -V U@U5 - + xAd +V U@U5 +x E G @@ -17819,20 +15093,11 @@ G NNN - -@ + +@ ! G - -ߏN Lȃ JB - -` - -, - *C(I( -,J@($,*F ( ) ("L(h! ( 튂( ( -,J@ ($("Lh! ( 튂( , -("Lh! ( 튂( + G+ % @@ -17842,10 +15107,10 @@ I` @y$ x @:La - + - + *y @@ -17865,20 +15130,20 @@ I` o c HCc -I +I x *L6Lǁ Q ;LH2 H L ` -@@I +@@I -xyo +xyo @x -2 +2 (GG$$"$" @@ -17889,17 +15154,17 @@ xyo @x BD HAd - + `H ` X ȃ -, +, q@BD HH@d - + x @@ -17915,13 +15180,13 @@ HA @ " N"HD 2P @x!xA! - + `@ ` - - + + HRo @@ -17978,7 +15243,7 @@ G GG -B +@C @@ -18016,14 +15281,14 @@ G - + J @xGGP !@$N @ " -N"HD 2P @x!xA! +N"HD 2P @x!xA! GG G G` @@ -18031,7 +15296,7 @@ GG @ @ -H!" +H!" I @@ -18052,7 +15317,7 @@ I "B @x@@ o @ - +@W~ ( ! (@( hQ2x( (o @@ -18063,7 +15328,7 @@ kè +B * -* +* ! ( 銂( ( @@ -18124,7 +15389,7 @@ G @ ! G - + y G@, % @@ -18442,74 +15707,58 @@ G *C(I( ,J@($,*F ( ) ("L(h! ( 튂( ( ,J@ ($("Lh! ( 튂( , -("Lh! ( 튂( - -G+ -% - @ +("Lh! ( 튂( + y +G@, +% I` -@y` -@y$ -x + + +@x @:La - - - - -*y - - - - - -, - - -B I - - - - -@ - + + + + +@-y o c HCc -I +I x *L6Lǁ Q ;LH2 H L ` -@@I +@@I -xyo +x @x -2 - -(GG$$"$" +2 + +(GGCG <L - + -@B +B @x BD HAd - + `H ` X ȃ -, +, q@BD HH@d - + x @@ -18525,15 +15774,15 @@ HA @ " N"HD 2P @x!xA! - +@< `@ ` - - -HRo - + + +Hzo + @x @@ -18558,14 +15807,15 @@ I@ LJ - + +` 1xG` -G +G G - +] G IGa @ a G @@ -18588,52 +15838,84 @@ G GG -B +b -H` -% - +H` +` + + + +*L6L @˂@ +@` +I +@b$ r +@I2@ +C +Br@@xr@ + + Gr +Gr + + + + + +`` + + +G +b + + +o + +H + + - -G + +G ` -x@ +x@ +I x Br -@ - - - +@ +G +I@ + + x HIa $ HJIIa " IJa ! - G + G + A Q@ -G - ` -I IB@HB@ +G + ` +@x I IB@HB@ - + - + J -@xGGP !@$N +xGGP !@$N @ " -N"HD 2P @x!xA! +N"HD 2P @x!xA! GG G G` @@ -18641,7 +15923,7 @@ GG @ @ -H!" +H!" I @@ -18650,7 +15932,7 @@ I N r - + ! RGIba IGa a @@ -18662,26 +15944,342 @@ I "B @x@@ o @ - +T~ ( -! (@( hQ2x( (o -( +! (@( hQ +( * kè 냨 +B * -* +* ! ( 銂( ( @$("Lh -! ( 銂( hЈ0D +! ( 銂( hЈ0D x( D *k +Q +* +* +k +p +* + +! h (( m-^ ( ( +@$("L( ( +! h (( -^ ( (X0D ( (0D ( ( +$/"L/ / +! h (( -^ ( ( +P$("L( ( +! h (( --^ ( h؎0D ( $$("L./( + + + +! ( 銂( @$("Lh +! ( 銂( hи0D @x( * +Q x+kA +k +p +0D ( ) ( +! h (( -^ ( @$("L( ( +! h (( ( (X0D ( (0D ( ( +! h (( m-^ ( P$("L( ( +! h (( 胂 ( hؾ0D ( $$("L./(( + + +@ x +@@x U@U5 +`a@ + +U@ + +@V + + +E NNN$"N + +xAd +V U@U5 + +E + +G +G +c + +NNN + + +@ +! +G + +ߏN Lȃ JB + +` + +, + *C(I( ,J@($,*F ( ) ("L(h! ( 튂( ( ,J@ ($("Lh! ( 튂( , -("Lh! ( 튂( +("Lh! ( 튂( + y +G@, +% +I` + + +@x +@:La + + + + +@-y +o +c +HCc +I +x +*L6Lǁ Q ;LH2 +H +L ` + +@@I + +x + + +@x + +2 + +(GGCG + +<L + + +B + +@x +BD HAd + +`H + + +` + +X ȃ +, + +q@BD HH@d + +x + + +@ +HA + + + +ȃ X + +x!GG +G$Lx0!$L@$N +@ +" +N"HD 2P @x!xA! +@< +`@ + + +` + + +Hzo + + + +@x + + +GI +O +I@ +I + +o +I@ +I + Rp + + + I`O + + + + + +LJ + + +` +1xG` +G +G + + + +] +G IGa @ +a +G + + + +` +x + +@ + +P
+ + + IG@ +@ + +P
+ + + +GG +b + + + +H` +` + + + +*L6L @˂@ +@` +I +@b$ r +@I2@ +C +Br@@xr@ + + Gr +Gr + + + + + +`` + + +G +b + + +o + +H + + + + + +G +` +x@ +I +x +Br +@ +G +I@ + + +x + + +HIa $ +HJIIa " +IJa ! + G + +A Q@ +G + ` +@x I IB@HB@ + + + + + + + + + + +J + +xGGP !@$N +@ +" +N"HD 2P @x!xA! +GG +G +G` + +@ + +@ +H!" + + +I +xF!x +@ + +N + r + + ! RGIba IGa +a + + + @@ + + + +"B @x@@ o + +@ +T~ + +( +! (@( hQ +( +* +kè +냨 ++B + +* +* + + +! ( 銂( ( +@$("Lh +! ( 銂( hЈ0D x( D *k +Q * * k @@ -18694,34 +16292,36 @@ p $/"L/ / ! h (( -^ ( ( P$("L( ( -! h (( --^ ( h؎0D ( $$("L./( +! h (( --^ ( h؎0D ( $$("L./( ! ( 銂( @$("Lh -! ( 銂( hи0D x( * +! ( 銂( hи0D @x( * +Q x+kA k -p +p 0D ( ) ( ! h (( -^ ( @$("L( ( ! h (( ( (X0D ( (0D ( ( ! h (( m-^ ( P$("L( ( ! h (( 胂 ( hؾ0D ( $$("L./(( -"xIU + @ x @@x U@U5 `a@ -U@ +U@ -@V +@V E NNN$"N - xAd -V U@U5 -x + +xAd +V U@U5 + E G @@ -18730,11 +16330,20 @@ G NNN - -@ + +@ ! G - + +ߏN Lȃ JB + +` + +, + *C(I( +,J@($,*F ( ) ("L(h! ( 튂( ( +,J@ ($("Lh! ( 튂( , +("Lh! ( 튂( G+ % @@ -19026,22 +16635,673 @@ G @ ! G - - + +x +` +x +@* +[x + +x
+H +H +! + + +@@HR`
@!
+ +@@HR`
Ob I + +w +vJH + + + + +@ + +@^x + + + + +@@HR`
+ +@@HR`
Ob H + +w +v n n n nH + +@ + +@ +
+ + M@b + +J +@I J@ J + + + +@ + + +MMG @O +@ +@ +9
+6
6
6
6
x +ʒ +K@˼R +J +QP@ʢ + +PCK +3 P @ +dO eOH +aO fO +bO gOcO@ + +HB +H@I@I"@ + +H@ + + +I + + + +K@ +J +QPPCK +" + +H@"@ +@c + +9
+6
6
6
6
x + +ʲ +K@
` +˼˵R +J +QP@ʢ + +PCK +3 P @ +
a ++! @ +dO eOH +aO fO +bO gOcO@ + +ʿ + + + +C + + + +w +J
K
L
M
x +À " +ƀ + + + + +xHH + +@ +H" @9~ +J2I +4 +9 + + H2@ + +AJ H2 + +J H +@ +H + J JH +>O@,~ +JO*~ + +JG + +I + ʠ + + ʠ + + + +D +7 + + +E +8 + IJ + +@I@ +I + ʠ + + ʠ + + + +@@ + +a 3
+!
+ +@@HR`
+ +@@HR`
Ob I + + +a 3
@ +!
+ +@@HR`
+ +@@HR`
OH". +b I +4M + + + + +@ +@ +@ + + +@` + Bc + @@ + +@ +@` + + @@P + + + +@ +Cb +@ +@. +RAI + +@ + +6Jv + +6A + + + + +x +` +x +@* +[x + +x
+H +H +! + + +@@HR`
@!
+ +@@HR`
Ob I + +w +vJH + + + + +@ + +@^x + + + + +@@HR`
+ +@@HR`
Ob H + +w +v n n n nH + +@ + +@ +
+ + M@b + +J +@I J@ J + + + +@ + + +MMG @O +@ +@ +9
+6
6
6
6
x +ʒ +K@˼R +J +QP@ʢ + +PCK +3 P @ +dO eOH +aO fO +bO gOcO@ + +HB +H@I@I"@ + +H@ + + +I + + + +K@ +J +QPPCK +" + +H@"@ +@c + +9
+6
6
6
6
x + +ʲ +K@
` +˼˵R +J +QP@ʢ + +PCK +3 P @ +
a ++! @ +dO eOH +aO fO +bO gOcO@ + +ʿ + + + +C + + + +w +J
K
L
M
x +À " +ƀ + + + + +xHH + +@ +H" @9~ +J2I +4 +9 + + H2@ + +AJ H2 + +J H +@ +H + J JH +>O@,~ +JO*~ + +JG + +I + ʠ + + ʠ + + + +D +7 + + +E +8 + IJ + +@I@ +I + ʠ + + ʠ + + + +@@ + +a 3
+!
+ +@@HR`
+ +@@HR`
Ob I + + +a 3
@ +!
+ +@@HR`
+ +@@HR`
OH". +b I +4M + + + + +@ +@ +@ + + +@` + Bc + @@ + +@ +@` + + @@P + + + +@ +Cb +@ +@. +RAI + +@ + +6Jv + +6A + + + + +x +` +x +@* +@^x + +x
+H +H +! + + +@@HR`
@!
+ +@@HR`
Ob `
I + +w +vJH + + + + +@ + +bx + + + + +@@HR`
+ +@@HR`
J" + + +w +v n n n nH + +@ + +@ +
+ + M@b + +J +@I J@ J + + + +@ + + +MMG @O +@ + +9
+6
6
6
6
x +ʒ +K@˼R +J +QP@ʢ + +PCK +3 P @ +dO eOH +aO fO +bO gOcO@ + +HB +H@I@I"@ + +H@ +Р +6
"@ + +I +6
+6
H@I"@ + + + +6
+ + +K@ +J +QPPCK +" + +aM8cMH@"@ +@c + +9
+6
6
6
6
x + +ʲ +K@
` +˼˵R +J +QP@ʢ + +PCK +3 P @ +
a ++! @ +dO eOH +aO fO +bO gOcO@ + +ʿ@ + + +C + + + +w +J
K
L
M
x +Ā " +Ȁ +6
H@JB@ + + + + + +xHH + +@ +H" $~ +J2I +4 +9 + + H2@ + +AJ H2 + +J H +@ +H + J JH +>O~ +JO@~ + +JG + +I + ʠ + + ʠ + + + +D +7 + + +E +8 + IJ + +@I@ +I + ʠ + + ʠ + + + +@@ + +a 3
+!
!
+ +@@HR`
!
+ +@@HR`
Ob I + +a 3
+!
@!
+ +@@HR`
+ +@@HR`
OH". +b I +4M + + + + +@ +@ +@ + + +@` + Bc + @@ + +@ +@` + + @@P + + + +@ +Cb +@ +@. +RAI + +@ + +6Jv + +6A + + + + @ I` -
y` - y$ - - - - - -Cd -)L - - -% +@x` + + + + + +@vyo +Cc +)L + + + GGG%&&&r !@ G @@ -19068,14 +17328,13 @@ Gd Q ? -RP* +RP ? NI HB @GAǀ -Gr@;HH - - +Gr@HH + o G#LB0 o @@ -19086,23 +17345,23 @@ G#LB0 o H ` - - + + -@? NI HB +? NI HB @ - + I - - + + LJ -@ - + + L @@ -19110,17 +17369,18 @@ H LJ J ʧ -q -, -@ -l - + + +I +, + + l - -x +x +x @ - + q @@ -19128,8 +17388,8 @@ x G -1@r -#G +A +#G \ @@ -19138,7 +17398,7 @@ H - + q!G` xZ @x @@ -19147,8 +17407,8 @@ H G -q -#G +A +@#G \ @@ -19174,53 +17434,53 @@ GA` @x G - + x -I +Io# Hx !#(HH5a @x -# + QLFLAIH p "@ȁ CL@ -@L@ @ +@L@ t H -a @ +a @ G - - - -x@ -I x - - - - -H - - + + + I + + +I + + + +H + + A Q@ -G +G Z` @ @ -I@@x @@ +I@@x @@ @x - + aH @ - -m`@ + +W @a J @@ -19230,7 +17490,7 @@ x @ a GLLa H - + x @d @@ -19250,11 +17510,11 @@ Q RPPCL @
-L -J - r - - +L + + b + + GB @@ -19264,26 +17524,21 @@ G @ @x s s -@ + L! o - -H - + +H + - -ǁ -U - -GL@H - - -1 - -x -Ct -.GLK.H - -@(~ + + + + + + +x +Ct +V~ P !x @@ -19361,7 +17616,7 @@ RP#LG . -`Z +WZ . @@ -19407,33 +17662,25 @@ Z Xш PH Ȉ X -H -*I*d +H *AL+CLh j@ j - - - -2 ! , -x3 - - - + @ I` -@y` -@y$ - - -@! - - -Cd -)L - - -%% + +x# + + + + + +Cc +)L + + +sy GGG%&&&r !@ G @@ -19460,14 +17707,13 @@ Gd Q ? -RP +RP@ ? NI HB @GAǀ -Gr@@>HH - - +Gr@@HH + o G#LB0 o @@ -19478,23 +17724,23 @@ G#LB0 o H ` - - + + -@? NI HB +? NI HB @ - + I - - + + LJ - - +@ + L @@ -19502,17 +17748,18 @@ H LJ J ʧ -q -, -@ -l - + + +I +, + + l -x -x +x +x @ - + q @@ -19520,8 +17767,8 @@ x G -1@@u - +A + \ @@ -19530,7 +17777,7 @@ H - + q!G` xZ @x @@ -19539,8 +17786,8 @@ H G -q] -@#G +A +#G \ @@ -19566,54 +17813,53 @@ GA` @x G - + x -I# +I Hx !#(HH5a @x - +e# QLFLAIH p "@ȁ CL@ -@L@ +@L@ @w H -a +a G - - - -x@ -I x - - - - -H - - + + + + +I + + + +H + + A Q@ -G +G Z` @ @ -I@@x @@ +I@@x @@ @x - + aH @ - -m`@ + +W @a J @@ -19623,7 +17869,7 @@ x @ a GLLa H - + x @d @@ -19643,11 +17889,11 @@ Q RPPCL @
-L -J - r - - +L + + b + + GB @@ -19657,25 +17903,20 @@ G @ @x s s - + L! o - -H - + +H + - -ǁ -V -GL@H - - -1= - -x -Ct -.GLK.H - -'~ + + + + + +x +Ct +U~ P P @@ -19754,7 +17995,7 @@ RP#LG . -`Z +WZ . @@ -19800,33 +18041,25 @@ Z Xш PH Ȉ X -H -*I*d +H *AL+CLh j@ j - - - -2 ! , -x3 - - - + @ I` -@y` -@y$ - - -@! - - -Cd -)L - - -%% +@x` + + + + + +@vyo +Cc +)L + + + GGG%&&&r !@ G @@ -19853,14 +18086,13 @@ Gd Q ? -RP +RP ? NI HB @GAǀ -Gr@@>HH - - +Gr@HH + o G#LB0 o @@ -19871,23 +18103,23 @@ G#LB0 o H ` - - + + -@? NI HB +? NI HB @ - + I - - + + LJ - - + + L @@ -19895,17 +18127,18 @@ H LJ J ʧ -q -, -@ -l - + + +I +, + + l -x -x +x +x @ - + q @@ -19913,8 +18146,8 @@ x G -1@@u - +A +#G \ @@ -19923,7 +18156,7 @@ H - + q!G` xZ @x @@ -19932,8 +18165,8 @@ H G -q] -@#G +A +@#G \ @@ -19959,54 +18192,53 @@ GA` @x G - + x -I# +Io# Hx !#(HH5a @x - + QLFLAIH p "@ȁ CL@ -@L@ +@L@ t H -a - +a @ G - - - -x@ -I x - - - - -H - - + + + I + + +I + + + +H + + A Q@ -G +G Z` @ @ -I@@x @@ +I@@x @@ @x - + aH @ - -m`@ + +W @a J @@ -20016,7 +18248,7 @@ x @ a GLLa H - + x @d @@ -20036,11 +18268,11 @@ Q RPPCL @
-L -J - r - - +L + + b + + GB @@ -20050,27 +18282,22 @@ G @ @x s s - + L! o - -H - + +H + - -ǁ -V -GL@H - - -1= - -x -Ct -.GLK.H - -'~ - -P + + + + + + +x +Ct +V~ + P !x @@ -20085,7 +18312,7 @@ Pd@QQ Q@Q@ bR `a -N D +N D @ Q@Q& @@ -20100,10 +18327,10 @@ x/Ǡ @A
/Ǡ P@PP4@a - - + + I| - Iz + I "p "h bp @@ -20147,7 +18374,7 @@ RP#LG . -`Z +WZ . @@ -20193,35 +18420,33 @@ Z Xш PH Ȉ X -H -*I*d +H *AL+CLh j@ j - - - -2 ! , -x3 - - - + @ I` -y` -y$ - - - - - -Cd -)L - - -%% + +y# +x + + +" + +Cc +)L + + +@y -GGG%&&&r !@ +GGG>%&&&C +D@f +&Lo + + + + G @@ -20242,58 +18467,84 @@ GGG%&&&r !@ Gd J - + Q ? -RP@' - - +RP + +C. + + ? NI HB -@GAǀ -Gr@8HH - - - +@GA +GACHH +D@b +C + + + + + o G#LB0 o A R LI - -% -H -` - - - + +%£ +H +c +C + +G +@c +&Lo + + +G + + +&Lo + + +Z` + -@? NI HB +@? NI HB @ - -I - - -@ + + LJ - - + +Da +@a + +I + + L - q -, -@ -l - + + +I +, + + l - -x + +x @ - + + +@ +Da +C@ + q @@ -20301,8 +18552,8 @@ x G -1@q -@#G +A +@#G \ @@ -20311,7 +18562,12 @@ H - + + +@ +Da +C@ + q!G` xZ @x @@ -20320,8 +18576,8 @@ H G -qY -#G +A +@#G \ @@ -20347,53 +18603,63 @@ GA` @x G - - + + x -I#@ +I# Hx !#(HH5a @x -@# + +I@ + QLFLAIH p "@ȁ CL@ -@L@ +@L@ H -a - +a @ + G - - - -x@ -I x - - - - -H - - + + +ID ` +@~ + +@x@ +I@ + + + +@ + +@a +G +H + + +@ + +@ʢ A Q@ -G +G Z` @ @ -I@@x @@ +I@@x @@ @x - + aH @ - -m` + +mmi @a J @@ -20403,7 +18669,7 @@ x @ a GLLa H - + x @d @@ -20423,47 +18689,51 @@ Q RPPCL @
-L -J - r -x @ R - +L + + + +Da +C@ + +J + +J + b +x @ R + GB @x G -@ +@ +C` @x s s - + L! o - -H - + +H + - -ǁ -U - -GL@H - - -1 - -x -Ct -.GLK.H - -+~ + + + + + + +x +Ct + P !x - + /ǣ -Pd@QQ +Pd@QQ ¢R @ BR @@ -20476,13 +18746,13 @@ Q@Q@ @ Q@Q& - + x/Ǡ t 4T - + B @A
/Ǡ P@PP4@a @@ -20513,13 +18783,13 @@ I@ 8 /$ @ -!a "a # Λ +!a "a # Λ ? ?aǠAPCG - - + + -ȁ +ȁ Q @@ -20534,7 +18804,7 @@ RP#LG . -`Z +miZ . @@ -20580,40 +18850,35 @@ Z Xш PH Ȉ X -H -*I*d +H + +H + + + + + + *AL+CLh j@ j - - - -2 ! , -x3 - - + @ I` -=y` -9y# -x - -@U -" - -Cd -)L - - -% +@x` + + + +@ + +@tyo +Cc +)L + + + -GGG>%&&&C -D@f -&Lo - - - - +GGG%&&&r !@ G @@ -20634,85 +18899,58 @@ GGG>%&&&C Gd J - + Q ? -RPX - -C. - - +RP + + ? NI HB -@GA -GA@gHH -D@b -C - - - - - - - +@GAǀ +Gr@
HH + + o G#LB0 o A R LI - -%£ -H -c -C - -G -@c -&Lo - - -G - - -&Lo - - -Z` - + +% +H +` + + + -@? NI HB +? NI HB @ - - + +I + + + LJ - -Da -@a - -I - - + + L - q - -@ -l - + + +I +, + + l -y -x +x +x @ - - -@ -Da -C@ - + q @@ -20720,8 +18958,8 @@ x G -1@ -@#G +A +@#G \ @@ -20730,12 +18968,7 @@ H - - -@ -Da -C@ - + q!G` xZ @x @@ -20744,8 +18977,8 @@ H G -q -#G +A + \ @@ -20771,65 +19004,52 @@ GA` @x G - - + + x -I +I@n#n Hx !#(HH5a @x -# -I@ - +a#@b QLFLAIH p "@ȁ CL@ -@L@ @ +@L@ s H -a - +a + G - - -ID ` -~x - -I@ - - - -@ - -@a -G -H - - - - -@ - -@ʢ + + + + +I + + + +H + + A Q@ -G +G Z` @ @ -I@@x @@ - +I@@x @@ @x - + aH @ - ---p + +W @a J @@ -20839,7 +19059,7 @@ x @ a GLLa H - + x @d @@ -20859,56 +19079,42 @@ Q RPPCL @
-L - - - -Da -C@ - -J - -J +L + b -@x @ R - + + GB @x G -@ -C` +@ @x s s -@ + L! o - -H - + +H + - -ǁ -{ - -GL@H - - -1` - -x -Ct -.GLK.H - -} + + + + + + +x +Ct +Y~ P !x - + /ǣ -Pd@QQ +Pd@QQ ¢R @ BR @@ -20921,13 +19127,13 @@ Q@Q@ @ Q@Q& - + x/Ǡ t 4T - + B @A
/Ǡ P@PP4@a @@ -20958,13 +19164,13 @@ I@ 8 /$ @ -!a "a # Λ +!a "a # Λ ? ?aǠAPCG - - + + -ȁ +ȁ Q @@ -20979,7 +19185,7 @@ RP#LG . --pZ +WZ . @@ -21025,41 +19231,25 @@ Z Xш PH Ȉ X -H - -H - - - - - - -*I*d +H *AL+CLh j@ j - - - -2 ! , -x3 - - - + @ I` -
y` - y$ - - - - - -Cd -)L - - -% + +x# + + + + + +Cc +)L + + +sy GGG%&&&r !@ G @@ -21086,14 +19276,13 @@ Gd Q ? -RP* +RP@ ? NI HB @GAǀ -Gr@;HH - - +Gr@@HH + o G#LB0 o @@ -21104,23 +19293,23 @@ G#LB0 o H ` - - + + -@? NI HB +? NI HB @ - + I - - + + LJ -@ - +@ + L @@ -21128,17 +19317,18 @@ H LJ J ʧ -q -, -@ -l - + + +I +, + + l - -x +x +x @ - + q @@ -21146,8 +19336,8 @@ x G -1@r -#G +A + \ @@ -21156,7 +19346,7 @@ H - + q!G` xZ @x @@ -21165,8 +19355,8 @@ H G -q -#G +A +#G \ @@ -21192,53 +19382,53 @@ GA` @x G - + x -I +I Hx !#(HH5a @x -# +e# QLFLAIH p "@ȁ CL@ -@L@ @ +@L@ @w H -a @ +a + G - - - -x@ -I x - - - - -H - - + + + + +I + + + +H + + A Q@ -G +G Z` @ @ -I@@x @@ +I@@x @@ @x - + aH @ - -m`@ + +W @a J @@ -21248,7 +19438,7 @@ x @ a GLLa H - + x @d @@ -21268,11 +19458,11 @@ Q RPPCL @
-L -J - r - - +L + + b + + GB @@ -21282,27 +19472,22 @@ G @ @x s s -@ + L! o - -H - + +H + - -ǁ -U - -GL@H - - -1 - -x -Ct -.GLK.H - -@(~ - + + + + + +x +Ct +U~ + +P P !x @@ -21317,7 +19502,7 @@ Pd@QQ Q@Q@ bR `a -N D +N D @ Q@Q& @@ -21332,10 +19517,10 @@ x/Ǡ @A
/Ǡ P@PP4@a - - + + I| - I + Iz "p "h bp @@ -21379,7 +19564,7 @@ RP#LG . -`Z +WZ . @@ -21425,4793 +19610,1689 @@ Z Xш PH Ȉ X -H -*I*d +H *AL+CLh j@ j - - - -2 ! , -x3 - - - FL CL R@ -I` -x` -xH! - -G
@a - -@x -y - - -, - - - -* - -! - - -J - - -,! - -G$ -` - - - -@I - -GIǁ -I@ -o -I@Ip v Gv v Gw p v Gv v Gw - -kWRk4P`@rP"kOPrk@gP -ȿ - -r -H - -@I - ` - -G
` -x - G`HR@ -`"@ - - -b - -2x -B -@ - - - - - -A - -@a - - - - - - -J` - - - - @I
^ G \ G Z -I - - - -I -@ -QGbɑ@I2 -QHbIb P PCIIb - -QRIc P PCIIG
B - -G LI B HbBx a t - -x@ - ɀ - - -ɱ - - - -GIǁ a -O -I@I - - - -@Lr@ǁ -` -H - -I - -@a - - -L -H2X - - -x@ - A$ -@c - - - ʣ H -@x - - - - Gx -H - - & - -a -% - - -$ -a# -HJ!" -! - G - -A Q@ -G - -@xGH ` -xGP ` -xGX ` -@xG@ H` -xGH ` - - - G -@x I IB@HB@ - - - - - - - - - -I -I - -AL"CLh @ - - -( -x(h -@ -i -(A -h -A - -߿ -( -( )CL): - - - - - - - -@xa - -I -A@_` -~ -A@ - - - - - - -s s Eg - -a - - -L@a - - - - -E@a - -L - -D - ! -<Ȁa -E<B - -B - - = -E=== E DL>L -b - -D@ @ - -xHR& b@I"@J@Hb - FL CL R@ -I` -x` -xH! -@x -G
@a - -@x -y - - -, - - - -@2 - -! - - -J - - -,! - -G$ -` - - - -@I - -GIǁ -I@ -o -I@IH IQ - - -kWRk4P`@rP"kOPrk@gP -ȿ - -r -H - -@I - ` - -G
` -@x - G`HR@ -`"@ - - - -b - -2x -B - - - - - - -A - -@a - - - - - - -J` - - - - @I
^ G \ G Z -I - - - -I -@ -QGbɑ@I2 -QHbIb P PCIIb - -QRIc P PCIIG
B - -G LI B HbBx a t - -x@ - ɀ - - -ɱ -x - - -GIǁ a -O -I@I - - - -@Lr@ǁ -` -H - -I - -@a - - -L -H2X - - -x@ - A$ -@c - - - ʣ H -@x - - - - Gx -H - - & - -a -% - - -$ -a# -HJ!" -! - G - -A Q@ -G - -@xGH ` -xGP ` -xGX ` -@xG@ H` -xGH ` - - - G -@x I IB@HB@ - - - - - - - - - -I -I - -AL"CLh @ - - -( -x(h -@ -i -(A -h -A - -߿ -( -( )CL): - - - - - - - -@xa - -I -A@_` - -A@ - - - - - - -s s Eg - -a - - -L@a - - - - -E@a - -L - -D - ! -<Ȁa -E<B - -B - - = -E=== E DL>L -b - -D@ @ - -xHR& b@I"@J@Hb - FL CL R@ + +3 + + + +ɑ zI ++ @ I` -x` -xH! - -G
@a - -@x -y - - -, - - - -* - -! - - -J - - -,! - -G$ -` - - - -@I - -GIǁ -I@ -o -I@Ip v Gv v Gw p v Gv v Gw - -kWRk4P`@rP"kOPrk@gP -ȿ - -r -H - -@I - ` - -G
` -x - G`HR@ -`"@ - - -b - -2x -B -@ - - - - - -A - -@a - - - - + zɀ` +y +@&xP + +>x@<x + + + + + +) + +J@ +
J +.8@ - -J` - - - - @I
^ G \ G Z -I - - - -I -@ -QGbɑ@I2 -QHbIb P PCIIb - -QRIc P PCIIG
B - -G LI B HbBx a t - -x@ - ɀ - - -ɱ - - - -GIǁ a -O -I@I - - - -@Lr@ǁ -` -H - -I - -@a - - -L -H2X - - -x@ - A$ -@c - - - ʣ H -@x - - - - Gx -H +GI , +O +I@ +I - & - -a -% - - -$ -a# -HJ!" -! - G - -A Q@ -G - -@xGH ` -xGP ` -xGX ` -@xG@ H` -xGH ` - - - G -@x I IB@HB@ - - - - - - - - - -I -I - -AL"CLh @ - - -( -x(h -@ -i -(A -h -A - -߿ -( -( )CL): - - - - - - - -@xa - -I -A@_` -~ -A@ - - - - - - -s s Eg - -a - - -L@a - - - - -E@a - -L - -D - ! -<Ȁa -E<B - -B - - = -E=== E DL>L -b - -D@ @ - -xHR& b@I"@J@Hb - FL CL R@ -I` -x` -xH! -@x -G
@a - -@x -y - - -, - - - -@2 - -! - +o +I@ +=Lʀ +I + bp + + + + +Q RPPCL + +@J +A +A +& +% +( +\ +!p! + +J + + + + +LJ +@ + H G +G@ +` +x
` + +x
+ +xvG` +@x@x@x + QL +FLHAȂ +G + + +q@ + + + + + +B + +<B/L% L' @ 0@ + + +G + +GI +@LBLAQ +` + + +$ + + + +@x$@ +W(Ǥ +*e@-UU +\!@xU@-U +¢V + +@TeP W| NB +EE@ +BV +@@xAՀe +&N U +TeP W| NB +U@%$U@x$&) +bV +`aV0 +&N U'$ + + +$` + + + + + u V,E +@ + + +B +@A
Ǡ + +A + -J - - -,! - -G$ -` - - - -@I - -GIǁ -I@ -o -I@IH IQ - - -kWRk4P`@rP"kOPrk@gP -ȿ - -r -H - -@I - ` - -G
` -@x - G`HR@ -`"@ - - - -b - -2x -B - - - - - - -A - -@a - - - - - - -J` - - - - @I
^ G \ G Z -I - - - -I -@ -QGbɑ@I2 -QHbIb P PCIIb - -QRIc P PCIIG
B - -G LI B HbBx a t - -x@ - ɀ - - -ɱ -x - - -GIǁ a -O -I@I +@@x +NNN@ + - - -@Lr@ǁ -` -H - -I - -@a - - -L -H2X - - -x@ - A$ -@c - - - ʣ H -@x - - - - Gx -H - - & - -a -% - - -$ -a# -HJ!" -! - G - -A Q@ -G - -@xGH ` -xGP ` -xGX ` -@xG@ H` -xGH ` - - - G -@x I IB@HB@ - - - - - - - - - -I -I - -AL"CLh @ - - -( -x(h -@ -i -(A -h -A - -߿ -( -( )CL): - - - - - - - -@xa - -I -A@_` - -A@ - - - - - - -s s Eg - -a - - -L@a - - - - -E@a - -L - -D - ! -<Ȁa -E<B - -B - - = -E=== E DL>L -b - -D@ @ - -xHR& b@I"@J@Hb - I ! - `xI@ C - @ -I - - -@x - - -@@` -RxL -` - -Go - - - -6L Kl - -K -ˠ - -QBN - - - - - -@xa -@ -@ - -@@ II24 A" - - Iɐ ɐ @ I SIH@! - -@I@ - -x@ -Iɀ -ɡ -IG# - -I -H -IA" - -I! - - -G
A Q@ -G - - - G - - -GHLȁP GL G A -q@ - -
Go - - -@I - - -H - -GxGMG -)L -q@ - - - -G@ - - -@F - - @a - -Gȁ ` - - - -B J@ -B -B B -K,@xBX I` -xBP ` - -,((LG/ - - -o - -GG - -d - -"& - - - -. -I - % -GMG -@ -G - - - -G@ - -@ -H - - -@; - - - - - -@Aa -x - - -B - -G - -Ba -G - - -"& -G -@x - -x - - -G - - -ǀ -2@ - -G -ǀ` -
x - -@ - - - - -GG - -@ -@ -BX J -BP -BH J - -(`xh@(C( -(( -x -@@ -@ -O - -MNC@ -@ xLM -O - - -@@
M@ -xMMM@
NNNNNNNQUNY -
-M@ -B -͂ -@Ixx
- -
O -
-
O -
M@
-OO -x -MC@
-
` -@ -x
P3@@$ -x -́ -
-@x - @
NMӀ
M3@M@
X
IM
tr M# - - -G@b - -IGB - - - - -@ - -!L@ -"L @ - -£ -J -@ -A - -@xo -r -@xJ JM` - - - - -@" - - -@ - -@ -@ -xV JM` - - -@ - - - - - - - -J JY" !L MJ" !\ @ - - -J - -c -@xK` -JAb -x -ˁ -` - - -J - - - - -pIrIB - - -I @x - -@} - -@ - @ x -x hx! V hx! T -U@e8hxqxU -TqxU5@ - -o8Q `8 - -e8hx% V - -ր` -xhx%@ - - U - - - @ -@x# -xI -x -$ -$Y@@ -$ -$)@S -d -
" !@ " !D MH - -H - -p r -r ]B - - ÿ - - - -H -@ - - s -q L - u HRJ RT v I@ -@I@ -@HP U SI -I UIǁ O - -@ -HP SI - +@@ II24 A" + + Iɐ ɐ @ IIR + +@I@ +I + +K +K +@@ +@ +G + +<G +< +` +xJ + +xIǀ! +< +J + +xJ +xJ +G2 +H" + + +2 +xJ +3@ +G4 + + +~ $ +H +H +! + +N,x + + +sx +@ + +S + x.I,J) +` +,@ +I +,@Ȅ@ -,
- +@ǠA+,- + +G +;H -% +< + + + +H@a - -!`xa@!C! - - - - - - I -A - - - ¥ -I - -A - -Di - - - - -G` - -x B I D` - -EG@ -ŀ -EŁx - -EG -ł -EŃ " @" ` - -G` - - - -EG -ń@ -EŅ@x -EG -ŀ -EŁ - -EG -ņ@ -EŇ@x -EG -ł -EŃ@ -` - I ! - `xI@ C - @ -I -.x -(x -@x - - -@` - -` - -Go - -~x - - -6L k - -K -ˠ -@yxTi -Q"N - - - - - -rxa -@ -@ @qx - -@@ II24 A" - - Iɐ ɐ @ I SIH@! - -@I@ - -x@ -Iɀ -ɡ -IG# - -I -H -IA" - -I! - - -G
A Q@ -G - - - G - - Ĩ -H(H(BL Q IGv v P -GHLȁP GL G A -q@ - @q@I -
Go - - -QI Q -@I - -H -H - -G@xGMG -)Lx -q@ - - - -G@ - - -@e - -H - - -Gȁ ` - - - -,((LG/ - - -o - -GG - -y - -"& - - - -.@n -I - -@ #`d` - -@U - - - - -H &(G` -GMG(LG@. -CG((LG/ -G - - -@Aa -x - - -B - -G - -Ba -G -? - -"& -G -G -` -@x; -@x@- - -x - - -G - - -ǀ -2@ -G -ǀ` -
x - - - - - - -GG - - - -BX J -BP -BH J - -(`xh@(C( -(( -HH -G@ -R - -x -@@ -@ -O - -MNC@ -@ xLM -O - - -@@
M@ -xMMM@
NNNNNNNQUNY -
-M@ -B -͂ -@Ixx
- -
O -
-
O -
M@
-OO -x -MC@
-
` -@ -x
P3@@$ -x -́ -
-@x - @
NMӀ
M3@M@
X
IM
tr M# - - -G@b - -IGB - - - - -A@Nȁ -@ - -!L@ -"L @ - -£ -J -@ -A - -@xo -r -@xJ JM` - - - - -@" - - -@ - -@ -@ -xV JM` - - -@ - - +H +;I - - - - -J JY" !L MJ" !\ @ - - -J + + + +GǑ@ʡ +;GR N;3 +xH;;G + +G @ + +GH;ȡ@ʡ + + + +G @@ + +G ; + +G @@ +I; + + J + + +J9 + + +J +G!a + + + +!sstG +@b + +GuuG + +@b + + x2 -c -@xK` -JAb -x -ˁ -` +< + + + +J +@b - -J - - - - -pIrIB - - -I @x - ,IB -ɱ@ - - @ -II @ - -x ,IB -ɱ@ - - @ -II @ -,C - -C -A - -2@ - -} - -@ - @ x -x hx! V hx! T -U@e8hxqxU -TqxU5@ - -o8Q `8 - -e8hx% V - -ր` -xhx%@ - - U - - ~ - -H -(G@ -, -<@ -P -XGA - - - - G@ - ! - $@ - < - HGA - x@@Gr1 - -G@ - Z - - -Gb@ -GB@ - -@x# -xI -x -$ -$Y@@ -$ -$)@S -d - -H -@ -p r -r - ÿ - - - -H - - - s -q u ILI -@I@HP U SI -I UIǁ O - -K<K4T - - - -!`xa@!C! - - - - - - I -A - - - ¥ -I - -A - -Di - - - - -G` - -x B I D` - -EG@ -ŀ -EŁx - -EG -ł -EŃ " K` -@" ` - -G` - - -EG -ń -EŅ " -EG -ņ -EŇ " - I ! - `iI@ C - @ -I - - -@x - - -@@` -RxL -` - -Go - - - -6L Kl - -K -ˠ - -QBN - - - - - -@xa -@ -@ - -@@ II24 A" - - Iɐ ɐ @ I SIH@! - -@I@ - -x@ -Iɀ -ɡ -IG# - -I -H -IA" - -I! - - -G
A Q@ -G - - - G - - -GHLȁP GL G A -q@ - -
Go - - -@I - - -H - -GxGMG -)L -q@ - - - -G@ - - -@F - - @a - -Gȁ ` - - +. -B J@ -B -B B -K,@xBX I` -xBP ` - -,((LG/ - - -o - -GG - -d - -"& - - - -. -I - % -GMG -@ -G - - - -G@ - -@ -H - - -@; - - - - - -@Aa -x - - -B - -G - -Ba -G - - -"& -G -@x - -x - - -G - - -ǀ -2@ - -G -ǀ` -
x - -@ - - - - -GG - -@ -@ -BX J -BP -BH J - -(`ih@(C( -(( -x -@@ -@ -O - -MNC@ -@ xLM -O - - -@@
M@ -xMMM@
NNNNNNNQUNY -
-M@ -B -͂ -@Ixx
- -
O -
-
O -
M@
-OO -x -MC@
-
` -@ -x
P3@@$ -x -́ -
-@x - @
NMӀ
M3@M@
X
IM
tr M# - - -G@b - -IGB - - - - -@ - -!L@ -"L @ - -£ -J -@ -A - -@xo -r -@xJ JM` - - - - -@" - - -@ - -@ -@ -xV JM` - - -@ - - - - - - - -J JY" !L MJ" !\ @ - - -J - -c -@xK` -JAb -x -ˁ -` - - -J - - - - -pIrIB - - -I @x - -@} - -@ - @ x -x hi! V hi! T -U@e)hiqiU -TqiU5@ - -o)Q `) - -e)hi% V - -ր` -xhi%@ - - U - - - @ -@x# -xI -x -$ -$Y@@ -$ -$)@S -d -
" !@ " !D MH - -H - -p r -r ]B - - ÿ - - - -H -@ - - s -q L - u HRJ RT v I@ -@I@ -@HP U SI -I UIǁ O - -@ -HP SI - - - -!`ia@!C! - - - - - - I -A - - - ¥ -I - -A - -Di - - - - -G` - -x B I D` - -EG@ -ŀ -EŁx - -EG -ł -EŃ " @" ` - -G` - - - -EG -ń@ -EŅ@x -EG -ŀ -EŁ - -EG -ņ@ -EŇ@x -EG -ł -EŃ@ -` - I ! - `xI@ C - @ -I -.x -(x -@x - - -@` - -` - -Go - -~x - - -6L k - -K -ˠ -@yxTi -Q"N - - - - - -rxa -@ -@ @qx - -@@ II24 A" - - Iɐ ɐ @ I SIH@! - -@I@ - -x@ -Iɀ -ɡ -IG# - -I -H -IA" - -I! - - -G
A Q@ -G - - - G - - Ĩ -H(H(BL Q IGv v P -GHLȁP GL G A -q@ - @q@I -
Go - - -QI Q -@I - -H -H - -G@xGMG -)Lx -q@ - - - -G@ - - -@e - -H - - -Gȁ ` - - - -,((LG/ - - -o - -GG - -y - -"& - - - -.@n -I - -@ #`d` - -@U - - - - -H &(G` -GMG(LG@. -CG((LG/ -G - - -@Aa -x - - -B - -G - -Ba -G -? - -"& -G -G -` -@x; -@x@- - -x - - -G - - -ǀ -2@ -G -ǀ` -
x - - - - - - -GG - - - -BX J -BP -BH J - -(`xh@(C( -(( -HH -G@ -R - -x -@@ -@ -O - -MNC@ -@ xLM -O - - -@@
M@ -xMMM@
NNNNNNNQUNY -
-M@ -B -͂ -@Ixx
- -
O -
-
O -
M@
-OO -x -MC@
-
` -@ -x
P3@@$ -x -́ -
-@x - @
NMӀ
M3@M@
X
IM
tr M# - - -G@b - -IGB - - - - -A@Nȁ -@ - -!L@ -"L @ - -£ -J -@ -A - -@xo -r -@xJ JM` - - - - -@" - - -@ - -@ -@ -xV JM` - -@ - - - - - - - -J JY" !L MJ" !\ @ - - -J - -c -@xK` -JAb -x -ˁ -` + +J + + + + + + + + + +~; + + + + +@~G . G. GGs$$ +o + + + +H + $@ +@I QIs Q #G)!D G)d + +Q;! + + + + + - -J - - - - -pIrIB + + +G,",@a +QI + + +Q +? +R@4yP,*(I0 ( + + + +N" $ +>?L ?LIB +A + + á +H! - -I @x - ,IB -ɱ@ - - @ -II @ - -x ,IB -ɱ@ - - @ -II @ -,C - -C -A - -2@ - -} - -@ - @ x -x hx! V hx! T -U@e8hxqxU -TqxU5@ - -o8Q `8 - -e8hx% V - -ր` -xhx%@ - - U - - ~ - -H -(G@ -, -<@ -P -XGA - - - - G@ - ! - $@ - < - HGA - x@@Gr1 - -G@ - Z - - -Gb@ -GB@ - -@x# -xI -x -$ -$Y@@ -$ -$)@S -d - -H -@ -p r -r - ÿ - - - -H - - - s -q u ILI -@I@HP U SI -I UIǁ O - -K<K4T - - - -!`xa@!C! - - - - - - I -A - - - ¥ -I - -A - -Di - - - - -G` - -x B I D` - -EG@ -ŀ -EŁx - -EG -ł -EŃ " K` -@" ` - -G` - - -EG -ń -EŅ " -EG -ņ -EŇ " - I ! - `xI@ C - @ -I - - -@x - - -@@` -RxL -` - -Go - - - -6L Kl - -K -ˠ - -QBN - - - - - -@xa -@ -@ - -@@ II24 A" - - Iɐ ɐ @ I SIH@! - -@I@ - -x@ -Iɀ -ɡ -IG# - -I -H -IA" - -I! - - -G
A Q@ -G - - - G - - -GHLȁP GL G A -q@ - q@I -
Go - - -@I - - -H - -GxGMG -)L -q@ - - - -G@ - - -F - - @a - -Gȁ ` - - - -B J@ -B -B B -K,@xBX I` -xBP ` - -,((LG/ - - -o - -GG - -d - -"& - - - -. -I - % -GMG -@ -G - - - -G@ - -@ -H - - -; - - - - - -@Aa -x - - -B - -G - -Ba -G - - -"& -G -@x@ - -x - - -G - - -ǀ -2@ -G -ǀ` -
x - - - - - - -GG - - - -BX J -BP -BH J - -(`xh@(C( -(( -x -@@ -@ -O - -MNC@ -@ xLM -O - - -@@
M@ -xMMM@
NNNNNNNQUNY -
-M@ -B -͂ -@Ixx
- -
O -
-
O -
M@
-OO -x -MC@
-
` -@ -x
P3@@$ -x -́ -
-@x - @
NMӀ
M3@M@
X
IM
tr M# - - -G@b - -IGB - - - - -A@Nȁ -@ - -!L@ -"L @ - -£ -J -@ -A - -@xo -r -@xJ JM` - - - - -@" - - -@ - -@ -@ -xV JM` - - -@ - - - - - - - -J JY" !L MJ" !\ @ - - -J - -c -@xK` -JAb -x -ˁ -` + à +G +IJr @ +IJ@ +` + + +Iʡ + + + +@I
ȁ +x +w +Jx + +v~ + + + + +A +b +xG + + +Gǡ@ʡ + +G + + ++ +/R + + +G# +# +q@)#q s +s s +' +L! o +!*! +G) +))YxJx +))%xx +G) +))Qx +)) +G$) + + +$ +@o + + + +'x 'LI! &'()) a ' 'LI! H$ a ' CI#G D +#LGB0 +@ +@ +* + + + @o +I@ +(@(`} + A R K +(@xGB +%B +G +H + +` +x + + + +'xI* +S@& NI HB +@ +N @o +@N @n +$m + +G$) + +' +'x 'LI! &') a ' 'LI! H$ a '#G D %$ +o + +!L"L%'Le! ,a +* +$ʀ - -J - - - - -pIrIB - - -I @x - -} - -@ - @ x -x hx! V hx! T -U@e8hxqxU -TqxU5@ - -o8Q `8 - -e8hx% V - -ր` -xhx%@ - - U - -O~ - -@x# -xI -x -$ -$Y@@ -$ -$)@S -d -
" !@ " !D MH - -H - -p r -r ]B - - ÿ - - - -H -@ - - s -q L - u HRJ RT v I@ -@I@ -@HP U SI -I UIǁ O - -@ -HP SI - - - -!`xa@!C! - - - - - - I -A - - - ¥ -I - -A - -Di - - - - -G` - -x B I D` - -EG@ -ŀ -EŁx - -EG -ł -EŃ " @" ` - -G` - - - -EG -ń@ -EŅ@x -EG -ŀ -EŁ - -EG -ņ@ -EŇ@x -EG -ł -EŃ@ -` - I ! - `xI@ C - @ -I - - -@x - - -@@` -RxL -` - -Go - - - -6L Kl - -K -ˠ - -QBN - - - - - -@xa -@ -@ - -@@ II24 A" - - Iɐ ɐ @ I SIH@! - -@I@ - -x@ -Iɀ -ɡ -IG# - -I -H -IA" - -I! - - -G
A Q@ -G - - - G - - -GHLȁP GL G A -q@ - q@I -
Go - - -@I - - -H - -GxGMG -)L -q@ - - - -G@ - - -F - - @a - -Gȁ ` - - + + +( +%&&&r !G%@ +G + +S& +F -B J@ -B -B B -K,@xBX I` -xBP ` - -,((LG/ - - -o - -GG - -d - -"& - - - -. -I - % -GMG -@ -G - - - -G@ - -@ -H - - -; - - - - - -@Aa -x - - -B - -G - -Ba -G - - -"& -G -@x@ - -x - - -G - - -ǀ -2@ -G -ǀ` -
x - - - - - - -GG - - - -BX J -BP -BH J - -(`xh@(C( -(( -x -@@ -@ -O - -MNC@ -@ xLM -O - - -@@
M@ -xMMM@
NNNNNNNQUNY -
-M@ -B -͂ -@Ixx
- -
O -
-
O -
M@
-OO -x -MC@
-
` -@ -x
P3@@$ -x -́ -
-@x - @
NMӀ
M3@M@
X
IM
tr M# - - -G@b - -IGB - - - - -A@Nȁ -@ - -!L@ -"L @ - -£ -J -@ -A - -@xo -r -@xJ JM` - - - - -@" - - -@ - -@ -@ -xV JM` - - -@ - - - - - - - -J JY" !L MJ" !\ @ - - -J - -c -@xK` -JAb -x -ˁ -` - - -J - - - - -pIrIB - - -I @x - -} - -@ - @ x -x hx! V hx! T -U@e8hxqxU -TqxU5@ - -o8Q `8 - -e8hx% V - -ր` -xhx%@ - - U - -O~ - -@x# -xI -x -$ -$Y@@ -$ -$)@S -d -
" !@ " !D MH - -H - -p r -r ]B - - ÿ - - - -H -@ - - s -q L - u HRJ RT v I@ -@I@ -@HP U SI -I UIǁ O - -@ -HP SI - - - -!`xa@!C! - - - - - - I -A - - - ¥ -I - -A - -Di - - - - -G` - -x B I D` - -EG@ -ŀ -EŁx - -EG -ł -EŃ " @" ` - -G` - - - -EG -ń@ -EŅ@x -EG -ŀ -EŁ - -EG -ņ@ -EŇ@x -EG -ł -EŃ@ -` - I ! - `xI@ C - @ -I -.x -(x -@x - - -@` - -` - -Go - -~x - - -6L k - -K -ˠ -@yxTi -Q"N - - - - - -rxa -@ -@ @qx - -@@ II24 A" - - Iɐ ɐ @ I SIH@! - -@I@ - -x@ -Iɀ -ɡ -IG# - -I -H -IA" - -I! - - -G
A Q@ -G - - - G - - Ĩ -H(H(BL Q IGv v P -GHLȁP GL G A -q@ - q@I -
Go - - -QI Q -@I - -H -H - -G@xGMG -)Lx -q@ - - - -G@ - - -d - -H - - -Gȁ ` - - - -,((LG/ - - -o - -GG - -y - -"& - - - -.@n -I - -@ #`d` - -T - - - - -H &(G` -GMG(LG@. -CG((LG/ -G -@ - -@Aa -x - - -B - -G - -Ba -G -? - -"& -G -G -` -@x; -@x, - -x +* + +$ @o +&I@ + + +, + +-xB + +G - -G - - -ǀ -2@ -EE@ -G -ǀ` -
x +-J +Fa + + + ++ + -@ - - - - -GG +g +J+J + + +Q +? +RP +@#\ a +L+L + +, + +@} +I@ ` + ~I,Db +@x +-J + + +-G% +! -@ -@ -BX J -BP -BH J - -(`xh@(C( -(( -HH -G@ -R - -x -@@ -@ -O - -MNC@ -@ xLM -O - - -@@
M@ -xMMM@
NNNNNNNQUNY -
-M@ -B -͂ -@Ixx
- -
O -
-
O -
M@
-OO -x -MC@
-
` -@ -x
P3@@$ -x -́ -
-@x - @
NMӀ
M3@M@
X
IM
tr M# - - -G@b - -IGB - - - - -@ - -!L@ -"L @ - -£ -J -@ -A - -@xo -r -@xJ JM` +-J+ + +x +! + + + @a + +x + b@ʢ c +$"L2@ + + + +CALc +AA K)` +! + + +@ +a $a ' + N, +?G)á +,@ǠA+ ++?aǠA+PCG + + + +@ +G + +ߏN LJ +J2x +@Ȇ + +0 +` + + + C!?C` + + 1 +@ +M*@I +G + *,@ +@@ +M*@I + *,@ +@ +M*@I + +ql +@0 +G + ,@ +@@0 + ,@ +@0 +qp + +qp +` + +qIq + + +J +O+ +a
` +z + +."@ +o@l + +J + +O+ + +a
` +z + +."@ +o@l + +G@@ + + + + + +H +Hs + + +@r + +@ + +@ + +x + +@ +x +W~ +
@R#LJ @U~ + + + + +r +@D~G@Q +
I + +6~ +3~ M + +*#G@H
Q +xH@B H@ +Q +Q + + + +#@#G@Q +G@Q +@ + / +B + / + + +;p ; + +GС@ʡ + +G@!x + + +G +!I@ +R B@h + ?C +H:
B G) +@!D # +G +G +GB G +G +} +xQ + +;Gp ; + +GБ@ʡ + + ;R` G)"j ! (! )I + - - - -@" +@ + +Ϡ +Aaa + +@G1 +N + +I + - -@ - -@ -@ -xV JM` +@ +G +Ϡ +Aaa +@ +@ + +I,J:9>>>G@ +@ +s@ +c@ +T@ + +G$@ +@&x + + + - -@ - - + + + +G @ + I + +CJ +G:G@c +q@1@ɑ + I + + + +.x G` +xG +x +x@9 + +r,s-nuua u +qs@! +xt +~ +@@ + +@@ + +} + + + a +I +0020ȁ + + + +zJa CG + + +H + +t + + + +B +s#sRP G)"j ! + +B @#BH #BP B @ s@IGr @ G + H + + +a +G@GA +I +I + + @ +#"@ + I + +@*x +@ +O + +" +x$r$ +O +, +" + +I - - - - -J JY" !L MJ" !\ @ - - -J + + +G @@# + +G"@ # + +L + +A +pA + +B@ +p3@ + + + + +1@A @@N @@ + +@x + + + +
+ +P + + + + +x@ +C + + + + +@x + + + + + + + + + C!?C` + +q + + + +K +@x +PH NL +xqMЀ LF +PJ N, +
+@xM@
Ҁ +
+@ +0q\ +J@ +@K<@Oq + +q +L@ +A@ +A@ +c@ +0Aa ,@ + +`! + + +A@ +0 + +Db +D` + + + + p T p0X +02p0 +K@ + +1L3 + + + + +0 +p +q<i +q
@ +@ + + +@ + +pF<@Op +a@ + +Q + + 2@ + +A + + + + 2@ + +A + + +q +1@ + + + 0 +0 + + + + + + + @ + +i + +3 + + + +ɑ zI ++ @ +I` + zɀ` +y +@&xP + +>x@<x + + + + + +) + +J@ +
J +.8@ -c -@xK` -JAb -x -ˁ -` +GI , +O +I@ +I - -J - - - - -pIrIB - - -I @x - ,IB -ɱ@ - - @ -II @ +o +I@ +=Lʀ +I + bp + + + + +Q RPPCL + +@J +A +A +& +% +( +\ +!p! + +J + + + + +LJ +@ + H G +G@ +` +x` -x ,IB -ɱ@ - - @ -II @ -,C - -C -A - -2@ - -@} - -@ - @ x -x hx! V hx! T -U@e8hxqxU -TqxU5@ - -o8Q `8 - -e8hx% V - -ր` -xhx%@ - - U - -@!~ - -H -(G@ -, -<@ -P -XGA - - - - G@ - ! - $@ - < - HGA - x@@Gr1 - -G@ - Z - - -Gb@ -GB@ - -@x# -xI -x -$ -$Y@@ -$ -$)@S -d - -H -@ -p r -r - ÿ - - - -H - - - s -q u ILI -@I@HP U SI -I UIǁ O - -K<K4T - +x
+ +xvG` +@x@xx + QL +FLHAȂ +G + + +q@ + + + + + +B + +<B/L' @ 0@ + + +G + +GI +@LBLAQ +` + + +$ + + + +@x$@ +W(Ǥ +*e@-UU +\!@xU@-U +¢V + +@TeP W| NB +EE@ +BV +@@xAՀe +&N U +TeP W| NB +U@%$U@x$&) +bV +`aV0 +&N U'$ + + +$` + + + + + u V,E +@ + + +B +@A
Ǡ + +A + + +@@x +NNN@ + + +@@ II24 A" + + Iɐ ɐ @ IIR + +@I@ +I + +K +K +@@ +@ +G + +<GU; +< +` +xJ + +xIǀ! +< +J + +xJ +xJ +G2 +H" + + +2 +xJ +3@ +G4 + + +~ $ +H +H +! + +N,x + + +sx +@ + +S + x.I,J) +` +,@ +I +,@Ȅ@ -,
- +@ǠA+,- + +G +;H -% +< + I + + H +H@a - -!`xa@!C! - - - - - - I -A - - - ¥ -I - -A - -Di - - - - -G` - -x B I D` - -EG@ -ŀ -EŁx - -EG -ł -EŃ " K` -@" ` - -G` - - -EG -ń -EŅ " -EG -ņ -EŇ " - I ! - `xI@ C - @ -I -.x -(x -@x - - -@` - -` - -Go - -~x - - -6L k - -K -ˠ -@yxTi -Q"N - - - - - -rxa -@ -@ @qx - -@@ II24 A" - - Iɐ ɐ @ I SIH@! - -@I@ - -x@ -Iɀ -ɡ -IG# - -I -H -IA" - -I! - - -G
A Q@ -G - - - G - - Ĩ -H(H(BL Q IGv v P -GHLȁP GL G A -q@ - q@I -
Go - - -QI Q -@I - -H -H - -G@xGMG -)Lx -q@ - - - -G@ - - -d - -H - - -Gȁ ` - - - -,((LG/ - - -o - -GG - -y - -"& - - - -.@n -I - -@ #`d` - -T - - - - -H &(G` -GMG(LG@. -CG((LG/ -G -@ - -@Aa -x - - -B - -G - -Ba -G -? - -"& -G -G -` -@x; -@x, - -x - - -G - - -ǀ -2@ -EE@ -G -ǀ` -
x - -@ - - - - -GG - -@ -@ -BX J -BP -BH J - -(`xh@(C( -(( -HH -G@ -R - -x -@@ -@ -O - -MNC@ -@ xLM -O - - -@@
M@ -xMMM@
NNNNNNNQUNY -
-M@ -B -͂ -@Ixx
- -
O -
-
O -
M@
-OO -x -MC@
-
` -@ -x
P3@@$ -x -́ -
-@x - @
NMӀ
M3@M@
X
IM
tr M# - - -G@b - -IGB - - - - -@ - -!L@ -"L @ - -£ -J -@ -A - -@xo -r -@xJ JM` - - - - -@" - - -@ - -@ -@ -xV JM` - - -@ - - + +;I - - - - -J JY" !L MJ" !\ @ - - -J + + + +GǑ@ʡ +@;GR N;3 +xH;;G + +G + +GH;ȡ@ʡ + + + +G @@@ + +G + +G @ +I; + + J + + +J9 + + +J +G!a + + + +!sstG +@b + +GuuG + +@b + + x2 -c -@xK` -JAb -x -ˁ -` +< + + + +J +@b - -J - - - - -pIrIB - - -I @x - ,IB -ɱ@ - - @ -II @ - -x ,IB -ɱ@ - - @ -II @ -,C - -C -A - -2@ - -@} - -@ - @ x -x hx! V hx! T -U@e8hxqxU -TqxU5@ - -o8Q `8 - -e8hx% V - -ր` -xhx%@ - - U - -@!~ - -H -(G@ -, -<@ -P -XGA - - - - G@ - ! - $@ - < - HGA - x@@Gr1 - -G@ - Z - - -Gb@ -GB@ - -@x# -xI -x -$ -$Y@@ -$ -$)@S -d - -H -@ -p r -r - ÿ - - - -H - - - s -q u ILI -@I@HP U SI -I UIǁ O - -K<K4T - - - -!`xa@!C! - - - - - - I -A - - - ¥ -I - -A - -Di - - - - -G` - -x B I D` - -EG@ -ŀ -EŁx - -EG -ł -EŃ " K` -@" ` - -G` - - -EG -ń -EŅ " -EG -ņ -EŇ " - I ! - `xI@ C - @ -I - - -@x - - -@@` -RxL -` - -Go - - - -6L Kl - -K -ˠ - -QBN - - - - - -@xa -@ -@ - -@@ II24 A" - - Iɐ ɐ @ I SIH@! - -@I@ - -x@ -Iɀ -ɡ -IG# - -I -H -IA" - -I! - - -G
A Q@ -G - - - G - - -GHLȁP GL G A -q@ - -
Go - - -@I - - -H - -GxGMG -)L -q@ - - - -G@ - - -@F - - @a - -Gȁ ` - - +. -B J@ -B -B B -K,@xBX I` -xBP ` - -,((LG/ - - -o - -GG - -d - -"& - - - -. -I - % -GMG -@ -G - - - -G@ - -@ -H - - -@; - - - - - -@Aa -x - -B - -G - -Ba -G - - -"& -G -@x - -x - - -G - - -ǀ -2@ - -G -ǀ` -
x - -@ - - - - -GG - -@ -@ -BX J -BP -BH J - -(`xh@(C( -(( -x -@@ -@ -O - -MNC@ -@ xLM -O - - -@@
M@ -xMMM@
NNNNNNNQUNY -
-M@ -B -͂ -@Ixx
- -
O -
-
O -
M@
-OO -x -MC@
-
` -@ -x
P3@@$ -x -́ -
-@x - @
NMӀ
M3@M@
X
IM
tr M# - - -G@b - -IGB - - - - -@ - -!L@ -"L @ - -£ -J -@ -A - -@xo -r -@xJ JM` - - - - -@" - - -@ - -@ -@ -xV JM` - - -@ - - - - - - - -J JY" !L MJ" !\ @ - - -J - -c -@xK` -JAb -x -ˁ -` + +J + + + + + + + + + +@~; + + +~ + +~G . G. GGs$$ +o + + + +H + $@ +@I QIs Q #G)!D G)d + +Q;! + + + + +~ - -J - - - - -pIrIB + + +G,",@a +QI + + +Q +? +R5yP,*(I0 ( + + + +N" $ +>?L ?LIB +A + + á +H! - -I @x - -@} - -@ - @ x -x hx! V hx! T -U@e8hxqxU -TqxU5@ - -o8Q `8 - -e8hx% V - -ր` -xhx%@ - - U - - - @ -@x# -xI -x -$ -$Y@@ -$ -$)@S -d -
" !@ " !D MH - -H - -p r -r ]B - - ÿ - - - -H -@ - - s -q L - u HRJ RT v I@ -@I@ -@HP U SI -I UIǁ O - -@ -HP SI - - - -!`xa@!C! - - - - - - I -A - - - ¥ -I - -A - -Di - - - - -G` - -x B I D` - -EG@ -ŀ -EŁx - -EG -ł -EŃ " @" ` - -G` - - - -EG -ń@ -EŅ@x -EG -ŀ -EŁ - -EG -ņ@ -EŇ@x -EG -ł -EŃ@ -` - I ! - `iI@ C - @ -I -.x -(x -@x - - -@` - -` - -Go - -~x - - -6L k - -K -ˠ -@yxTi -Q"N - - - - - -rxa -@ -@ @qx - -@@ II24 A" - - Iɐ ɐ @ I SIH@! - -@I@ - -x@ -Iɀ -ɡ -IG# - -I -H -IA" - -I! - - -G
A Q@ -G - - - G - - Ĩ -H(H(BL Q IGv v P -GHLȁP GL G A -q@ - q@I -
Go - - -QI Q -@I - -H -H - -G@xGMG -)Lx -q@ - - - -G@ - - -d - -H - - -Gȁ ` - - - -,((LG/ - - -o - -GG - -y - -"& - - - -.@n -I - -@ #`d` - -T - - - - -H &(G` -GMG(LG@. -CG((LG/ -G -@ - -@Aa -x - - -B - -G - -Ba -G -? - -"& -G -G -` -@x; -@x, - -x - - -G - - -ǀ -2@ -EE@ -G -ǀ` -
x + à +G +IJr @ +IJ@ +` + + +Iʡ + + + +@I
ȁ +x +w +Jx + +@x~ + +v~ + + +A +b +xG + + +Gǡ@ʡ +k~g#+#L +G + + ++ +/R + + +G# +# +q@)#q s +s s +' +L! o +!*! +G) +))YxJx +))%xx +G) +))Qx +)) +G$) + + +$ +@o + + + +'x 'LI! &'()) a ' 'LI! H$ a ' CI#G D +#LGB0 +@ +@ +* + + + @o +I@ +(@(`} + A R K +(@xGB +%B +G +H + +` +x + + + +'xI* +S@& NI HB +@ +N @o +@N @n +$m + +G$) + +' +'x 'LI! &') a ' 'LI! H$ a '#G D %$ +o + +!L"L%'Le! ,a +* +$ʀ -@ - - - - -GG + + +( +%&&&r !G%@ +G + +S& +@E + +* + +$ @o +&I@ + + +, + +-xB + +G -@ -@ -BX J -BP -BH J - -(`ih@(C( -(( -HH -G@ -R - -x -@@ -@ -O - -MNC@ -@ xLM -O - - -@@
M@ -xMMM@
NNNNNNNQUNY -
-M@ -B -͂ -@Ixx
- -
O -
-
O -
M@
-OO -x -MC@
-
` -@ -x
P3@@$ -x -́ -
-@x - @
NMӀ
M3@M@
X
IM
tr M# - - -G@b - -IGB - - - - -@ - -!L@ -"L @ - -£ -J -@ -A - -@xo -r -@xJ JM` +-J +Fa + + + ++ + - - - -@" +g +J+J + + +Q +? +RP +@#\ a +L+L +@ +, + +@} +I@ ` + +@x +-J + + +-G% +! - -@ - -@ -@ -xV JM` +-J+ + +x +! +G + + + @a + +x + b@ʢ c +$"L2@ + + + +CALc +AA K)` +! + + +@ +a $a ' + N, +?G)á +,@ǠA+ ++?aǠA+PCG + + + +@ +G + +ߏN LJ +J2x +@Ȇ + +0 +` + + + C!?C` + + 1 +@ +M*@I +G + *,@ +@@ +M*@I + *,@ +@ +M*@I + +ql +@0 +G + ,@ +@@0 + ,@ +@0 +qp + +qp +` + +qIq + + +J +O+ +a
` +z + +."@ +o@l + +J + +O+ + +a
` +z + +."@ +o@l + +G@@ + + + + + +H +Hs + + +@r + +@ + +@ + +x + +@ +x +W~ +
@R#LJ @U~ + + + + +r +@D~G@Q +
I + +6~ +3~ M + +*#G@H
Q +xH@B H@ +Q +Q + + + +#@#G@Q +G@Q +@ + / +B + / + + +;p ; + +GС@ʡ + +G@!x + + +G +!I@ +R B@h + ?C +H:
B G) +@!D # +G +G +GB G +G +} +xQ + +;Gp ; + +GБ@ʡ + + ;R` G)"j ! (! )I + - -@ - - +@ + +Ϡ +Aaa + +@G1 +N + +I + - - - - -J JY" !L MJ" !\ @ - - -J +@ +G +Ϡ +Aaa +@ +@ + +I,J:9>>>G@ +@ +s@ +c@ +T@ + +G$@ +@&x + + + -c -@xK` -JAb -x -ˁ -` + + + +G @ + I + +CJ +G:G@c +q@1@ɑ + I + + + +.x G` +xG +x +x@9 + +r,s-nuua u +qs@! +xt +~ +@@ + +@@ + +} + + + a +I +0020ȁ + + + +zJa CG + + +H + +t + + + +B +s#sRP G)"j ! + +B @#BH #BP B @ + H + + +a +G@GA +I +I + + @ +#"@ + I + +@*x +@ +O + +" +x$ +O +, +" + +I - -J - - - - -pIrIB - - -I @x - ,IB -ɱ@ - - @ -II @ - -x ,IB -ɱ@ - - @ -II @ -,C - -C -A - -2@ - -@} - -@ - @ x -x hi! V hi! T -U@e)hiqiU -TqiU5@ - -o)Q `) - -e)hi% V - -ր` -xhi%@ - - U - -@!~ - -H -(G@ -, -<@ -P -XGA - - - - G@ - ! - $@ - < - HGA - x@@Gr1 - -G@ - Z - - -Gb@ -GB@ - -@x# -xI -x -$ -$Y@@ -$ -$)@S -d - -H -@ -p r -r - ÿ - - - -H - - - s -q u ILI -@I@HP U SI -I UIǁ O - -K<K4T - - - -!`ia@!C! - - - - - - I -A - - - ¥ -I - -A - -Di - - - - -G` - -x B I D` - -EG@ -ŀ -EŁx - -EG -ł -EŃ " K` -@" ` - -G` - - -EG -ń -EŅ " -EG -ņ -EŇ " -@x + + +G @@# + +G"@ # + +L + +A +pA + +B@ +p3@ + + + + +1@A @@N @@ + +@x + + + +
+ +P + + + + +x@ +C + + + + +@x + + + + + + + + + C!?C` + +q + + + +K +@x +PH NL +xqMЀ LF +PJ N, +
+@xM@
Ҁ +
+@ +0q\ +J@ +@K<@Oq + +q +L@ +A@ +A@ +c@ +0Aa ,@ + +`! + + +A@ +0 + +Db +D` + + + + p T p0X +02p0 +K@ + +1L3 + + + + +0 +p +q<i +q
@ +@ + + +@ + +pF<@Op +a@ + +Q + + 2@ + +A + + + + 2@ + +A + + +q +1@ + + + 0 +0 + + + + + + + @ + +i + + @` -@x + - +x ` -@7x + - + - - - + + + EFQ@ @@ -26235,7 +21316,7 @@ A@A` @`AA0@ - + CL @@ -26330,7 +21411,7 @@ H H x -) +) B @ @@ -26406,10 +21487,12 @@ H x I - + - -"@ #@ + +#E +"@ # + 1~ H @@ -26420,11 +21503,11 @@ IH H@I @ J - B #EBH + B #EBH #EBP B @ - #E"@ !@ + #E"@ !@ @ @@ -26441,7 +21524,7 @@ HѕH@H HѕH@H J - B #EBH #EBP B @ !@ + B @#EBH #EBP B @ !@ I@I` H@
I H @@ -26529,10 +21612,10 @@ K# @ `H II@ - + E - + @`J 2@ʢ @@ -26543,13 +21626,13 @@ I U Q @ -@`#@ +@`#@ @ E - + URAU@2@AP @@ -26559,8 +21642,8 @@ URAU@2@AP 2@ʤ 5 - -URAU@PPA# + +URAU@PPA@# @@ -26596,17 +21679,17 @@ x P @`3@
Ѐ @Q -@ - -L -L + + +L +L @ D @ * - + CL - + @NH2 @@ -26615,25 +21698,25 @@ $ H` -x +x - + H -@Hx -1xix - -I - +Ixyx + + + + +I + I ʀ @I Ȁ QIȃ Q & -"D c +"D c -B@ - -y Q IH H -dL +B@ Q IH H +䆁dN ȃ @@ -26721,7 +21804,7 @@ K' -I +I K!% %G @@ -26732,7 +21815,7 @@ K!% #K -H! +H! JI %b @ x @@ -26812,7 +21895,7 @@ V N J - + JG I @@ -26823,7 +21906,7 @@ V D -E +E IJ @I@ @@ -26834,21 +21917,21 @@ E -@@ +@@ ߏN LJ J2x @Ȇ 0 ` - + @` x ` - + @@ -27251,11 +22334,11 @@ L L @ D @ * - + CL - + @NH2 @@ -27264,25 +22347,25 @@ $ H` -x +x - + H -@Hx -1xix - -I - +Ixyx + + + + +I + I ʀ @I Ȁ QIȃ Q & -"D c +"D c -B@ - -y Q IH H -dL +B@ Q IH H +䆁dN ȃ @@ -27370,7 +22453,7 @@ K' -I +I K!% %G @@ -27381,7 +22464,7 @@ K!% #K -H! +H! JI %b @ x @@ -27461,7 +22544,7 @@ V N J - + JG I @@ -27472,7 +22555,7 @@ V D -E +E IJ @I@ @@ -27483,21 +22566,21 @@ E -@@ +@@ ߏN LJ J2x @Ȇ 0 ` - + @` x ` - + @@ -27900,11 +22983,11 @@ L L @ D @ * - + CL - + @NH2 @@ -27913,25 +22996,25 @@ $ H` -x +x - + H -Ixyx - - - - -I - +@Hx +1xix + +I + I ʀ @I Ȁ QIȃ Q & -"D c +"D c -B@ Q IH H -䆁dN +B@ + +y Q IH H +dL ȃ @@ -28019,7 +23102,7 @@ K' -I +I K!% %G @@ -28030,7 +23113,7 @@ K!% #K -H! +H! JI %b @ x @@ -28110,7 +23193,7 @@ V N J - + JG I @@ -28121,7 +23204,7 @@ V D -E +E IJ @I@ @@ -28132,21 +23215,21 @@ E -@@ +@@ ߏN LJ J2x @Ȇ 0 ` - + @` x ` - + @@ -28549,11 +23632,11 @@ L L @ D @ * - + CL - + @NH2 @@ -28562,25 +23645,25 @@ $ H` -x +x - + H -Ixyx - - - - -I - +@Hx +1xix + +I + I ʀ @I Ȁ QIȃ Q & -"D c +"D c -B@ Q IH H -䆁dN +B@ + +y Q IH H +dL ȃ @@ -28668,7 +23751,7 @@ K' -I +I K!% %G @@ -28679,7 +23762,7 @@ K!% #K -H! +H! JI %b @ x @@ -28759,7 +23842,7 @@ V N J - + JG I @@ -28770,7 +23853,7 @@ V D -E +E IJ @I@ @@ -28781,31 +23864,31 @@ E -@@ +@@ ߏN LJ J2x @Ȇ 0 ` - - + +@x @` - +@x -x + ` - +@7x - + - - - + + + EFQ@ @@ -28829,7 +23912,7 @@ A@A` @`AA0@ - + CL @@ -28924,7 +24007,7 @@ H H x -) +) B @ @@ -29000,12 +24083,10 @@ H x I - + - -#E -"@ # - + +"@ #@ 1~ H @@ -29016,11 +24097,11 @@ IH H@I @ J - B #EBH #EBP B @ + B #EBH - #E"@ !@ + #E"@ !@ @ @@ -29037,7 +24118,7 @@ HѕH@H HѕH@H J - B @#EBH #EBP B @ !@ + B #EBH #EBP B @ !@ I@I` H@
I H @@ -29125,10 +24206,10 @@ K# @ `H II@ - + E - + @`J 2@ʢ @@ -29139,13 +24220,13 @@ I U Q @ -@`#@ +@`#@ @ E - + URAU@2@AP @@ -29155,8 +24236,8 @@ URAU@2@AP 2@ʤ 5 - -URAU@PPA@# + +URAU@PPA# @@ -29192,10 +24273,10 @@ x P @`3@
Ѐ @Q - - -L -L +@ + +L +L @ D @ * @@ -29328,7 +24409,7 @@ K!% #K -H! +H! JI %b @ x @@ -29437,1217 +24518,6601 @@ J2x 0 ` - - - - - - -G -% - -@:La - - - - -@y -o -c -HCc -I -x -*L6Lǁ Q ;LH2 -H -L ` - -@@I - -x - - -@x - -2 - -(GGCG - -<L - - -B - - -BD HAd - -` + + +x +@x + + + + - + + + + + + + +` +@ +xI +Ib + + + + +H +H@ + +@Jo + + + +@x + A + +x +@x + + + + +H.. +!H..xH&Hb +'h&@]x + +I# + +#F #-FH - + + + + ` - -X ȃ -, - -q@BD HH@d - -x - - -@ -HA - - - -ȃ X - -x!GG -G$Lx0!$L@$N -@ -" -N"HD 2P @x!xA! - -`@ + + + + +E E "` I "d -- ` - BX I- Bx -. +/I/` '( + + + + + + /-" +@x@H +@ + + +I/H +@@@ + + @K +H01DH +HR n + +/@a +I# +@ + + + +~ + + + +@a + @ +> ~ @M@
@LÀ +J +> ~ @M@
@LÀL + + + + +"Ab +!H! +Z +_ I# + +@
x + + +@ +@ + + + + +r + + +.H2 + + +x +x.I +! + +! +J J +@xBX H` +xBP ` + +! +JH H@ +JH +JH JH +A1 + + + xI +@ +ɀ +A + ` +x +"J@ + xI +@ +ɀ +A + ` +x +!"J@ +@@ +@H3
@ +@@ +@"@I +@ +K +K + + + + + +K +3@ + + + + + +3@ + + + +@ "x +I@J@ +B` H I "| +I@J@ +Bh H %G @ B D
"H G "@ I "H "P D @ I B D "@ I "D +HH0HII@HHIHII + +H H +#I H +# H +#ɐ H +$ H +H+I H ++ H +(ɑ H +H( H +H,I H + +R0 + + + +2@@I + + + + +@ + 0 + + 0I 0 +J@ɑ A H@M +@ + +I/2@-@ +@ +n + F> +m + + +/^a Ѐ +J; +bI@@ +%A#$AdIA +# +@#A + +$ @M + + +@3x +$@# +$ +$9#I + + + + + + +W + + + + +$$f +$"x + +%>` + x%` +@)x%> ! d& +d +% +@x +$$$$$ + + +$A$> $ +#Dc/ + +c +d! + +Q f9@ +@xe<&a +d)e +xIa +de +@ x$@@$) a +#: @c@ +c% +fH + + +#$ +d@ +# +f!x& +c +@ +e + + +%` + + +i2 $$$$$ +d + + +f!$e +$< +d&I@ +i2 +d + + +f $$<@ + + + +hr +# + +C@ + +`B +@ +`B + + +( +! '* + +(@o + + + + + + +x
GK` + + + +@A +C +C @ +C O +C C - ` - - -Hzo - -N - - + + +J +@ +ʀ -GI -O -I@ -I + +xNCh @xNC@ xNCH @xNCP +K@ + x
@ x
x
@2I + +K@ + +` +JB@Jb@H + +@xNb@ +N@#I + + +\ + +A> + +@b + + +xM@Q +S$S$AL +S + +@@AH> + + + + + +I@ P +IIbIIIb@ +IIRIIIR +I -o -I@ -I - Rp - - - I`O - - - - - -LJ - - -` -6xG` -G -G - - - -^ -G IGa @ -a -G - - - -` -x - -@ -@ -P @ -x -9 - IG -@ -@ -P @ -x - - -GG -B - - - -H`W -x - -HH - - + +@|s@ +JAHR0 AH! IAH! AHB8 AH0 @ -*L6L @˂@ -@KK -I - - - -Br@@xr@ - - Gr -Gr - - -G` - - -G -b - - -o -I -H - - - - -G@H -?I ȑ -I a -I I - - - - - - - - - - - -J - -xGGP !@$N -@ -" -N"HD 2P @x!xA! -GG -G -G` - -@ - -@ -H!" - - -I -xF!x -@ - -N - r - - ! RGIba IGa -a +A@ +J> +AAAAJ< +A"@@@AH> ` - -"B @x@@ o - -@ -ۆ[@GLa~ ǀ - - - - -( -! (@( hQ -( -* -kè -냨 -+B - -* -* - - -! ( 銂( ( -@$("Lh -! ( 銂( hЈ0D x( D *k -Q -* -* -k -p -* - -! h (( m-^ ( ( -@$("L( ( -! h (( -^ ( (X0D ( (0D ( ( -$/"L/ / -! h (( -^ ( ( -P$("L( ( -! h (( --^ ( h؎0D ( $$("L./( - - - -! ( 銂( @$("Lh -! ( 銂( hи0D @x( * -Q x+kA -k -p -0D ( ) ( -! h (( -^ ( @$("L( ( -! h (( ( (X0D ( (0D ( ( -! h (( m-^ ( P$("L( ( -! h (( 胂 ( hؾ0D ( $$("L./(( -@#xIU - -@ x -@@x U@U5 -`a@ - -U@ - -@V - - -E NNN$"N - -xAd -V U - -E - -G -G -c - -NNN - - -@ -! -G - -ߏN Lȃ JB - + + + + +AH> +@I +H +bs@} +} + +[s@ +Jc +s@AHR0 AH! IAH! AAH0 @ + +A@ +J> +AAAAJ< +A"@@@I + +Q s@@I@ a #AH> + + + + + +I + +AH> +^ + + + + + +@ +AH0 H. @AH> H< H: + +@s@} + +AH! AH! AH> +H< AH> @ +H$ IH AH6 @ + +@x +A ` + +A ` +xAH! AH! AH! AH! IAH> + +J ` - -, - *C(I( -,J@($,*F ( ) ("L(h! ( 튂( ( -,J@ ($("Lh! ( 튂( , -("Lh! ( 튂( - - - - - -G -% - -@:La - - - - -y -o -c -HCc -I -x -*L6Lǁ Q ;LH2 -H -L ` - -@@I - -x - - -@x - -2 - -(GGCG - -<L - - -B - - -BD HAd - -` +x +A> @ +AH0 AHR6 H4 HR* AHB8 HB0 +AHB8 AHR6 HR, HR" +\} + +@ +b + + + +s@JHB +J +s@AH> IH< H26 H4 H2 IS + + + +xFHE!AH> I @ + - + + + +# $I$@x$AH> #H< a + $9I$@9$AH> b + + + + + +*} + + ? +Hr + + + + +s@ +s@ + s@JHB +J +s@% +&@xI&H@ + +J@ɑ H&& +Nx +ȁ &@ +I + a + +J@ɑ H'AH> @a +
@ +@x +@ + +x +H!I A! !A@x A IB +J@ɑ AH> AH> +@I + +( + +AAH> b +bT (` + + + +/I + +Al + )I @ + +@a +I + +((I + + I{DH2@ + + + + + ++ + + $+I$+$x ,AH> a +++ + +H(@a ++ +@x +H#` +@x,,@ +I + +@ AH +@H% +@I + +BH/ + + + +:I& ` +& + + +C + +x +x + + + + + + + + + + + + +` +@ +xI +Ib + + + + +H +H@ + +@Jo + + + +@x + A + +x +N +@x + +Nx + + +H.. +!H..xH&Hb +'h&bx + +I# + +@c +@ + + + ` - -X ȃ -, - -q@BD HH@d - -x - - -@ -HA - - - -ȃ X - -x!GG -G$Lx0!$L@$N -@ -" -N"HD 2P @x!xA! - -`@ + +I I L F +ɗ ɗ a -- a .. a + +ER + + +E "` I "d -- ` ~ ..` +ȇ +/I/` '( + + + + + + /-" +@x@H +@ + + +I/H +@@@ + + @K +H01DH +HR n + +/@a +I# +@ + + + + + + + +@a + @ +> ~ @M@
@LÀ +J +> ~ @M@
@LÀL + + + + + b +H + + + +@9 +"Ab +!H! +Z +_ I# + +@
x + + +@ +@ + + + + +@u + + +.H2 + + +x +x.I +! + +! +J J +@xBX H` +xBP ` + +! +JH H@ +JH +JH JH +A1 + + + xI +@ +ɀ +A + ` +x +"J@ + xI +@ +ɀ +A + ` +x +!"J@ +@@ +@H3
@ +@@ +@"@I +@ +K +K + + + + +K +3@ + + + + + +3@ + + + +@ "x +I@J@ +B` H I "| +I@J@ +Bh H %G @ B D
"H G "@ I "H "P D @ I B D "@ I "D +HH0HII@HHIHII + +H H +#I H +# H +#ɐ H +$ H +H+I H ++ H +(ɑ H +H( H +H,I H + +R0 + + + +2@@I + + + + +@ + 0 + + 0I 0 +J@ɑ A H@M +@ + + +/^a Ѐ +$@ +Y@hB&i + + +J; +bI@ +%A#$AdIA +# +@#A + +$ + + + +$@# +$ +$9#I + + + + + + + +W + + + + +$$f +$"x + +%>` + x%` +@)x%> ! d& +d +% +@x +$$$$$ + + +$A$> $ +#Dc/ + +c +d! + +Q f9@ +@xe<&a +d)e +xIa +de +@ x$@@$) a +#: @c@ +c% +fH + + +#$ +d@ +# +f!x& +c +@ +e + + +%` + + +i2 $$$$$ +d + + +f!$e +$< +d&I@ +i2 +d + + +f $$<@ + + + +hr +# + +C@ + +`B +@ +`B + + +( +! '* + +(@o + + + + + + +x
GK` + + + +@A +C +C @ +C O +C C - ` - - -Hzo - -N - - + + +J +@ +ʀ -GI -O -I@ -I + +xNCh @xNC@ xNCH @xNCP +K@ + x
@ x
x
/I + +K@ + +` +JB@Jb@H + +@xNb@ +N@ + + +\ + +A> + +@b + + +xM@Q +S$S$AL +S + + +@@AH> + + + + + +I@ P +IIbIIIb@ +IIRIIIR +I -o -I@ -I - Rp - - - I`O - - - - - -LJ - - -` -6xG` -G -G - - - -^ -G IGa @ -a -G - - - -` -x - -@ -@ -P @ -x -9 - IG -@ -@ -P @ -x - - -GG -B - - - -H`W@Ux -x - -HH - - + +ys@ +JAHR0 AH! IAH! AHB8 AH0 @ -*L6L @˂@ -@KK -I - - - -Br@@xr@ - - Gr -Gr - - -G` - - -G -b - - -o -I -H - - - -G@H -?I ȑ -I a -I I - - - - - - - - - - - -J - -xGGP !@$N -@ -" -N"HD 2P @x!xA! -GG -G -G` - -@ - -@ -H!" - - -I -xF!x -@ - -N - r - - ! RGIba IGa -a +A@ +J> +AAAAJ< +A"@@@AH> ` - -"B @x@@ o - -@ -ۆ[@GLa~ ǀ - - - - -( -! (@( hQ -( -* -kè -냨 -+B - -* -* - - -! ( 銂( ( -@$("Lh -! ( 銂( hЈ0D x( D *k -Q -* -* -k -p -* - -! h (( m-^ ( ( -@$("L( ( -! h (( -^ ( (X0D ( (0D ( ( -$/"L/ / -! h (( -^ ( ( -P$("L( ( -! h (( --^ ( h؎0D ( $$("L./( - - - -! ( 銂( @$("Lh -! ( 銂( hи0D @x( * -Q x+kA -k -p -0D ( ) ( -! h (( -^ ( @$("L( ( -! h (( ( (X0D ( (0D ( ( -! h (( m-^ ( P$("L( ( -! h (( 胂 ( hؾ0D ( $$("L./(( -@#xIU - -@ x -@@x U@U5 -`a@ - -U@ - -@V - - -E NNN$"N - -xAd -V U - -E - -G -G -c - -NNN - - -@ -! -G - -ߏN Lȃ JB - + + + + +AH> +I +H +@`s@@} + + + +J +s@AHR0 AH! IAH! AAH0 @ + +A@ +J> +AAAAJ< +A"@@@@I + + + FI> o + + + + + + +I + +AH> +@] + + + + + +@ +AH0 H. @AH> H< H: + +@s@} + +AH! AH! AH> +H< AH> @ +H$ IH AH6 @ + +@t +A ` + +A ` +xAH! AH! AH! AH! IAH> + +J ` - -, - *C(I( -,J@($,*F ( ) ("L(h! ( 튂( ( -,J@ ($("Lh! ( 튂( , -("Lh! ( 튂( - - - - - -G -% - -@:La - - - - -y -o -c -HCc -I -x -*L6Lǁ Q ;LH2 -H -L ` - -@@I - -x - - -@x - -2 - -(GGCG - -<L - - -B - - -BD HAd - -` +x +A> @ +AH0 AHR6 H4 HR* AHB8 HB0 +AHB8 AHR6 HR, HR" +X} + +@ s@@V +b + + + +s@JHB +J +s@AH> IH< H26 H4 H2 IO + + + +x +@ - + + + +# $I$@x$AH> #H< a + $ + + + +@s@(} + +%} + + ? +Hr + + + + +s@! +s@ + s@JHB +J +s@% +&@xI&H@ + +J@ɑ H&& +Lx +ȁ +I + a + +J@ɑ H'AH> @a +
@@ +@x +@ + +x +H!I A! !A@x A IB +J@ɑ AH> AH> +I + +( + +AAH> b +bT (` + +@((I + +/I + +Al + )I @ + +@a +I + +((I + + I { + +@* + AH* ++ + + $+I$+$x ,AH> a +++@ ,#@ + +H(@a ++ +@x +H#` +@x + + +@ AH +@H% +I + +F> o + + + + +:I& ` +& + + +@ + +@ +x +x + + + + + + + + + + + + +` +@ +xI +Ib + + + + +H +H@ + +@Jo + + + +@x + A +@ +x +@x + +@Jx + + +H.. +!H..xH&Hb +'@h&Vx + +I# + + + + ` - -X ȃ -, - -q@BD HH@d - -x - - -@ -HA - - - -ȃ X - -x!GG -G$Lx0!$L@$N -@ -" -N"HD 2P @x!xA! - -`@ + +I I L F +ɗ ɗ a -- a .. a + +ER + + +E "` I "d -- ` ~ ..` +ȇ +/I/` '( + + + + + + /-" +@x@H +@ + + +I/H +@@@ + + @K +H01DH +HR n + +/@a +I# +@ + + + +~ + + + +@a + @ +> ~ @M@
@LÀ +J +> ~ @M@
@LÀL + + + + +"Ab +!H! +Z +_ I# + +@
x + + +@ +@ + + + + +@h + + +.H2 + + +x +x.I +! + +! +J J +@xBX H` +xBP ` + +! +JH H@ +JH +JH JH +A1 + + + xI +@ +ɀ +A + ` +x +"J@ + xI +@ +ɀ +A + ` +x +!"J@ +@@ +@H3
@ +@@ +@"@I +@ +K +K + + + + +K +3@ + + + + + +3@ + + + +@ "x +I@J@ +B` H I "| +I@J@ +Bh H %G @ B D
"H G "@ I "H "P D @ I B D "@ I "D +HH0HII@HHIHII + +H H +#I H +# H +#ɐ H +$ H +H+I H ++ H +(ɑ H +H( H +H,I H + +R0 + + + +2@@I + + + + +@ + 0 + + 0I 0 +J@ɑ A H@M +@ + + +/^a Ѐ +$@ +Y@hB&i + +%A#$AdIA +# +@#A + +$ + + + +$@# +$ +$9#I + + + + + + + +W + + + + +$$f +$"x + +%>` + x%` +@)x%> ! d& +d +% +@x +$$$$$ + + +$A$> $ +#Dc/ + +c +d! + +Q f9@ +@xe<&a +d)e +xIa +de +@ x$@@$) a +#: @c@ +c% +fH + + +#$ +d@ +# +f!x& +c +@ +e + + +%` + + +i2 $$$$$ +d + + +f!$e +$< +d&I@ +i2 +d + + +f $$<@ + + + +hr +# + +C@ + +`B +@ +`B + + +( +! '* + +(@o + + + + + + +x
GK` + + + +@A +C +C @ +C O +C C - ` - - -Hzo - -N - - + + +J +@ +ʀ -GI -O -I@ -I + +xNCh @xNC@ xNCH @xNCP +K@ + x
@ x
x
<I + +K@ + +` +JB@Jb@H + +@xNb@ +N@ + + +\ + +A> + +@b + + +xM@Q +S$S$AL +S + +@@AH> + + + + + +I@ P +IIbIIIb@ +IIRIIIR +I -o -I@ -I - Rp - - - I`O - - - - - -LJ - - -` -6xG` -G -G - - - -^ -G IGa @ -a -G - - - -` -x - -@ -@ -P @ -x -9 - IG -@ -@ -P @ -x - - -GG -B - - - -H`W@Ux -x - -HH - - + +s@ +JAHR0 AH! IAH! AHB8 AH0 @ -*L6L @˂@ -@KK -I - - - -Br@@xr@ - - Gr -Gr - - -G` - - -G -b - - -o -I -H - - - -G@H -?I ȑ -I a -I I - - - - - - - - - - - -J - -xGGP !@$N -@ -" -N"HD 2P @x!xA! -GG -G -G` - -@ - -@ -H!" - - -I -xF!x -@ - -N - r - - ! RGIba IGa -a +A@ +J> +AAAAJ< +A"@@@AH> ` - -"B @x@@ o - -@ -ۆ[@GLa~ ǀ - - - - -( -! (@( hQ -( -* -kè -냨 -+B - -* -* - - -! ( 銂( ( -@$("Lh -! ( 銂( hЈ0D x( D *k -Q -* -* -k -p -* - -! h (( m-^ ( ( -@$("L( ( -! h (( -^ ( (X0D ( (0D ( ( -$/"L/ / -! h (( -^ ( ( -P$("L( ( -! h (( --^ ( h؎0D ( $$("L./( - - - -! ( 銂( @$("Lh -! ( 銂( hи0D @x( * -Q x+kA -k -p -0D ( ) ( -! h (( -^ ( @$("L( ( -! h (( ( (X0D ( (0D ( ( -! h (( m-^ ( P$("L( ( -! h (( 胂 ( hؾ0D ( $$("L./(( -@#xIU - -@ x -@@x U@U5 -`a@ - -U@ - -@V - - -E NNN$"N - -xAd -V U - -E - -G -G -c - -NNN - - -@ -! -G - -ߏN Lȃ JB - + + + + +AH> +I +H +@ms@@} + + + +J +s@AHR0 AH! IAH! AAH0 @ + +A@ +J> +AAAAJ< +A"@@@@I + + + FI> o + + + + + + +I + +AH> +@] + + + + + +@ +AH0 H. @AH> H< H: + +@%s@} + +AH! AH! AH> +H< AH> @ +H$ IH AH6 @ + +@ +A ` + +A ` +xAH! AH! AH! AH! IAH> + +J ` - -, - *C(I( -,J@($,*F ( ) ("L(h! ( 튂( ( -,J@ ($("Lh! ( 튂( , -("Lh! ( 튂( - - - - - -G -% - -@:La - - - - -@y -o -c -HCc -I -x -*L6Lǁ Q ;LH2 -H -L ` - -@@I - -x - - -@x - -2 - -(GGCG - -<L - - -B - - -BD HAd - -` +x +A> @ +AH0 AHR6 H4 HR* AHB8 HB0 +AHB8 AHR6 HR, HR" +e} + +@ s@@c +b + + + +s@JHB +J +s@AH> IH< H26 H4 H2 I\ + + + +x +@ - + + + +# $I$@x$AH> #H< a + $ + + + +@s@5} + +2} + + ? +Hr + + + + +s@! +s@ + s@JHB +J +s@% +&@xI&H@ + +J@ɑ H&& +Lx +ȁ +I + a + +J@ɑ H'AH> @a +
@@ +@x +@ + +x +H!I A! !A@x A IB +J@ɑ AH> AH> +I + +( + +AAH> b +bT (` + +@((I + +/I + +Al + )I @ + +@a +I + +((I + + I { + +@* + AH* ++ + + $+I$+$x ,AH> a +++@ ,#@ + +H(@a ++ +@x +H#` +@x + + +@ AH +@H% +I + +F> o + + + + +:I& ` +& + + +@ + +x +x + + + + + + + + + + + + +` +@ +xI +Ib + + + + +H +H@ + +@Jo + + + + +@x + A + +x +@x + +@Kx + + +H.. +!H..xH&Hb +'h&Wx + +I# + + + + + ` - -X ȃ -, - -q@BD HH@d - -x - - -@ -HA - - - -ȃ X - -x!GG -G$Lx0!$L@$N -@ -" -N"HD 2P @x!xA! - -`@ + + + + +E E "` I "d -- ` - BX I- Bx -. +/I/` '( + + + + + + /-" +@x@H +@ + + +I/H +@@@ + + @K +H01DH +HR n + +/@a +I# +@ + + + +~ + + + +@a + @ +> ~ @M@
@LÀ +J +> ~ @M@
@LÀL + + + + +"Ab +!H! +Z +_ I# + +@
x + + +@ +@ + + + + +e + + +.H2 + + +x +x.I +! + +! +J J +@xBX H` +xBP ` + +! +JH H@ +JH +JH JH +A1 + + + xI +@ +ɀ +A + ` +x +"J@ + xI +@ +ɀ +A + ` +x +!"J@ +@@ +@H3
@ +@@ +@"@I +@ +K +K + + + + +K +3@ + + + + + +3@ + + + +@ "x +I@J@ +B` H I "| +I@J@ +Bh H %G @ B D
"H G "@ I "H "P D @ I B D "@ I "D +HH0HII@HHIHII + +H H +#I H +# H +#ɐ H +$ H +H+I H ++ H +(ɑ H +H( H +H,I H + +R0 + + + +2@@I + + + + +@ + 0 + + 0I 0 +J@ɑ A H@M +@ + +I/2@-@ + + + F> +@n + + +/^a Ѐ +%A#$AdIA +# +@#A + +$ @M + + +@3x +$@# +$ +$9#I + + + + + + +W + + + + +$$f +$"x + +%>` + x%` +@)x%> ! d& +d +% +@x +$$$$$ + + +$A$> $ +#Dc/ + +c +d! + +Q f9@ +@xe<&a +d)e +xIa +de +@ x$@@$) a +#: @c@ +c% +fH + + +#$ +d@ +# +f!x& +c +@ +e + + +%` + + +i2 $$$$$ +d + + +f!$e +$< +d&I@ +i2 +d + + +f $$<@ + + + +hr +# + +C@ + +`B +@ +`B + + +( +! '* + +(@o + + + + + + +x
GK` + + + +@A +C +C @ +C O +C C - ` - - -Hzo - -N - - + + +J +@ +ʀ -GI -O -I@ -I + +xNCh @xNC@ xNCH @xNCP +K@ + x
@ x
x
?I + +K@ + +` +JB@Jb@H + +@xNb@ +N@0I + + +\ + +A> + +@b + + +xM@Q +S$S$AL +S + +@@AH> + + + + + +I@ P +IIbIIIb@ +IIRIIIR +I + + +s@ +JAHR0 AH! IAH! AHB8 AH0 @ + +A@ +J> +AAAAJ< +A"@@@AH> ` + + + + + +AH> +I +H + +} + +hs@ +Jp +s@AHR0 AH! IAH! AAH0 @ + +A@ +J> +AAAAJ< +A"@@@ + +^ s@I + @I@ @I AH> ` + + + + +I + +AH> +^ + + + + + + +AH0 H. @AH> H< H: + +)s@} + +AH! AH! AH> +H< AH> @ +H$ IH AH6 @ + + +A ` + +A ` +xAH! AH! AH! AH! IAH> +@xI +J +` +x +A> @ +AH0 AHR6 H4 HR* AHB8 HB0 +AHB8 AHR6 HR, HR" + + +
s@g +b + + + +s@JHB +J +s@AH> IH< H26 H4 H2 I` + + + +x +@ + + + + +# $I$@x$AH> #H< a + $ + + + +@s@:} + +7} + + ? +Hr + + + + +s@ +s@ + s@JHB +J +s@% +&@xI&H@ + +J@ɑ H&& +Nx +ȁ +I + a + +J@ɑ H'AH> @a +
@ +@x +@ + +x +H!I A! !A@x A IB +J@ɑ AH> AH> +I + +( + +AAH> b +bT (` + +@((I + +/I + +Al + )I @ + +@a +I + +((I + + I{DH2@ + + + + +@* + AH* ++ + + $+I$+$x ,AH> a +++@ ,#@ + +H(@a ++ +@x +H#` +@x + + +@ AH +@H% +I + +BH/ + + + +:I& ` +& + + +C + +x +@x + + + + + + + + + + + + +` +@ +xI +Ib + + + + +H +H@ + +@Jo + + + +@x + A + +x +@x + + + + +H.. +!H..xH&Hb +'h&@]x + +I# + +#F #-FH - + + + + +` + + + + +E E "` I "d -- ` - bT I- bt -. +/I/` '( + + + + + + /-" +@x@H +@ + + +I/H +@@@ + + @K +H01DH +HR n + +/@a +I# +@ + + + +~ + + + +@a + @ +> ~ @M@
@LÀ +J +> ~ @M@
@LÀL + + + + +"Ab +!H! +Z +_ I# + +@
x + + +@ +@ + + + + +r + + +.H2 + + +x +x.I +! + +! +J J +@xBX H` +xBP ` + +! +JH H@ +JH +JH JH +A1 + + + xI +@ +ɀ +A + ` +x +"J@ + xI +@ +ɀ +A + ` +x +!"J@ +@@ +@H3
@ +@@ +@"@I +@ +K +K + + + + + +K +3@ + + + + + +3@ + + + +@ "x +I@J@ +B` H I "| +I@J@ +Bh H %G @ B D
"H G "@ I "H "P D @ I B D "@ I "D +HH0HII@HHIHII + +H H +#I H +# H +#ɐ H +$ H +H+I H ++ H +(ɑ H +H( H +H,I H + +R0 + + + +2@@I + + + + +@ + 0 + + 0I 0 +J@ɑ A H@M +@ + +I/2@-@ +@ +n + F> +m + + +/^a Ѐ +J; +bI@@ +%A#$AdIA +# +@#A + +$ @M + + +@3x +$@# +$ +$9#I + + + + + + +W + + + + +$$f +$"x + +%>` + x%` +@)x%> ! d& +d +% +@x +$$$$$ + + +$A$> $ +#Dc/ + +c +d! + +Q f9@ +@xe<&a +d)e +xIa +de +@ x$@@$) a +#: @c@ +c% +fH + + +#$ +d@ +# +f!x& +c +@ +e + + +%` + + +i2 $$$$$ +d + + +f!$e +$< +d&I@ +i2 +d + + +f $$<@ + + + +hr +# + +C@ + +`B +@ +`B + + +( +! '* + +(@o + + + + + + +x
GK` + + + +@A +C +C @ +C O +C C + +` + + +J +@ +ʀ + + +xNCh @xNC@ xNCH @xNCP +K@ + x
@ x
x
@2I + +K@ + +` +JB@Jb@H + +@xNb@ +N@#I + + +\ + +A> + +@b + + +xM@Q +S$S$AL +S + +@@AH> + + + + + +I@ P +IIbIIIb@ +IIRIIIR +I + + +@|s@ +JAHR0 AH! IAH! AHB8 AH0 @ + +A@ +J> +AAAAJ< +A"@@@AH> ` + + + + + +AH> +@I +H +bs@} +} + +[s@ +Jc +s@AHR0 AH! IAH! AAH0 @ + +A@ +J> +AAAAJ< +A"@@@I + +Q s@@I@ a #AH> + + + + + +I + +AH> +^ + + + + + +@ +AH0 H. @AH> H< H: + +@s@} + +AH! AH! AH> +H< AH> @ +H$ IH AH6 @ + +@x +A ` + +A ` +xAH! AH! AH! AH! IAH> + +J +` +x +A> @ +AH0 AHR6 H4 HR* AHB8 HB0 +AHB8 AHR6 HR, HR" +\} + +@ +b + + + +s@JHB +J +s@AH> IH< H26 H4 H2 IS + + + +xFHE!AH> I @ + + + + + +# $I$@x$AH> #H< a + $9I$@9$AH> b + + + + + +*} + + ? +Hr + + + + +s@ +s@ + s@JHB +J +s@% +&@xI&H@ + +J@ɑ H&& +Nx +ȁ &@ +I + a + +J@ɑ H'AH> @a +
@ +@x +@ + +x +H!I A! !A@x A IB +J@ɑ AH> AH> +@I + +( + +AAH> b +bT (` + + + +/I + +Al + )I @ + +@a +I + +((I + + I{DH2@ + + + + + ++ + + $+I$+$x ,AH> a +++ + +H(@a ++ +@x +H#` +@x,,@ +I + +@ AH +@H% +@I + +BH/ + + + +:I& ` +& + + +C + +x +@x + + + + + + + + + + + + +` +@ +xI +Ib + + + + +H +H@ + +@Jo + + + +@x + A + +x +@x + + + + +H.. +!H..xH&Hb +'h&@]x + +I# + +#F #-FH - + + + + +` + + + + +E E "` I "d -- ` - BX I- Bx -. +/I/` '( + + + + + + /-" +@x@H +@ + + +I/H +@@@ + + @K +H01DH +HR n + +/@a +I# +@ + + + +~ + + + +@a + @ +> ~ @M@
@LÀ +J +> ~ @M@
@LÀL + + + + +"Ab +!H! +Z +_ I# + +@
x + + +@ +@ + + + + +r + + +.H2 + + +x +x.I +! + +! +J J +@xBX H` +xBP ` + +! +JH H@ +JH +JH JH +A1 + + + xI +@ +ɀ +A + ` +x +"J@ + xI +@ +ɀ +A + ` +x +!"J@ +@@ +@H3
@ +@@ +@"@I +@ +K +K + + + + + +K +3@ + + + + + +3@ + + + +@ "x +I@J@ +B` H I "| +I@J@ +Bh H %G @ B D
"H G "@ I "H "P D @ I B D "@ I "D +HH0HII@HHIHII + +H H +#I H +# H +#ɐ H +$ H +H+I H ++ H +(ɑ H +H( H +H,I H + +R0 + + + +2@@I + + + + +@ + 0 + + 0I 0 +J@ɑ A H@M +@ + +I/2@-@ +@ +n + F> +m + + +/^a Ѐ +J; +bI@@ +%A#$AdIA +# +@#A + +$ @M + + +@3x +$@# +$ +$9#I + + + + + + +W + + + + +$$f +$"x + +%>` + x%` +@)x%> ! d& +d +% +@x +$$$$$ + + +$A$> $ +#Dc/ + +c +d! + +Q f9@ +@xe<&a +d)e +xIa +de +@ x$@@$) a +#: @c@ +c% +fH + + +#$ +d@ +# +f!x& +c +@ +e + + +%` + + +i2 $$$$$ +d + + +f!$e +$< +d&I@ +i2 +d + + +f $$<@ + + + +hr +# + +C@ + +`B +@ +`B + + +( +! '* + +(@o + + + + + + +x
GK` + + + +@A +C +C @ +C O +C C + +` + + +J +@ +ʀ + + +xNCh @xNC@ xNCH @xNCP +K@ + x
@ x
x
@2I + +K@ + +` +JB@Jb@H + +@xNb@ +N@#I + + +\ + +A> + +@b + + +xM@Q +S$S$AL +S + +@@AH> + + + + + +I@ P +IIbIIIb@ +IIRIIIR +I + + +@|s@ +JAHR0 AH! IAH! AHB8 AH0 @ + +A@ +J> +AAAAJ< +A"@@@AH> ` + + + + + +AH> +@I +H +bs@} +} + +[s@ +Jc +s@AHR0 AH! IAH! AAH0 @ + +A@ +J> +AAAAJ< +A"@@@I + +Q s@@I@ a #AH> + + + + + +I + +AH> +^ + + + + + +@ +AH0 H. @AH> H< H: + +@s@} + +AH! AH! AH> +H< AH> @ +H$ IH AH6 @ + +@x +A ` + +A ` +xAH! AH! AH! AH! IAH> + +J +` +x +A> @ +AH0 AHR6 H4 HR* AHB8 HB0 +AHB8 AHR6 HR, HR" +\} + +@ +b + + + +s@JHB +J +s@AH> IH< H26 H4 H2 IS + + + +xFHE!AH> I @ + + + + + +# $I$@x$AH> #H< a + $9I$@9$AH> b + + + + + +*} + + ? +Hr + + + + +s@ +s@ + s@JHB +J +s@% +&@xI&H@ + +J@ɑ H&& +Nx +ȁ &@ +I + a + +J@ɑ H'AH> @a +
@ +@x +@ + +x +H!I A! !A@x A IB +J@ɑ AH> AH> +@I + +( + +AAH> b +bT (` + + + +/I + +Al + )I @ + +@a +I + +((I + + I{DH2@ + + + + + ++ + + $+I$+$x ,AH> a +++ + +H(@a ++ +@x +H#` +@x,,@ +I + +@ AH +@H% +@I + +BH/ + + + +:I& ` +& + + +C + +x +@x + + + + + + + + + + + + +` +@ +xI +Ib + + + + +H +H@ + +@Jo + + + +@x + A + +x +@x + + + + +H.. +!H..xH&Hb +'h&@]x + +I# + +#F #-FH - + + + + +` + + + + +E E "` I "d -- ` - BX I- Bx -. +/I/` '( + + + + + + /-" +@x@H +@ + + +I/H +@@@ + + @K +H01DH +HR n + +/@a +I# +@ + + + +~ + + + +@a + @ +> ~ @M@
@LÀ +J +> ~ @M@
@LÀL + + + + +"Ab +!H! +Z +_ I# + +@
x + + +@ +@ + + + + +r + + +.H2 + + +x +x.I +! + +! +J J +@xBX H` +xBP ` + +! +JH H@ +JH +JH JH +A1 + + + xI +@ +ɀ +A + ` +x +"J@ + xI +@ +ɀ +A + ` +x +!"J@ +@@ +@H3
@ +@@ +@"@I +@ +K +K + + + + + +K +3@ + + + + + +3@ + + + +@ "x +I@J@ +B` H I "| +I@J@ +Bh H %G @ B D
"H G "@ I "H "P D @ I B D "@ I "D +HH0HII@HHIHII + +H H +#I H +# H +#ɐ H +$ H +H+I H ++ H +(ɑ H +H( H +H,I H + +R0 + + + +2@@I + + + + +@ + 0 + + 0I 0 +J@ɑ A H@M +@ + +I/2@-@ +@ +n + F> +m + + +/^a Ѐ +J; +bI@@ +%A#$AdIA +# +@#A + +$ @M + + +@3x +$@# +$ +$9#I + + + + + + +W + + + + +$$f +$"x + +%>` + x%` +@)x%> ! d& +d +% +@x +$$$$$ + + +$A$> $ +#Dc/ + +c +d! + +Q f9@ +@xe<&a +d)e +xIa +de +@ x$@@$) a +#: @c@ +c% +fH + + +#$ +d@ +# +f!x& +c +@ +e + + +%` + + +i2 $$$$$ +d + + +f!$e +$< +d&I@ +i2 +d + + +f $$<@ + + + +hr +# + +C@ + +`B +@ +`B + + +( +! '* + +(@o + + + + + + +x
GK` + + + +@A +C +C @ +C O +C C + +` + + +J +@ +ʀ + + +xNCh @xNC@ xNCH @xNCP +K@ + x
@ x
x
@2I + +K@ + +` +JB@Jb@H + +@xNb@ +N@#I + + +\ + +A> + +@b + + +xM@Q +S$S$AL +S + +@@AH> + + + + + +I@ P +IIbIIIb@ +IIRIIIR +I + + +@|s@ +JAHR0 AH! IAH! AHB8 AH0 @ + +A@ +J> +AAAAJ< +A"@@@AH> ` + + + + + +AH> +@I +H +bs@} +} + +[s@ +Jc +s@AHR0 AH! IAH! AAH0 @ + +A@ +J> +AAAAJ< +A"@@@I + +Q s@@I@ a #AH> + + + + + +I + +AH> +^ + + + + + +@ +AH0 H. @AH> H< H: + +@s@} + +AH! AH! AH> +H< AH> @ +H$ IH AH6 @ + +@x +A ` + +A ` +xAH! AH! AH! AH! IAH> + +J +` +x +A> @ +AH0 AHR6 H4 HR* AHB8 HB0 +AHB8 AHR6 HR, HR" +\} + +@ +b + + + +s@JHB +J +s@AH> IH< H26 H4 H2 IS + + + +xFHE!AH> I @ + + + + + +# $I$@x$AH> #H< a + $9I$@9$AH> b + + + + + +*} + + ? +Hr + + + + +s@ +s@ + s@JHB +J +s@% +&@xI&H@ + +J@ɑ H&& +Nx +ȁ &@ +I + a + +J@ɑ H'AH> @a +
@ +@x +@ + +x +H!I A! !A@x A IB +J@ɑ AH> AH> +@I + +( + +AAH> b +bT (` + + + +/I + +Al + )I @ + +@a +I + +((I + + I{DH2@ + + + + + ++ + + $+I$+$x ,AH> a +++ + +H(@a ++ +@x +H#` +@x,,@ +I + +@ AH +@H% +@I + +BH/ + + + +:I& ` +& + + +C +y + + +x +x +@x + + + + + + + + + + +` +@ +xI +Ib + + + + +H +H@ + +@Jo + + + +@x + A + +x +@x + + + + +H.. +!H..xH&Hb +' + +I# + +@c +@ + + + +` + +I I L F +ɗ ɗ a -- a .. a + +ER + + +
+ I H +-- ` /J/J` HR@ +- +@ +ȇ +/I/` '( + + + + + + /-" +@x@H +@ + + +I/H +@@@ + + @K +H01DH +HR n + +/@a +I# + + + + + + + + +@a + @ +> ~ @M@
@LÀ +J +> ~ @M@
@LÀL + + + + + b +H + + + +: +"Ab +!H! + +_ I# + +x + + +@ +@@ + + + + + +@u + + +.H2 + + +x +x.I +! + +! +J J +@xBX H` +xBP ` + +! +JH H@ +JH +JH JH +A1 + + + xI +@ +ɀ +A + ` +x +"J@ + xI +@ +ɀ +A + ` +x +!"J@ +@@ +@H3
@ +@@ +@"@I +@ +K +K + + + + +K +3@ + + + + + +3@ + + + +@ "x +I@J@ +B` H I "| +I@J@ +Bh H %G @ B D
"H G "@ I "H "P D @ I B D "@ I "D +HH0HII@HHIHII + +H H +#I H +# H +#ɐ H +$ H +H+I H ++ H +(ɑ H +H( H +H,I H + +R0 + + + +2@@I + + + + +@ + 0 + + 0I 0 +J@ɑ A H@M +@ + + +/^a Ѐ +$@ +Y@hB&i + + +J; +bI@ +%A#$AdIA +# +@#A + +$ + + + +$@# +$ +$9#I + + + + + + + +W + + + + +$$f +$"x + +%>` + x%` +@)x%> ! d& +d +% +@x +$$$$$ + + +$A$> $ +#Dc/ + +c +d! + +Q f9@ +@xe<&a +d)e +xIa +de +@ x$@@$) a +#: @c@ +c% +fH + + +#$ +d@ +# +f!x& +c +@ +e + + +%` + + +i2 $$$$$ +d + + +f!$e +$< +d&I@ +i2 +d + + +f $$<@ + + + +hr +# + +C@ + +`B +@ +`B + + +( +! '* +@ + + + + + +x
GK` + + + +@A +C +C @ +C O +C C + +` + + +J +@ +ʀ + +xNCh @xNC@ xNCH @xNCP +K@ + x
@ x
x
@7I + +K@ + +` +JB@Jb@H + +@xNb@ +N@(I + + +\ + +A> + +@b + + +xM@Q +S$S$AL +S + +@@AH> + + + + + +I@ P +IIbIIIb@ +IIRIIIR +I + + +@@CHg@@ + + + +@s@ +JAHR0 AH! IAH! AHB8 AH0 @ + +A@ +J> +AAAAJ< +A"@@@AH> ` + + + + + +AH> +@I +H + +} + +s@ +J' +s@AHR0 AH! IAH! AAH0 @ + +A@ +J> +AAAAJ< +A"@@@I + + s@@I~@~ a #A R + FI> o + + + + + +@s +I + +AH> +@ + + + + + +P +AH0 H. @AH> H< H: + + + +AH! AH! AH> +H< AH> @ +H$ IH AH6 @ + +9 +A ` + +A ` +xAH! AH! AH! AH! IAH> +,I +J +` +x +A> @ +AH0 AHR6 H4 HR* AHB8 HB0 +AHB8 AHR6 HR, HR" +@} + + +b + + +@M +s@JHB +J@E +s@AH> IH< H26 H4 H2 I + + + +xH!AH> I @ + + + + + +# $I$@x$AH> #H< a + $I$ + + + + + +@~} + + ? +Hr + + + + +s@r +s@ +
s@JHB +J +s@% +&@xI&H@ + +J@ɑ H&& +Lx +ȁ c&@ +I + a + +J@ɑ H'AH> @a +
@@1 +@x +@ + +x +H!I A! !A@x A IB +J@ɑ AH> AH> + + +( + +AAH> b +bT (` + +>((I + +/I @T + +Al + )I @ + +@a +I + +((I + + I { + +'*@' + AH* ++ + + $+I$+$x ,AH> a ++@+ ,#@ + +H(@a ++ +@x +H#` +@x,,@ +I + +@ AH +@H% + + +F> o + + + + +:I& ` +& + + + +A@ + + + + +E +Q +@ +R +@ +P +PCJ +Q +@ +R +@ +P +PCJ +SC o -I@ -I - Rp - - - I`O - - - - - -LJ - - -` -6xG` -G -G - - - -^ -G IGa @ -a -G - - - -` -x - -@ -@ -P @ -x -9 - IG -@ -@ -P @ -x - - -GG -B - - - -H`W -x - -HH - - + +A + + HNB + + + +T "< K + +ɢ +h "< + +ɢ( ɢ ʢ + +@ +T +2@K
+ + +B +AaJ` + +" +"0 +r Ҡ + +r2 Ҡ + r Ҡ + r2 Ҡ + + +@ + + +
K +
K
3 +
+ D H + D + D Ȁ + +H + + + + + + + + + ++@+@ + + + + + +I + +@ + + +H +AH2: @. +h OI +x + +H + II + IAH2: ` + + +AH0 AH! I + +J +AH> ` +xAH> +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +4 + +HB6 + +4 + +HB6 + +4 + +HB6 + + + a + @a + +` + +I + +OAI + n + p + r t O + + +@K2 + + +@ +AH> J +H +` +` + + +A@ + +ʣ @x + MA + + + +H0 + +I + + + +H0 + + +H + +a + @a +H ` + + +" +AAAH o +H J +2X O +b +HAAAH o -*L6L @˂@ -@KK -I - - - -Br@@xr@ - - Gr -Gr - - -G` - - -G -b - - -o -I -H - - - - -G@H -?I ȑ -I a -I I - - - - - - - - - - - -J - -xGGP !@$N -@ -" -N"HD 2P @x!xA! -GG -G -G` - -@ - -@ -H!" - - -I -xF!x -@ - -N - r - - ! RGIba IGa -a + +H @ +Hb +"| AAAH @m + +B@ + + +xHAAAH o + +HAAAH o + + +OAHH +O JB@ + - -"B @x@@ o - -@ -ۆ[@GLa~ ǀ - - - - -( -! (@( hQ -( -* -kè -냨 -+B - -* -* - - -! ( 銂( ( -@$("Lh -! ( 銂( hЈ0D x( D *k -Q -* -* -k -p -* - -! h (( m-^ ( ( -@$("L( ( -! h (( -^ ( (X0D ( (0D ( ( -$/"L/ / -! h (( -^ ( ( -P$("L( ( -! h (( --^ ( h؎0D ( $$("L./( - - - -! ( 銂( @$("Lh -! ( 銂( hи0D @x( * -Q x+kA -k -p -0D ( ) ( -! h (( -^ ( @$("L( ( -! h (( ( (X0D ( (0D ( ( -! h (( m-^ ( P$("L( ( -! h (( 胂 ( hؾ0D ( $$("L./(( -@#xIU - -@ x -@@x U@U5 -`a@ - -U@ - -@V - - -E NNN$"N + +H + + +H +J +OA +"T O +HAAAH o + +H"HAAAH o + + +HAAAH o + + + +AAAH o + + + +
_
+
+ +9A + + +9J2@ɗ :H + + + +@ + +H2@ 2 + +J` JJ` +I +I + +OAH + +O + +H @ + ȇ $H
@d +
c + + + + + + +h O@a + +@AH0 AH( I b + +
J OAJb@ O +# + + + +H": ` +2` O + +*CAf +#G + +@ +I +
~ + + + KKa
AK@/ + +IH2 -xAd -V U - -E - -G -G -c - -NNN - - -@ -! -G - -ߏN Lȃ JB - -` - -, - *C(I( -,J@($,*F ( ) ("L(h! ( 튂( ( -,J@ ($("Lh! ( 튂( , -("Lh! ( 튂( - - - - - - - -:x +xJ
" +$ + +l +A1 +@ +~~ +((+@Q R PPCH + + +2@@I +@ F> +o + + +xJ +- + +?AH0 ˂@ɂ@ ʀ +` + +-AH> + + + +?AH0 ˂@ɂ@ +
x + + +V AHb4 b@ bH H2 P T B + +@AH> +F AH"< "B AH> @ 2l ˷ aF + + + +a + H + + +? + +? + + +? + +? +@ + +` + + + + + +H @H + I +@xI + +@a + I +b +IB +@ + +` + + + + + +H2@"@H +` + +P/@G +H@ + +H0 + + +H0 + +H? "P +J +bI@@ +@bA˷ aF + +b ++" ++.[ + +a .
AB+@+@ + +T + + +!+A/ + + + +,@l! + + +o + + 00 + +0 +x1! + + + +J` JJ` + ++@+@ + + + + + +I + +@ + + +H +AH2: @$ +h OI +x + +H + II + IAH2: ` + + +AH0 AH! I + +J +AH> ` +xAH> +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +4 + +HB6 + +4 + +HB6 + +4 + +HB6 + + + a + @a + +` + +I + +OAI + n + p + r t O + + +@K2 + + +@ +AH> J +H +` +` + + +A@ + +ʣ @x + MA + + + +H0 + +I + + + +H0 + + +H + +a + @a +H ` + + +" +AAAH o +H J +2X O +b +HAAAH o + + +H @ +Hb +"| AAAH @m + +B@ + + +xHAAAH o + +HAAAH o + + +OAHH +O JB@ + + + +H + + +H +J +OA +"T O +HAAAH o + +H"HAAAH o + + +HAAAH o + + + +AAAH o + + + +
+
+ +9A + + +9J2@ɗ :H + + + + + +H2@ 2 + +J` JJ` +I +I + +OAH + +O + +H @ + ȇ $H
f +
@f + + + + + + +@ +h O@a + +@AH0 AH( I b + +
J OAJb@ O +# + + + +H": ` +2` O + +*CAf +#G + +@ +I +
~ + + + KKa
AK@/ + +IH2 + +xJ
" +$ + +l +A1 +@ +@|~ +((+@Q R PPCH + + +2@@I +@ F> +o + + +xJ +- + +?AH0 ˂@ɂ@ ʀ +` + +-AH> + + + +?AH0 ˂@ɂ@ +
x + + +V AHb4 b@ bH H2 P T B + +@AH> +F AH"< "B AH> @ 2l ˷ aF + + + +a + H + + +? + +? + + +? + +? +@ + +` + + + + + +H @H + I +@xI + +@a + I +b +IB +@ + +` + + + + + +H2@"@H +` + +P/: +H@ + +H0 + + +H0 + +H? "P +@bA˷ aF + +b ++.[ + +a .
AB+@+@ + + + + +!+A/ + + + +,@l! + + +o + + 00 + +0 +x1! + + + +J` JJ` + ++@+@ + + + +y + +I + +@ + + +H +AH2: +h OI +x + +H + II + IAH2: ` + + +AH0 AH! I + +J +AH> ` +xAH> +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +4 + +HB6 + +4 + +HB6 + +4 + +HB6 + + + a + @a + +` + +I + +OAI + n + p + r t O@ + + +@ +AH> J +H +` +` + + +A@ + +ʣ @x + MA + + + +H0 + +I + + + +H0 + + +H + +a + @a +H ` + + +" +AAAH o +H J +2X O +b +HAAAH o + + +H @ +Hb +"| AAAH @m + +B@ + + +xHAAAH o + +HAAAH o + + +OAHH +O JB@ + + + +H + + +H +J +OA +"T O +HAAAH o + +H"HAAAH o + + +HAAAH o + + + +AAAH o + + + +
+
+ +9A + + +9J2@ɗ :H + + + + + +H2@ 2 + +J` JJ` +I +I + +OAH + +O + +H @ + ȇ $H
f +
@f + + + + + + +@ +h O@a + +AH0 AH( I b + +
J OAJb@ O +# + + + +H": ` +2` O@ + +*CAf +#G + +@ +I +
~ + + + KKa
AK@/ + +IH2 + +xJ
" +$ + +l +A1 +@ +}~ +((+@Q R PPCH + + +2@@I +@ F> +o + + +xJ +- + +?AH0 ˂@ɂ@ ʀ +` + +-AH> + + + +?AH0 ˂@ɂ@ +
x + + +V AHb4 b@ bH H2 P T B + +@AH> +F AH"< "B AH> @ 2l ˷ aF + + + +a + H + + +? + +? + + +? + +? +@ + +` + + + + + +H @H + I +@xI + +@a + I +b +IB +@ + +` + + + + + +H2@"@H +` + +P/: +H@ + +H0 + + +H0 + +H? "P +@bA˷ aF + +b ++.[ + +a .
AB+@+@ + + + + +!+A/ + + + +,@l! + + +o + + 00 + +0 +x1! + + + +J` JJ` + ++@+@ + + + + y + +I + +@ + + +H +AH2: # +h OI +@x + +H + II + IAH2: ` + + +AH0 AH! I + +J +AH> ` +xAH> +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +4 + +HB6 + +4 + +HB6 + +4 + +HB6 + + + a + @a + +` + +I + +OAI + n + p + r t O + + +@ +AH> J +H +` +` + + +A + +ʣ @x + MA + + + +H0 + +I + + + +H0 + + +H + +a + @a +H ` + + +" +AAAH o +H J +2X O +b +HAAAH o + + +H @ +Hb +"| AAAH @m + +B@ + + +xHAAAH o + +HAAAH o + + +OAHH +O JB@ + + + +H + + +H +J +OA +"T O +HAAAH o + +H"HAAAH o + + +HAAAH o + + + +AAAH o + + + +
_
+
+ +9A + + +9J2@ɗ :H + + + + + +H2@ 2 + +J` JJ` +I +I + +OAH + +O + +H @ + ȇ $H
f +
@f + + + + + + +@ +h O@a + +AH0 AH( I b + +
J OAJb@ O +# + + + +H": ` +2` O + +*CAf +#G + +@ +I +
~ + + + KKa
AK@/ + +IH2 + +xJ
" +$ + +l +A1 +@ +|~ +((+@Q R PPCH + + +2@@I +@ F> +o + + +xJ +- + +?AH0 ˂@ɂ@ ʀ +` + +-AH> + + + +?AH0 ˂@ɂ@ +
x + + +V AHb4 b@ bH H2 P T B + +@AH> +F AH"< "B AH> @ 2l ˷ aF + + + +a + H + + +? + +? + + +? + +? +@ + +` + + + + + +H @H + I +@xI + +@a + I +b +IB +@ + +` + + + + + +H2@"@H +` + +P/: +H@ + +H0 + + +H0 + +H? "P +@bA˷ aF + +b ++.[ + +a .
AB+@+@ + + + + +!+A/ + + + +,@l! + + +o + + 00 + +0 +x1! + + + +J` JJ` + ++@+@ + + + + + +I + +@ + + +H +AH2: @$ +h OI +x + +H + II + IAH2: ` + + +AH0 AH! I + +J +AH> ` +xAH> +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +4 + +HB6 + +4 + +HB6 + +4 + +HB6 + + + a + @a + +` + +I + +OAI + n + p + r t O + + +@K2 + + +@ +AH> J +H +` +` + + +A@ + +ʣ @x + MA + + + +H0 + +I + + + +H0 + + +H + +a + @a +H ` + + +" +AAAH o +H J +2X O +b +HAAAH o + + +H @ +Hb +"| AAAH @m + +B@ + + +xHAAAH o + +HAAAH o + + +OAHH +O JB@ + + + +H + + +H +J +OA +"T O +HAAAH o + +H"HAAAH o + + +HAAAH o + + + +AAAH o + + + +
+
+ +9A + + +9J2@ɗ :H + + + + + +H2@ 2 + +J` JJ` +I +I + +OAH + +O + +H @ + ȇ $H
f +
@f + + + + + + +@ +h O@a + +@AH0 AH( I b + +
J OAJb@ O +# + + + +H": ` +2` O + +*CAf +#G + +@ +I +
~ + + + KKa
AK@/ + +IH2 + +xJ
" +$ + +l +A1 +@ +@|~ +((+@Q R PPCH + + +2@@I +@ F> +o + + +xJ +- + +?AH0 ˂@ɂ@ ʀ +` + +-AH> + + + +?AH0 ˂@ɂ@ +
x + + +V AHb4 b@ bH H2 P T B + +@AH> +F AH"< "B AH> @ 2l ˷ aF + + + +a + H + + +? + +? + + +? + +? +@ + +` + + + + + +H @H + I +@xI + +@a + I +b +IB +@ + +` + + + + + +H2@"@H +` + +P/: +H@ + +H0 + + +H0 + +H? "P +@bA˷ aF + +b ++.[ + +a .
AB+@+@ + + + + +!+A/ + + + +,@l! + + +o + + 00 + +0 +x1! + + + +J` JJ` + ++@+@ + + + +y + +I + +@ + + +H +AH2: * +h OI +x + +H + II + IAH2: ` + + +AH0 AH! I + +J +AH> ` +xAH> +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +4 + +HB6 + +4 + +HB6 + +4 + +HB6 + + + a + @a + +` + +I + +OAI + n + p + r t O + + +@K2 + + +@ +AH> J +H +` +` + + +A + +ʣ @x + MA@ + + + +H0 + +I + + + +H0 + + +H + +a + @a +H ` + + +" +AAAH o +H J +2X O +b +HAAAH o + + +H @ +Hb +"| AAAH @m + +B@ + + +xHAAAH o + +HAAAH o + + +OAHH +O JB@ + + + +H + + +H +J +OA +"T O +HAAAH o + +H"HAAAH o + + +HAAAH o + + + +AAAH o + + + +
+
+ +9A + + +9J2@ɗ :H + + + + + +H2@ 2 + +J` JJ` +I +I + +OAH + +O + +H @ + ȇ $H
+
` + + + + + + + +h O@a + +AH0 AH( I b + +
J OAJb@ O +# + + + +H": ` +2` O@ + +*CAf +#G + +@ +I +
~ + + + KKa
AK@/ + +IH2 + +xJ
" +$ + +l +A1 +@ +~ +((+@Q R PPCH + + +2@@I +@ F> +o + + +xJ +- + +?AH0 ˂@ɂ@ ʀ +` + +-AH> + + + +?AH0 ˂@ɂ@ +
x + + +V AHb4 b@ bH H2 P T B + +@AH> +F AH"< "B AH> @ 2l ˷ aF + + + +a + H + + +? + +? + + +? + +? +@ + +` + + + + + +H @H + I +@xI + +@a + I +b +IB +@ + +` + + + + + +H2@"@H +` + +P/@G +H@ + +H0 + + +H0 + +H? "P +J +bI@@ +@bA˷ aF + +b ++" ++.[ + +a .
AB+@+@ + +T + + +!+A/ + + + +,@l! + + +o + + 00 + +0 +x1! + + + +J` JJ` + ++@+@ + + + + y + +I + +@ + + +H +AH2: # +h OI +@x + +H + II + IAH2: ` + + +AH0 AH! I + +J +AH> ` +xAH> +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +0 + +Hb2 + +4 + +HB6 + +4 + +HB6 + +4 + +HB6 + + + a + @a + +` + +I + +OAI + n + p + r t O + + +@ +AH> J +H +` +` + + +A + +ʣ @x + MA + + + +H0 + +I + + + +H0 + + +H + +a + @a +H ` + + +" +AAAH o +H J +2X O +b +HAAAH o + + +H @ +Hb +"| AAAH @m + +B@ + + +xHAAAH o + +HAAAH o + + +OAHH +O JB@ + + + +H + + +H +J +OA +"T O +HAAAH o + +H"HAAAH o + + +HAAAH o + + + +AAAH o + + + +
_
+
+ +9A + + +9J2@ɗ :H + + + + + +H2@ 2 + +J` JJ` +I +I + +OAH + +O + +H @ + ȇ $H
f +
@f + + + + + + +@ +h O@a + +AH0 AH( I b + +
J OAJb@ O +# + + + +H": ` +2` O + +*CAf +#G + +@ +I +
~ + + + KKa
AK@/ + +IH2 + +xJ
" +$ + +l +A1 +@ +|~ +((+@Q R PPCH + + +2@@I +@ F> +o + + +xJ +- + +?AH0 ˂@ɂ@ ʀ +` + +-AH> + + + +?AH0 ˂@ɂ@ +
x + + +V AHb4 b@ bH H2 P T B + +@AH> +F AH"< "B AH> @ 2l ˷ aF + + + +a + H + + +? + +? + + +? + +? +@ + +` + + + + + +H @H + I +@xI + +@a + I +b +IB +@ + +` + + + + + +H2@"@H +` + +P/: +H@ + +H0 + + +H0 + +H? "P +@bA˷ aF + +b ++.[ + +a .
AB+@+@ + + + + +!+A/ + + + +,@l! + + +o + + 00 + +0 +x1! + + + +J` JJ` + FL CL R@ +I` +x` +xH! +@x G
@a - + @x -x +
y , - + - + ! -J +J ,! @@ -30655,46 +31120,47 @@ J G$ ` - + @I - + +GIǁ +I@ o -I@Ip v Gv v Gw p v Gv v Gw - - - -k@WY - -@ +I@IH IQ + + +kWRk@5P` + + r -H - +H + @I ` G
` -@x +@x G`HR@ `"@ - - + + + b 2x -B - - - - - - - +B + + + + + + A @a - - + + @@ -30703,78 +31169,124 @@ G
` - @I ^ G \ G Z -I + @I
^ G \ G Z +I -I - +I +@ QGbɑ@I2 QHbIb P PCIIb -@ + QRIc P PCIIG
B -G LI B HbBx a t - - - -` - -GIǁ a -O +G LI B HbBx a t + +x@ + ɀ + + +ɱ +x + + +GIǁ a +O I@I - - - -@ x - -> -@x - + - -xQL FLBL -@Lr@ǁ -?I H -I HR - I Ix I I + + +@Lr@ǁ +` +H + +I + +@a + L H2X - IH - - + + +x@ + A$ +@c + + + ʣ H +@x + + + + Gx +H + + & + +a +% + + +$ +a# +HJ!" +! + G + +A Q@ +G + +@xGH ` +xGP ` +xGX ` +@xG@ H` +xGH ` + + + G +@x I IB@HB@ + - - - - - -AL"CLh ޘ@ - - + + + +I +I + +AL"CLh @ + + +( +x(h +@ +i +(A +h +A + +߿ +( +( )CL): - + @xa - -I -A@_` -T@GL@~ -U - - -A@ - + +I +A@_` +@~ +A@ + @@ -30783,19 +31295,18 @@ U s s Eg a - + L@a - + + E@a -@ + L - -D -GIǁ -I@ + +D ! <Ȁa E<B @@ -30806,35 +31317,30 @@ E<B E=== E DL>L b -D@ @ - -@xHR& b@I"@J@Hb - - - - - - - - - -:x +D@ @ + +xHR& b@I"@J@Hb + FL CL R@ +I` +x` +xH! + G
@a - + @x -x +y , - + -@ ++ ! -J +J ,! @@ -30842,46 +31348,45 @@ J G$ ` - + @I - + +GIǁ +I@ o -I@Ip v Gv v Gw p v Gv v Gw - - - -k@W@W - -@ +I@Ip v Gv v Gw p v Gv v Gw + +kWRk@5P` + + r -H - +H + @I ` G
` -x +x G`HR@ `"@ - - + + b 2x -B - - - - - - - +B + + + + + + A @a - - + + @@ -30890,77 +31395,124 @@ G
` - @I ^ G \ G Z -I + @I
^ G \ G Z +I -I - +I +@ QGbɑ@I2 QHbIb P PCIIb -@ + QRIc P PCIIG
B -G LI B HbBx a t - - - -@^ - -GIǁ a -O +G LI B HbBx a t + +x@ + ɀ + + +ɱ + + + +GIǁ a +O I@I - - -@ x - -> -@x - + - -xQL FLBL -@Lr@ǁ -?I H -I HR - I Ix I I + +@Lr@ǁ +` +H + +I + +@a + L H2X - - + + +x@ + A$ +@c + + + ʣ H +@x + + + + Gx +H + + & + +a +% + + +$ +a# +HJ!" +! + G + +A Q@ +G + +@xGH ` +xGP ` +xGX ` +@xG@ H` +xGH ` + + + G +@x I IB@HB@ + - - - - - -AL"CLh ޘ@ - - + + + +I +I + +AL"CLh @ + + +( +x(h +@ +i +(A +h +A + +߿ +( +( )CL): - + @xa - -I -A@_` -T@GL~ -U - - -A@ - + +I +A@_` +~ +A@ + @@ -30969,19 +31521,18 @@ U s s Eg a - + L@a - + + E@a -@ + L - -D -GIǁ -I@ + +D ! <Ȁa E<B @@ -30992,35 +31543,30 @@ E<B E=== E DL>L b -D@ @ - -@xHR& b@I"@J@Hb - - - - - - - - - -:x +D@ @ + +xHR& b@I"@J@Hb + FL CL R@ +I` +x` +xH! +@x G
@a - + @x -x +
y , - + - + ! -J +J ,! @@ -31028,46 +31574,47 @@ J G$ ` - + @I - + +GIǁ +I@ o -I@Ip v Gv v Gw p v Gv v Gw - - - -k@WY - -@ +I@IH IQ + + +kWRk@5P` + + r -H - +H + @I ` G
` -@x +@x G`HR@ `"@ - - + + + b 2x -B - - - - - - - +B + + + + + + A @a - - + + @@ -31076,78 +31623,124 @@ G
` - @I ^ G \ G Z -I + @I
^ G \ G Z +I -I - +I +@ QGbɑ@I2 QHbIb P PCIIb -@ + QRIc P PCIIG
B -G LI B HbBx a t - - - -` - -GIǁ a -O +G LI B HbBx a t + +x@ + ɀ + + +ɱ +x + + +GIǁ a +O I@I - - - -@ x - -> -@x - + - -xQL FLBL -@Lr@ǁ -?I H -I HR - I Ix I I + + +@Lr@ǁ +` +H + +I + +@a + L H2X - IH - - + + +x@ + A$ +@c + + + ʣ H +@x + + + + Gx +H + + & + +a +% + + +$ +a# +HJ!" +! + G + +A Q@ +G + +@xGH ` +xGP ` +xGX ` +@xG@ H` +xGH ` + + + G +@x I IB@HB@ + - - - - - -AL"CLh ޘ@ - - + + + +I +I + +AL"CLh @ + + +( +x(h +@ +i +(A +h +A + +߿ +( +( )CL): - + @xa - -I -A@_` -T@GL@~ -U - - -A@ - + +I +A@_` +@~ +A@ + @@ -31156,19 +31749,18 @@ U s s Eg a - + L@a - + + E@a -@ + L - -D -GIǁ -I@ + +D ! <Ȁa E<B @@ -31179,35 +31771,30 @@ E<B E=== E DL>L b -D@ @ - -@xHR& b@I"@J@Hb - - - - - - - - - -:x +D@ @ + +xHR& b@I"@J@Hb + FL CL R@ +I` +x` +xH! + G
@a - + @x -x +y , - + -@ ++ ! -J +J ,! @@ -31215,46 +31802,45 @@ J G$ ` - + @I - + +GIǁ +I@ o -I@Ip v Gv v Gw p v Gv v Gw - - - -k@W@W - -@ +I@Ip v Gv v Gw p v Gv v Gw + +kWRk@5P` + + r -H - +H + @I ` G
` -x +x G`HR@ `"@ - - + + b 2x -B - - - - - - - +B + + + + + + A @a - - + + @@ -31263,77 +31849,124 @@ G
` - @I ^ G \ G Z -I + @I
^ G \ G Z +I -I - +I +@ QGbɑ@I2 QHbIb P PCIIb -@ + QRIc P PCIIG
B -G LI B HbBx a t - - - -@^ - -GIǁ a -O +G LI B HbBx a t + +x@ + ɀ + + +ɱ + + + +GIǁ a +O I@I - - -@ x - -> -@x - + - -xQL FLBL -@Lr@ǁ -?I H -I HR - I Ix I I + +@Lr@ǁ +` +H + +I + +@a + L H2X - - + + +x@ + A$ +@c + + + ʣ H +@x + + + + Gx +H + + & + +a +% + + +$ +a# +HJ!" +! + G + +A Q@ +G + +@xGH ` +xGP ` +xGX ` +@xG@ H` +xGH ` + + + G +@x I IB@HB@ + - - - - - -AL"CLh ޘ@ - - + + + +I +I + +AL"CLh @ + + +( +x(h +@ +i +(A +h +A + +߿ +( +( )CL): - + @xa - -I -A@_` -T@GL~ -U - - -A@ - + +I +A@_` +~ +A@ + @@ -31342,19 +31975,18 @@ U s s Eg a - + L@a - + + E@a -@ + L - -D -GIǁ -I@ + +D ! <Ȁa E<B @@ -31365,8 +31997,6 @@ E<B E=== E DL>L b -D@ @ - -@xHR& b@I"@J@Hb - - +D@ @ + +xHR& b@I"@J@Hb |