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 if (!ctx) {
54 ALOGE("ERROR: Failed %s %d: ctx is nullptr", __func__, __LINE__);
55 return -1;
56 }
57 auto transport = GoldfishMediaTransport::getInstance();
58 transport->writeParam(ctx->id, 0, ctx->address_offset);
59 sendVpxOperation(ctx, MediaOperation::DestroyContext);
60 transport->returnMemorySlot(ctx->memory_slot);
61 ctx->memory_slot = -1;
62 return 0;
63 }
64
vpx_codec_dec_init(vpx_codec_ctx_t * ctx)65 int vpx_codec_dec_init(vpx_codec_ctx_t* ctx) {
66 DDD("%s %d", __func__, __LINE__);
67 auto transport = GoldfishMediaTransport::getInstance();
68 int slot = transport->getMemorySlot();
69 if (slot < 0) {
70 ALOGE("ERROR: Failed %s %d: cannot get memory slot", __func__,
71 __LINE__);
72 return -1;
73 } else {
74 DDD("got slot %d", slot);
75 }
76 ctx->id = applyForOneId();
77 ctx->memory_slot = slot;
78 ctx->address_offset = static_cast<unsigned int>(ctx->memory_slot) * (1 << 20);
79 DDD("got address offset 0x%x version %d", (int)(ctx->address_offset),
80 ctx->version);
81
82 // data and dst are on the host side actually
83 ctx->data = transport->getInputAddr(ctx->address_offset);
84 ctx->dst = transport->getInputAddr(
85 ctx->address_offset); // re-use input address
86 transport->writeParam(ctx->id, 0, ctx->address_offset);
87 transport->writeParam(ctx->version, 1, ctx->address_offset);
88 sendVpxOperation(ctx, MediaOperation::InitContext);
89 return 0;
90 }
91
getReturnCode(uint8_t * ptr)92 static int getReturnCode(uint8_t* ptr) {
93 int* pint = (int*)(ptr);
94 return *pint;
95 }
96
97 // vpx_image_t myImg;
getVpxFrame(uint8_t * ptr,vpx_image_t & myImg)98 static void getVpxFrame(uint8_t* ptr, vpx_image_t& myImg) {
99 DDD("%s %d", __func__, __LINE__);
100 uint8_t* imgptr = (ptr + 8);
101 myImg.fmt = *(vpx_img_fmt_t*)imgptr;
102 imgptr += 8;
103 myImg.d_w = *(unsigned int *)imgptr;
104 imgptr += 8;
105 myImg.d_h = *(unsigned int *)imgptr;
106 imgptr += 8;
107 myImg.user_priv = (void*)(*(uint64_t*)imgptr);
108 DDD("fmt %d dw %d dh %d userpriv %p", (int)myImg.fmt, (int)myImg.d_w,
109 (int)myImg.d_h, myImg.user_priv);
110 }
111
112 //TODO: we might not need to do the putting all the time
vpx_codec_get_frame(vpx_codec_ctx_t * ctx,int hostColorBufferId)113 vpx_image_t* vpx_codec_get_frame(vpx_codec_ctx_t* ctx, __attribute__((unused)) int hostColorBufferId) {
114 DDD("%s %d %p", __func__, __LINE__);
115 if (!ctx) {
116 ALOGE("ERROR: Failed %s %d: ctx is nullptr", __func__, __LINE__);
117 return nullptr;
118 }
119 auto transport = GoldfishMediaTransport::getInstance();
120
121 transport->writeParam(ctx->id, 0, ctx->address_offset);
122 transport->writeParam(ctx->outputBufferWidth, 1, ctx->address_offset);
123 transport->writeParam(ctx->outputBufferHeight, 2, ctx->address_offset);
124 transport->writeParam(ctx->width, 3, ctx->address_offset);
125 transport->writeParam(ctx->height, 4, ctx->address_offset);
126 transport->writeParam(ctx->bpp, 5, ctx->address_offset);
127 transport->writeParam(ctx->hostColorBufferId, 6, ctx->address_offset);
128 transport->writeParam(
129 transport->offsetOf((uint64_t)(ctx->dst)) - ctx->address_offset, 7,
130 ctx->address_offset);
131
132 sendVpxOperation(ctx, MediaOperation::GetImage);
133
134 auto* retptr = transport->getReturnAddr(ctx->address_offset);
135 int ret = getReturnCode(retptr);
136 if (ret) {
137 return nullptr;
138 }
139 getVpxFrame(retptr, ctx->myImg);
140 return &(ctx->myImg);
141 }
142
vpx_codec_flush(vpx_codec_ctx_t * ctx)143 int vpx_codec_flush(vpx_codec_ctx_t* ctx) {
144 DDD("%s %d", __func__, __LINE__);
145 if (!ctx) {
146 ALOGE("ERROR: Failed %s %d: ctx is nullptr", __func__, __LINE__);
147 return -1;
148 }
149 auto transport = GoldfishMediaTransport::getInstance();
150 transport->writeParam(ctx->id, 0, ctx->address_offset);
151 sendVpxOperation(ctx, MediaOperation::Flush);
152 return 0;
153 }
154
vpx_codec_decode(vpx_codec_ctx_t * ctx,const uint8_t * data,unsigned int data_sz,void * user_priv,long deadline)155 int vpx_codec_decode(vpx_codec_ctx_t *ctx,
156 const uint8_t* data,
157 unsigned int data_sz,
158 void* user_priv,
159 __attribute__((unused)) long deadline) {
160 if (!ctx) {
161 ALOGE("ERROR: Failed %s %d: ctx is nullptr", __func__, __LINE__);
162 return -1;
163 }
164 DDD("%s %d data size %d userpriv %p", __func__, __LINE__, (int)data_sz,
165 user_priv);
166 auto transport = GoldfishMediaTransport::getInstance();
167 memcpy(ctx->data, data, data_sz);
168
169 transport->writeParam(ctx->id, 0, ctx->address_offset);
170 transport->writeParam(
171 transport->offsetOf((uint64_t)(ctx->data)) - ctx->address_offset, 1,
172 ctx->address_offset);
173 transport->writeParam((__u64)data_sz, 2, ctx->address_offset);
174 transport->writeParam((__u64)user_priv, 3, ctx->address_offset);
175 sendVpxOperation(ctx, MediaOperation::DecodeImage);
176 return 0;
177 }
178