1 #include <log/log.h>
2 
3 #include <linux/types.h>
4 #include <linux/ioctl.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <sys/mman.h>
8 #include <sys/ioctl.h>
9 #include <fcntl.h>
10 #include <unistd.h>
11 #include <cstdlib>
12 #include <string>
13 #include <errno.h>
14 #include "goldfish_vpx_defs.h"
15 #include "goldfish_media_utils.h"
16 
17 #include <memory>
18 #include <mutex>
19 #include <vector>
20 
21 #define DEBUG 0
22 #if DEBUG
23 #define DDD(...) ALOGD(__VA_ARGS__)
24 #else
25 #define DDD(...) ((void)0)
26 #endif
27 
28 // static vpx_image_t myImg;
29 static uint64_t s_CtxId = 0;
30 static std::mutex sCtxidMutex;
31 
applyForOneId()32 static uint64_t applyForOneId() {
33     DDD("%s %d", __func__, __LINE__);
34     std::lock_guard<std::mutex> g{sCtxidMutex};
35     ++s_CtxId;
36     return s_CtxId;
37 }
38 
sendVpxOperation(vpx_codec_ctx_t * ctx,MediaOperation op)39 static void sendVpxOperation(vpx_codec_ctx_t* ctx, MediaOperation op) {
40     DDD("%s %d", __func__, __LINE__);
41     if (ctx->memory_slot < 0) {
42         ALOGE("ERROR: Failed %s %d: there is no memory slot", __func__,
43               __LINE__);
44     }
45     auto transport = GoldfishMediaTransport::getInstance();
46     transport->sendOperation(ctx->vpversion == 9 ? MediaCodecType::VP9Codec
47                                                  : MediaCodecType::VP8Codec,
48                              op, ctx->address_offset);
49 }
50 
vpx_codec_destroy(vpx_codec_ctx_t * ctx)51 int vpx_codec_destroy(vpx_codec_ctx_t* ctx) {
52     DDD("%s %d", __func__, __LINE__);
53     auto transport = GoldfishMediaTransport::getInstance();
54     transport->writeParam(ctx->id, 0, ctx->address_offset);
55     sendVpxOperation(ctx, MediaOperation::DestroyContext);
56     transport->returnMemorySlot(ctx->memory_slot);
57     ctx->memory_slot = -1;
58     return 0;
59 }
60 
vpx_codec_dec_init(vpx_codec_ctx_t * ctx)61 int vpx_codec_dec_init(vpx_codec_ctx_t* ctx) {
62     DDD("%s %d", __func__, __LINE__);
63     auto transport = GoldfishMediaTransport::getInstance();
64     int slot = transport->getMemorySlot();
65     if (slot < 0) {
66         ALOGE("ERROR: Failed %s %d: cannot get memory slot", __func__,
67               __LINE__);
68         return -1;
69     } else {
70         DDD("got slot %d", slot);
71     }
72     ctx->id = applyForOneId();
73     ctx->memory_slot = slot;
74     ctx->address_offset = static_cast<unsigned int>(slot) * 8 * (1 << 20);
75     DDD("got address offset 0x%x version %d", (int)(ctx->address_offset),
76         ctx->version);
77 
78     // data and dst are on the host side actually
79     ctx->data = transport->getInputAddr(ctx->address_offset);
80     ctx->dst = transport->getInputAddr(
81             ctx->address_offset);  // re-use input address
82     transport->writeParam(ctx->id, 0, ctx->address_offset);
83     transport->writeParam(ctx->version, 1, ctx->address_offset);
84     sendVpxOperation(ctx, MediaOperation::InitContext);
85     return 0;
86 }
87 
getReturnCode(uint8_t * ptr)88 static int getReturnCode(uint8_t* ptr) {
89     int* pint = (int*)(ptr);
90     return *pint;
91 }
92 
93 // vpx_image_t myImg;
getVpxFrame(uint8_t * ptr,vpx_image_t & myImg)94 static void getVpxFrame(uint8_t* ptr, vpx_image_t& myImg) {
95     DDD("%s %d", __func__, __LINE__);
96     uint8_t* imgptr = (ptr + 8);
97     myImg.fmt = *(vpx_img_fmt_t*)imgptr;
98     imgptr += 8;
99     myImg.d_w = *(unsigned int *)imgptr;
100     imgptr += 8;
101     myImg.d_h = *(unsigned int *)imgptr;
102     imgptr += 8;
103     myImg.user_priv = (void*)(*(uint64_t*)imgptr);
104     DDD("fmt %d dw %d dh %d userpriv %p", (int)myImg.fmt, (int)myImg.d_w,
105         (int)myImg.d_h, myImg.user_priv);
106 }
107 
108 //TODO: we might not need to do the putting all the time
vpx_codec_get_frame(vpx_codec_ctx_t * ctx,int hostColorBufferId)109 vpx_image_t* vpx_codec_get_frame(vpx_codec_ctx_t* ctx, int hostColorBufferId) {
110     DDD("%s %d %p", __func__, __LINE__);
111     auto transport = GoldfishMediaTransport::getInstance();
112 
113     transport->writeParam(ctx->id, 0, ctx->address_offset);
114     transport->writeParam(ctx->outputBufferWidth, 1, ctx->address_offset);
115     transport->writeParam(ctx->outputBufferHeight, 2, ctx->address_offset);
116     transport->writeParam(ctx->width, 3, ctx->address_offset);
117     transport->writeParam(ctx->height, 4, ctx->address_offset);
118     transport->writeParam(ctx->bpp, 5, ctx->address_offset);
119     transport->writeParam(ctx->hostColorBufferId, 6, ctx->address_offset);
120     transport->writeParam(
121             transport->offsetOf((uint64_t)(ctx->dst)) - ctx->address_offset, 7,
122             ctx->address_offset);
123 
124     sendVpxOperation(ctx, MediaOperation::GetImage);
125 
126     auto* retptr = transport->getReturnAddr(ctx->address_offset);
127     int ret = getReturnCode(retptr);
128     if (ret) {
129         return nullptr;
130     }
131     getVpxFrame(retptr, ctx->myImg);
132     return &(ctx->myImg);
133 }
134 
vpx_codec_flush(vpx_codec_ctx_t * ctx)135 int vpx_codec_flush(vpx_codec_ctx_t* ctx) {
136     DDD("%s %d", __func__, __LINE__);
137     auto transport = GoldfishMediaTransport::getInstance();
138     transport->writeParam(ctx->id, 0, ctx->address_offset);
139     sendVpxOperation(ctx, MediaOperation::Flush);
140     return 0;
141 }
142 
vpx_codec_decode(vpx_codec_ctx_t * ctx,const uint8_t * data,unsigned int data_sz,void * user_priv,long deadline)143 int vpx_codec_decode(vpx_codec_ctx_t *ctx,
144                      const uint8_t* data,
145                      unsigned int data_sz,
146                      void* user_priv,
147                      long deadline) {
148     DDD("%s %d data size %d userpriv %p", __func__, __LINE__, (int)data_sz,
149         user_priv);
150     auto transport = GoldfishMediaTransport::getInstance();
151     memcpy(ctx->data, data, data_sz);
152 
153     transport->writeParam(ctx->id, 0, ctx->address_offset);
154     transport->writeParam(
155             transport->offsetOf((uint64_t)(ctx->data)) - ctx->address_offset, 1,
156             ctx->address_offset);
157     transport->writeParam((__u64)data_sz, 2, ctx->address_offset);
158     transport->writeParam((__u64)user_priv, 3, ctx->address_offset);
159     sendVpxOperation(ctx, MediaOperation::DecodeImage);
160     return 0;
161 }
162