Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2021
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / mediacodec decoder filter
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 :
26 :
27 : #include <gpac/internal/media_dev.h>
28 : #include <gpac/constants.h>
29 :
30 : #if defined(GPAC_CONFIG_ANDROID) && defined(GPAC_HAS_MEDIACODEC)
31 :
32 : #include "dec_mediacodec.h"
33 :
34 : typedef struct
35 : {
36 : //opts
37 : Bool disable_gl;
38 :
39 :
40 : GF_List *streams;
41 : GF_List *frames_res;
42 : GF_Filter *filter;
43 : GF_FilterPid *opid;
44 : u32 codecid;
45 : u32 cfg_crc;
46 :
47 : AMediaCodec *codec;
48 : AMediaFormat *format;
49 : ANativeWindow *window;
50 :
51 : Bool use_gl_textures;
52 : u32 dequeue_timeout;
53 : u32 width, height, stride, out_size;
54 : u32 pix_fmt;
55 : GF_Fraction sar;
56 :
57 : u32 crop_left, crop_right, crop_top, crop_bottom;
58 :
59 : const char *mime;
60 : u8 chroma_format, luma_bit_depth, chroma_bit_depth;
61 :
62 : Bool is_adaptive;
63 : Bool surface_rendering;
64 : Bool frame_size_changed;
65 : Bool inputEOS, outputEOS;
66 :
67 : GF_MCDecSurfaceTexture surfaceTex;
68 :
69 : //NAL-based specific
70 : GF_List *SPSs, *PPSs, *VPSs;
71 : s32 active_sps, active_pps, active_vps;
72 : u32 nalu_size_length;
73 : Bool inject_xps;
74 :
75 : AVCState avc;
76 : HEVCState hevc;
77 :
78 : u32 decoded_frames_pending;
79 : Bool reconfig_needed;
80 : Bool before_exit_registered;
81 :
82 : //hevc
83 : u32 luma_bpp, chroma_bpp;
84 : u8 chroma_format_idc;
85 :
86 : ssize_t outIndex;
87 : GLuint tex_id;
88 : } GF_MCDecCtx;
89 :
90 : typedef struct {
91 : GF_FilterFrameInterface frame_ifce;
92 : u8 * frame;
93 : GF_MCDecCtx * ctx;
94 : ssize_t outIndex;
95 : Bool flushed;
96 : } GF_MCDecFrame;
97 :
98 : enum {
99 : MCDEC_PPS = 0,
100 : MCDEC_SPS,
101 : MCDEC_VPS,
102 : };
103 :
104 : #if 0
105 : u8 sdkInt()
106 : {
107 : char sdk_str[3] = "0";
108 : //__system_property_get("ro.build.version.sdk", sdk_str, "0");
109 : return atoi(sdk_str);
110 : }
111 : #endif
112 :
113 :
114 : void mcdec_init_media_format(GF_MCDecCtx *ctx, AMediaFormat *format)
115 : {
116 : AMediaFormat_setString(ctx->format, AMEDIAFORMAT_KEY_MIME, ctx->mime);
117 : AMediaFormat_setInt32(ctx->format, AMEDIAFORMAT_KEY_WIDTH, ctx->width);
118 : AMediaFormat_setInt32(ctx->format, AMEDIAFORMAT_KEY_HEIGHT, ctx->height);
119 : AMediaFormat_setInt32(ctx->format, AMEDIAFORMAT_KEY_STRIDE, ctx->stride);
120 : AMediaFormat_setInt32(ctx->format, AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, ctx->width * ctx->height);
121 : }
122 :
123 :
124 : static void mcdec_reset_ps_list(GF_List *list)
125 : {
126 : while (list && gf_list_count(list)) {
127 : GF_NALUFFParam *slc = gf_list_get(list, 0);
128 : gf_free(slc->data);
129 : gf_free(slc);
130 : gf_list_rem(list, 0);
131 : }
132 : }
133 :
134 :
135 : GF_Err mcdec_init_avc_dec(GF_MCDecCtx *ctx)
136 : {
137 : s32 idx;
138 : u32 i;
139 : GF_NALUFFParam *sps = NULL;
140 : GF_NALUFFParam *pps = NULL;
141 :
142 : for (i=0; i<gf_list_count(ctx->SPSs); i++) {
143 : sps = gf_list_get(ctx->SPSs, i);
144 : if (ctx->active_sps<0) ctx->active_sps = sps->id;
145 :
146 : if (sps->id==ctx->active_sps) break;
147 : sps = NULL;
148 : }
149 : if (!sps) return GF_NON_COMPLIANT_BITSTREAM;
150 : for (i=0; i<gf_list_count(ctx->PPSs); i++) {
151 : pps = gf_list_get(ctx->PPSs, i);
152 : if (ctx->active_pps<0) ctx->active_pps = pps->id;
153 : if (pps->id==ctx->active_pps) break;
154 : pps = NULL;
155 : }
156 : if (!pps) return GF_NON_COMPLIANT_BITSTREAM;
157 : ctx->reconfig_needed = GF_FALSE;
158 : ctx->inject_xps = GF_TRUE;
159 :
160 : idx = ctx->active_sps;
161 : ctx->width = ctx->avc.sps[idx].width;
162 : ctx->height = ctx->avc.sps[idx].height;
163 : ctx->crop_left = ctx->avc.sps[idx].crop.left;
164 : ctx->crop_right = ctx->avc.sps[idx].crop.right;
165 : ctx->crop_top = ctx->avc.sps[idx].crop.top;
166 : ctx->crop_bottom = ctx->avc.sps[idx].crop.bottom;
167 : ctx->crop_left = ctx->avc.sps[idx].crop.left;
168 : ctx->width += ctx->crop_left + ctx->crop_right;
169 : ctx->height += ctx->crop_top + ctx->crop_bottom;
170 : ctx->out_size = ctx->height * ctx->width * 3/2 ;
171 :
172 : if (ctx->avc.sps[idx].vui.par_num && ctx->avc.sps[idx].vui.par_den) {
173 : ctx->sar.num = ctx->avc.sps[idx].vui.par_num;
174 : ctx->sar.den = ctx->avc.sps[idx].vui.par_den;
175 : }
176 : ctx->chroma_format = ctx->avc.sps[idx].chroma_format;
177 : ctx->luma_bit_depth = 8 + ctx->avc.sps[idx].luma_bit_depth_m8;
178 : ctx->chroma_bit_depth = 8 + ctx->avc.sps[idx].chroma_bit_depth_m8;
179 : switch (ctx->chroma_format) {
180 : case 2:
181 : if (ctx->luma_bit_depth>8) {
182 : ctx->pix_fmt = GF_PIXEL_YUV422_10;
183 : } else {
184 : ctx->pix_fmt = GF_PIXEL_YUV422;
185 : }
186 : break;
187 : case 3:
188 : if (ctx->luma_bit_depth>8) {
189 : ctx->pix_fmt = GF_PIXEL_YUV444_10;
190 : } else {
191 : ctx->pix_fmt = GF_PIXEL_YUV444;
192 : }
193 : break;
194 : default:
195 : if (ctx->luma_bit_depth>8) {
196 : ctx->pix_fmt = GF_PIXEL_YUV_10;
197 : }
198 : break;
199 : }
200 : ctx->frame_size_changed = GF_TRUE;
201 : return GF_OK;
202 : }
203 :
204 :
205 : GF_Err mcdec_init_m4vp2_dec(GF_MCDecCtx *ctx)
206 : {
207 : GF_ESD *esd;
208 : GF_M4VDecSpecInfo vcfg;
209 : GF_BitStream *bs;
210 : u8 *dsi_data;
211 : u32 dsi_size;
212 : GF_FilterPid *ipid = gf_list_get(ctx->streams, 0);
213 : const GF_PropertyValue *dcd = gf_filter_pid_get_property(ipid, GF_PROP_PID_DECODER_CONFIG);
214 :
215 : if (!dcd) return GF_NON_COMPLIANT_BITSTREAM;
216 :
217 :
218 : gf_m4v_get_config(dcd->value.data.ptr, dcd->value.data.size, &vcfg);
219 : ctx->width = vcfg.width;
220 : ctx->height = vcfg.height;
221 :
222 : esd = gf_odf_desc_esd_new(2);
223 : esd->decoderConfig->decoderSpecificInfo->data = dcd->value.data.ptr;
224 : esd->decoderConfig->decoderSpecificInfo->dataLength = dcd->value.data.size;
225 :
226 : bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
227 : gf_bs_write_u32(bs, 1);
228 : gf_odf_desc_write_bs((GF_Descriptor *) esd, bs);
229 : gf_bs_get_content(bs, &dsi_data, &dsi_size);
230 : gf_bs_del(bs);
231 :
232 : ctx->mime = "video/mp4v-es";
233 : AMediaFormat_setBuffer(ctx->format, "csd-0", dsi_data, dsi_size);
234 :
235 : gf_free(dsi_data);
236 : gf_odf_desc_del((GF_Descriptor*)esd);
237 : return GF_OK;
238 : }
239 :
240 :
241 : GF_Err mcdec_init_hevc_dec(GF_MCDecCtx *ctx)
242 : {
243 :
244 : s32 idx;
245 :
246 : u32 i;
247 : GF_NALUFFParam *sps = NULL;
248 : GF_NALUFFParam *pps = NULL;
249 : GF_NALUFFParam *vps = NULL;
250 :
251 : for (i=0; i<gf_list_count(ctx->SPSs); i++) {
252 : sps = gf_list_get(ctx->SPSs, i);
253 : if (ctx->active_sps<0) ctx->active_sps = sps->id;
254 :
255 : if (sps->id==ctx->active_sps) break;
256 : sps = NULL;
257 : }
258 : if (!sps) return GF_NON_COMPLIANT_BITSTREAM;
259 : for (i=0; i<gf_list_count(ctx->PPSs); i++) {
260 : pps = gf_list_get(ctx->PPSs, i);
261 : if (ctx->active_pps<0) ctx->active_pps = pps->id;
262 :
263 : if (pps->id==ctx->active_pps) break;
264 : pps = NULL;
265 : }
266 : for (i=0; i<gf_list_count(ctx->VPSs); i++) {
267 : vps = gf_list_get(ctx->VPSs, i);
268 : if (ctx->active_vps<0) ctx->active_vps = vps->id;
269 :
270 : if (vps->id==ctx->active_vps) break;
271 : vps = NULL;
272 : }
273 : if (!vps) return GF_NON_COMPLIANT_BITSTREAM;
274 : ctx->reconfig_needed = GF_FALSE;
275 : ctx->inject_xps = GF_TRUE;
276 :
277 : idx = ctx->active_sps;
278 : ctx->width = ctx->hevc.sps[idx].width;
279 : ctx->height = ctx->hevc.sps[idx].height;
280 : ctx->luma_bpp = ctx->hevc.sps[idx].bit_depth_luma;
281 : ctx->chroma_bpp = ctx->hevc.sps[idx].bit_depth_chroma;
282 : ctx->chroma_format_idc = ctx->hevc.sps[idx].chroma_format_idc;
283 :
284 : ctx->stride = ((ctx->luma_bpp==8) && (ctx->chroma_bpp==8)) ? ctx->width : ctx->width * 2;
285 : if ( ctx->chroma_format_idc == 1) { // 4:2:0
286 : ctx->out_size = ctx->stride * ctx->height * 3 / 2;
287 : }
288 : else if ( ctx->chroma_format_idc == 2) { // 4:2:2
289 : ctx->out_size = ctx->stride * ctx->height * 2 ;
290 : }
291 : else if ( ctx->chroma_format_idc == 3) { // 4:4:4
292 : ctx->out_size = ctx->stride * ctx->height * 3;
293 : }
294 : else {
295 : return GF_NOT_SUPPORTED;
296 : }
297 :
298 : switch (ctx->chroma_format) {
299 : case 2:
300 : if (ctx->luma_bit_depth>8) {
301 : ctx->pix_fmt = GF_PIXEL_YUV422_10;
302 : } else {
303 : ctx->pix_fmt = GF_PIXEL_YUV422;
304 : }
305 : break;
306 : case 3:
307 : if (ctx->luma_bit_depth>8) {
308 : ctx->pix_fmt = GF_PIXEL_YUV444_10;
309 : } else {
310 : ctx->pix_fmt = GF_PIXEL_YUV444;
311 : }
312 : break;
313 : default:
314 : if (ctx->luma_bit_depth>8) {
315 : ctx->pix_fmt = GF_PIXEL_NV12;
316 : }
317 : break;
318 : }
319 :
320 : ctx->frame_size_changed = GF_TRUE;
321 : return GF_OK;
322 : }
323 :
324 :
325 : static GF_Err mcdec_init_decoder(GF_MCDecCtx *ctx) {
326 :
327 : GF_Err err;
328 :
329 : ctx->format = AMediaFormat_new();
330 :
331 : if(!ctx->format) {
332 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaFormat_new failed\n"));
333 : return GF_FILTER_NOT_FOUND;
334 : }
335 :
336 : ctx->sar.num = ctx->sar.den = 0;
337 : ctx->pix_fmt = GF_PIXEL_NV12;
338 :
339 : switch (ctx->codecid) {
340 : case GF_CODECID_AVC :
341 : err = mcdec_init_avc_dec(ctx);
342 : break;
343 : case GF_CODECID_MPEG4_PART2 :
344 : err = mcdec_init_m4vp2_dec(ctx);
345 : break;
346 : case GF_CODECID_HEVC:
347 : err = mcdec_init_hevc_dec(ctx);
348 : break;
349 : default:
350 : return GF_NOT_SUPPORTED;
351 : }
352 :
353 : if (err != GF_OK) {
354 : return err;
355 : }
356 :
357 : ctx->dequeue_timeout = 5000;
358 : ctx->stride = ctx->width;
359 : mcdec_init_media_format(ctx, ctx->format);
360 :
361 : if (!ctx->codec) {
362 : char *decoder_name = mcdec_find_decoder(ctx->mime, ctx->width, ctx->height, &ctx->is_adaptive);
363 : if(!decoder_name) return GF_PROFILE_NOT_SUPPORTED;
364 :
365 : ctx->codec = AMediaCodec_createCodecByName(decoder_name);
366 : gf_free(decoder_name);
367 : }
368 :
369 : if (!ctx->codec) {
370 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaCodec_createDecoderByType failed\n"));
371 : return GF_FILTER_NOT_FOUND;
372 : }
373 :
374 : if (ctx->disable_gl) {
375 : ctx->surface_rendering = 0;
376 : } else if (!ctx->window) {
377 : if(mcdec_create_surface(ctx->tex_id, &ctx->window, &ctx->surface_rendering, &ctx->surfaceTex) != GF_OK)
378 : return GF_BAD_PARAM;
379 : }
380 :
381 : //TODO add support for crypto
382 : if( AMediaCodec_configure(ctx->codec, ctx->format, (ctx->surface_rendering) ? ctx->window : NULL, NULL, 0) != AMEDIA_OK) {
383 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaCodec_configure failed\n"));
384 : return GF_BAD_PARAM;
385 : }
386 :
387 : if( AMediaCodec_start(ctx->codec) != AMEDIA_OK){
388 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC , ("[MCDec] AMediaCodec_start failed\n"));
389 : return GF_BAD_PARAM;
390 : }
391 :
392 : ctx->inputEOS = GF_FALSE;
393 : ctx->outputEOS = GF_FALSE;
394 : GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[MCDec] Video size: %d x %d\n", ctx->width, ctx->height));
395 :
396 :
397 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_WIDTH, &PROP_UINT(ctx->width) );
398 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_HEIGHT, &PROP_UINT(ctx->height) );
399 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STRIDE, &PROP_UINT(ctx->stride) );
400 : if (ctx->sar.den)
401 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAR, &PROP_FRAC(ctx->sar) );
402 :
403 : if (ctx->surface_rendering) {
404 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PIXFMT, &PROP_UINT(GF_PIXEL_GL_EXTERNAL) );
405 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PIXFMT_WRAPPED, &PROP_UINT(ctx->pix_fmt) );
406 : } else {
407 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PIXFMT, &PROP_UINT(ctx->pix_fmt) );
408 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PIXFMT_WRAPPED, NULL );
409 : }
410 :
411 : switch (ctx->codecid) {
412 : case GF_CODECID_AVC:
413 : gf_filter_set_name(ctx->filter, "MediaCodec hardware AVC|H264");
414 : break;
415 : case GF_CODECID_HEVC:
416 : gf_filter_set_name(ctx->filter, "MediaCodec hardware HEVC|H265");
417 : break;
418 : case GF_CODECID_MPEG4_PART2:
419 : gf_filter_set_name(ctx->filter, "MediaCodec hardware MPEG-4 Part2");
420 : break;
421 : default:
422 : gf_filter_set_name(ctx->filter, "MediaCodec unsupported");
423 : break;
424 : }
425 : return GF_OK;
426 : }
427 :
428 : static void mcdec_register_avc_param_set(GF_MCDecCtx *ctx, u8 *data, u32 size, u8 xps)
429 : {
430 : Bool add = GF_TRUE;
431 : u32 i, count;
432 : s32 ps_id;
433 : GF_List *dest = (xps == MCDEC_SPS) ? ctx->SPSs : ctx->PPSs;
434 :
435 : if (xps == MCDEC_SPS) {
436 : ps_id = gf_avc_read_sps(data, size, &ctx->avc, 0, NULL);
437 : if (ps_id<0) return;
438 : }
439 : else {
440 : ps_id = gf_avc_read_pps(data, size, &ctx->avc);
441 : if (ps_id<0) return;
442 : }
443 : count = gf_list_count(dest);
444 : for (i = 0; i<count; i++) {
445 : GF_NALUFFParam *a_slc = gf_list_get(dest, i);
446 : if (a_slc->id != ps_id) continue;
447 : //not same size or different content but same ID, remove old xPS
448 : if ((a_slc->size != size) || memcmp(a_slc->data, data, size)) {
449 : gf_free(a_slc->data);
450 : gf_free(a_slc);
451 : gf_list_rem(dest, i);
452 : break;
453 : }
454 : else {
455 : add = GF_FALSE;
456 : }
457 : break;
458 : }
459 : if (add) {
460 : GF_NALUFFParam *slc;
461 : GF_SAFEALLOC(slc, GF_NALUFFParam);
462 : if (!slc) return;
463 : slc->data = gf_malloc(size);
464 : if (!slc->data) {
465 : gf_free(slc);
466 : return;
467 : }
468 : memcpy(slc->data, data, size);
469 : slc->size = size;
470 : slc->id = ps_id;
471 : gf_list_add(dest, slc);
472 :
473 : //force re-activation of sps/pps
474 : if (xps == MCDEC_SPS) ctx->active_sps = -1;
475 : else ctx->active_pps = -1;
476 : }
477 : }
478 :
479 : static void mcdec_register_hevc_param_set(GF_MCDecCtx *ctx, u8 *data, u32 size, u8 xps)
480 : {
481 : Bool add = GF_TRUE;
482 : u32 i, count;
483 : s32 ps_id;
484 : GF_List *dest = NULL;
485 :
486 : switch(xps) {
487 : case MCDEC_SPS:
488 : dest = ctx->SPSs;
489 : ps_id = gf_hevc_read_sps(data, size, &ctx->hevc);
490 : if (ps_id<0) return;
491 : break;
492 : case MCDEC_PPS:
493 : dest = ctx->PPSs;
494 : ps_id = gf_hevc_read_pps(data, size, &ctx->hevc);
495 : if (ps_id<0) return;
496 : break;
497 : case MCDEC_VPS:
498 : dest = ctx->VPSs;
499 : ps_id = gf_hevc_read_vps(data, size, &ctx->hevc);
500 : if (ps_id<0) return;
501 : break;
502 : default:
503 : break;
504 : }
505 :
506 : count = gf_list_count(dest);
507 : for (i = 0; i<count; i++) {
508 : GF_NALUFFParam *a_slc = gf_list_get(dest, i);
509 : if (a_slc->id != ps_id) continue;
510 : //not same size or different content but same ID, remove old xPS
511 : if ((a_slc->size != size) || memcmp(a_slc->data, data, size)) {
512 : gf_free(a_slc->data);
513 : gf_free(a_slc);
514 : gf_list_rem(dest, i);
515 : break;
516 : }
517 : else {
518 : add = GF_FALSE;
519 : }
520 : break;
521 : }
522 : if (add && dest) {
523 : GF_NALUFFParam *slc;
524 : GF_SAFEALLOC(slc, GF_NALUFFParam);
525 : if (!slc) return;
526 : slc->data = gf_malloc(size);
527 : if (!slc->data) {
528 : gf_free(slc);
529 : return;
530 : }
531 : memcpy(slc->data, data, size);
532 : slc->size = size;
533 : slc->id = ps_id;
534 : gf_list_add(dest, slc);
535 :
536 : //force re-activation of sps/pps/vps
537 : if (xps == MCDEC_SPS) ctx->active_sps = -1;
538 : else if (xps == MCDEC_PPS) ctx->active_pps = -1;
539 : else ctx->active_vps = -1;
540 : }
541 : }
542 :
543 : static GF_Err mcdec_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
544 : {
545 : const GF_PropertyValue *p, *dsi;
546 : const GF_PropertyValue *dcd;
547 : u32 codecid, dsi_crc;
548 : Bool do_reset=GF_FALSE;
549 : u32 i;
550 : GF_FilterPid *base_pid = NULL;
551 : GF_MCDecCtx *ctx = gf_filter_get_udta(filter);
552 :
553 : if (is_remove) {
554 : gf_list_del_item(ctx->streams, pid);
555 : if (!gf_list_count(ctx->streams)) {
556 : if (ctx->codec) AMediaCodec_stop(ctx->codec);
557 : if (ctx->opid) {
558 : gf_filter_pid_remove(ctx->opid);
559 : ctx->opid = NULL;
560 : }
561 : }
562 : return GF_OK;
563 : }
564 : if (! gf_filter_pid_check_caps(pid)) {
565 : return GF_NOT_SUPPORTED;
566 : }
567 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
568 : if (!p) {
569 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] Missing codecid, cannot initialize\n"));
570 : return GF_NOT_SUPPORTED;
571 : }
572 : codecid = p->value.uint;
573 :
574 : base_pid = gf_list_get(ctx->streams, 0);
575 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_DEPENDENCY_ID);
576 : if (!p && base_pid && (base_pid != pid)) return GF_REQUIRES_NEW_INSTANCE;
577 : else if (p) {
578 : u32 base_idx_plus_one = 0;
579 :
580 : if (ctx->codecid != GF_CODECID_HEVC) return GF_REQUIRES_NEW_INSTANCE;
581 :
582 : for (i=0; i<gf_list_count(ctx->streams); i++) {
583 : GF_FilterPid *ipid = gf_list_get(ctx->streams, i);
584 : const GF_PropertyValue *p_dep;
585 : if (ipid==pid) continue;
586 :
587 : p_dep = gf_filter_pid_get_property(ipid, GF_PROP_PID_ID);
588 : if (p_dep && p_dep->value.uint == p->value.uint) {
589 : base_idx_plus_one = i+1;
590 : break;
591 : }
592 : }
593 : if (!base_idx_plus_one) return GF_REQUIRES_NEW_INSTANCE;
594 :
595 : //no support for L-HEVC
596 : if (codecid != GF_CODECID_HEVC) return GF_NOT_SUPPORTED;
597 : if (gf_list_find(ctx->streams, pid) < 0) {
598 : gf_list_insert(ctx->streams, pid, base_idx_plus_one);
599 : }
600 : //no configure for temporal enhancements
601 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_FPS);
602 : if (ctx->opid && p) gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_FPS, p);
603 : return GF_OK;
604 : }
605 :
606 :
607 : dsi = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
608 : dsi_crc = dsi ? gf_crc_32(dsi->value.data.ptr, dsi->value.data.size) : 0;
609 : if ((codecid==ctx->codecid) && (dsi_crc == ctx->cfg_crc)) return GF_OK;
610 :
611 : if (gf_list_find(ctx->streams, pid) < 0) {
612 : gf_list_insert(ctx->streams, pid, 0);
613 : }
614 : ctx->cfg_crc = dsi_crc;
615 :
616 : gf_filter_set_max_extra_input_pids(filter, (codecid==GF_CODECID_HEVC) ? 5 : 0);
617 :
618 : if (!ctx->opid) {
619 : ctx->opid = gf_filter_pid_new(filter);
620 : gf_filter_pid_set_framing_mode(pid, GF_TRUE);
621 : }
622 :
623 : //copy properties at init or reconfig
624 : gf_filter_pid_copy_properties(ctx->opid, pid);
625 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_RAW) );
626 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DECODER_CONFIG, NULL );
627 :
628 : dcd = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
629 : //not ready yet
630 : if (!dcd) return GF_OK;
631 :
632 : if (codecid!=ctx->codecid) do_reset = GF_TRUE;
633 : else if (!ctx->is_adaptive) do_reset = GF_TRUE;
634 : else ctx->inject_xps = GF_TRUE;
635 :
636 : ctx->codecid = codecid;
637 :
638 : if (do_reset && ctx->codec) {
639 : AMediaCodec_delete(ctx->codec);
640 : ctx->codec = NULL;
641 : mcdec_reset_ps_list(ctx->SPSs);
642 : mcdec_reset_ps_list(ctx->VPSs);
643 : mcdec_reset_ps_list(ctx->PPSs);
644 :
645 : if (ctx->format) AMediaFormat_delete(ctx->format);
646 : ctx->format = NULL;
647 : }
648 :
649 : if (!ctx->tex_id)
650 : glGenTextures(1, &ctx->tex_id);
651 :
652 : //check AVC config
653 : if (ctx->codecid == GF_CODECID_AVC) {
654 : GF_AVCConfig *cfg;
655 : GF_NALUFFParam *slc;
656 :
657 : ctx->mime = "video/avc";
658 : ctx->avc.sps_active_idx = -1;
659 : ctx->active_sps = ctx->active_pps = -1;
660 :
661 : cfg = gf_odf_avc_cfg_read(dcd->value.data.ptr, dcd->value.data.size);
662 : for (i = 0; i<gf_list_count(cfg->sequenceParameterSets); i++) {
663 : slc = gf_list_get(cfg->sequenceParameterSets, i);
664 : slc->id = -1;
665 : mcdec_register_avc_param_set(ctx, slc->data, slc->size, MCDEC_SPS);
666 : }
667 :
668 : for (i = 0; i<gf_list_count(cfg->pictureParameterSets); i++) {
669 : slc = gf_list_get(cfg->pictureParameterSets, i);
670 : slc->id = -1;
671 : mcdec_register_avc_param_set(ctx, slc->data, slc->size, MCDEC_PPS);
672 : }
673 : //activate first SPS/PPS by default
674 : slc = gf_list_get(ctx->SPSs, 0);
675 : if (slc) ctx->active_sps = slc->id;
676 :
677 : slc = gf_list_get(ctx->PPSs, 0);
678 : if (slc) ctx->active_pps = slc->id;
679 :
680 : ctx->nalu_size_length = cfg->nal_unit_size;
681 : gf_odf_avc_cfg_del(cfg);
682 : }
683 : else if (codecid == GF_CODECID_MPEG4_PART2) {
684 : GF_M4VDecSpecInfo vcfg;
685 : gf_m4v_get_config(dcd->value.data.ptr, dcd->value.data.size, &vcfg);
686 : ctx->width = vcfg.width;
687 : ctx->height = vcfg.height;
688 : ctx->out_size = ctx->width*ctx->height*3/2;
689 : ctx->pix_fmt = GF_PIXEL_NV12;
690 : }
691 : else if (codecid == GF_CODECID_HEVC) {
692 : ctx->mime = "video/hevc";
693 : GF_HEVCConfig *hvcc;
694 : GF_NALUFFParam *sl;
695 : HEVCState hevc;
696 : u32 j;
697 :
698 : memset(&hevc, 0, sizeof(HEVCState));
699 :
700 : hvcc = gf_odf_hevc_cfg_read(dcd->value.data.ptr, dcd->value.data.size, GF_FALSE);
701 : if (!hvcc) return GF_NON_COMPLIANT_BITSTREAM;
702 : ctx->nalu_size_length = hvcc->nal_unit_size;
703 :
704 : for (i=0; i< gf_list_count(hvcc->param_array); i++) {
705 : GF_NALUFFParamArray *ar = (GF_NALUFFParamArray *)gf_list_get(hvcc->param_array, i);
706 : for (j=0; j< gf_list_count(ar->nalus); j++) {
707 : sl = (GF_NALUFFParam *)gf_list_get(ar->nalus, j);
708 :
709 : if (ar->type==GF_HEVC_NALU_SEQ_PARAM) {
710 : mcdec_register_hevc_param_set(ctx, sl->data, sl->size, MCDEC_SPS);
711 : } else if (ar->type==GF_HEVC_NALU_VID_PARAM) {
712 : mcdec_register_hevc_param_set(ctx, sl->data, sl->size, MCDEC_VPS);
713 : } else if (ar->type==GF_HEVC_NALU_PIC_PARAM) {
714 : mcdec_register_hevc_param_set(ctx, sl->data, sl->size, MCDEC_PPS);
715 : }
716 : }
717 : }
718 : //activate first VPS/SPS/PPS by default
719 : sl = gf_list_get(ctx->VPSs, 0);
720 : if (sl) ctx->active_vps = sl->id;
721 :
722 : sl = gf_list_get(ctx->SPSs, 0);
723 : if (sl) ctx->active_sps = sl->id;
724 :
725 : sl = gf_list_get(ctx->PPSs, 0);
726 : if (sl) ctx->active_pps = sl->id;
727 :
728 : gf_odf_hevc_cfg_del(hvcc);
729 : }
730 : if (ctx->codec) return GF_OK;
731 : return mcdec_init_decoder(ctx);
732 : }
733 :
734 : static void mcdec_write_ps(GF_BitStream *bs, GF_List *ps, s32 active_ps, Bool all)
735 : {
736 : u32 i, count;
737 : if (!all && (active_ps<0)) return;
738 : count = gf_list_count(ps);
739 : for (i=0; i<count; i++) {
740 : GF_NALUFFParam *sl = gf_list_get(ps, i);
741 : if (all || (sl->id==active_ps)) {
742 : gf_bs_write_u32(bs, 1);
743 : gf_bs_write_data(bs, sl->data, sl->size);
744 : if (!all) return;
745 : }
746 : }
747 : }
748 :
749 :
750 : static GF_Err mcdec_rewrite_annex_b(GF_MCDecCtx *ctx, u8 *inBuffer, u32 inBufferLength, u8 **out_buffer, u32 *out_size)
751 : {
752 : u32 i;
753 : u8 *ptr = inBuffer;
754 : u32 nal_size;
755 : GF_Err e = GF_OK;
756 : GF_BitStream *bs = NULL;
757 :
758 : *out_buffer = NULL;
759 : *out_size = 0;
760 :
761 : bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
762 : if (!bs) return GF_OUT_OF_MEM;
763 :
764 : if (ctx->inject_xps) {
765 : ctx->inject_xps = GF_FALSE;
766 : mcdec_write_ps(bs, ctx->VPSs, ctx->active_vps, ctx->is_adaptive);
767 : mcdec_write_ps(bs, ctx->SPSs, ctx->active_sps, ctx->is_adaptive);
768 : mcdec_write_ps(bs, ctx->PPSs, ctx->active_pps, ctx->is_adaptive);
769 : }
770 :
771 : while (inBufferLength) {
772 : nal_size = 0;
773 : for (i = 0; i<ctx->nalu_size_length; i++) {
774 : nal_size = (nal_size << 8) + ((u8)ptr[i]);
775 : }
776 : ptr += ctx->nalu_size_length;
777 :
778 : gf_bs_write_u32(bs, 1);
779 : gf_bs_write_data(bs, ptr, nal_size);
780 :
781 :
782 : ptr += nal_size;
783 :
784 : if (inBufferLength < nal_size + ctx->nalu_size_length) break;
785 : inBufferLength -= nal_size + ctx->nalu_size_length;
786 : }
787 :
788 : gf_bs_get_content(bs, out_buffer, out_size);
789 : gf_bs_del(bs);
790 : return e;
791 : }
792 :
793 : static GF_Err mcdec_check_ps_state(GF_MCDecCtx *ctx, u8 *inBuffer, u32 inBufferLength)
794 : {
795 : u32 nal_size;
796 : GF_Err e = GF_OK;
797 : GF_BitStream *bs = gf_bs_new(inBuffer, inBufferLength, GF_BITSTREAM_READ);
798 :
799 :
800 : while (gf_bs_available(bs)) {
801 : u8 nal_type;
802 : u32 pos;
803 : //turn off epb removal when reading nal size
804 : gf_bs_enable_emulation_byte_removal(bs, GF_FALSE);
805 : nal_size = gf_bs_read_int(bs, ctx->nalu_size_length * 8);
806 : pos = gf_bs_get_position(bs);
807 :
808 : if (ctx->codecid==GF_CODECID_AVC) {
809 : //this will turn it back on
810 : gf_avc_parse_nalu (bs, &ctx->avc);
811 : gf_bs_seek(bs, pos + nal_size);
812 :
813 : nal_type = ctx->avc.last_nal_type_parsed;
814 : switch (nal_type) {
815 : case GF_AVC_NALU_SEQ_PARAM:
816 : case GF_AVC_NALU_PIC_PARAM:
817 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AVC Parameter sets still present in packet payload !\n"));
818 : break;
819 : default:
820 : if ((nal_type <= GF_AVC_NALU_IDR_SLICE) && ctx->avc.s_info.sps) {
821 : if (ctx->avc.sps_active_idx != ctx->active_sps) {
822 : ctx->reconfig_needed = GF_TRUE;
823 : ctx->active_sps = ctx->avc.sps_active_idx;
824 : ctx->active_pps = ctx->avc.s_info.pps->id;
825 : gf_bs_del(bs);
826 : return GF_OK;
827 : }
828 : }
829 : break;
830 : }
831 : } else {
832 : u8 quality_id, temporal_id;
833 : gf_hevc_parse_nalu_bs (bs, &ctx->hevc, &nal_type, &temporal_id, &quality_id);
834 : gf_bs_seek(bs, pos + nal_size);
835 :
836 : switch(nal_type) {
837 : case GF_HEVC_NALU_SEQ_PARAM:
838 : case GF_HEVC_NALU_PIC_PARAM:
839 : case GF_HEVC_NALU_VID_PARAM:
840 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] HEVC Parameter sets still present in packet payload !\n"));
841 : break;
842 : default:
843 : if ((nal_type <= GF_HEVC_NALU_SLICE_CRA) && ctx->hevc.s_info.sps) {
844 : if ((ctx->hevc.sps_active_idx != ctx->active_sps) || (ctx->hevc.sps[ctx->active_sps].vps_id != ctx->active_vps)) {
845 : ctx->reconfig_needed = GF_TRUE;
846 : ctx->active_sps = ctx->hevc.sps_active_idx;
847 : ctx->active_pps = ctx->hevc.s_info.pps->id;
848 : ctx->active_vps = ctx->hevc.sps[ctx->active_sps].vps_id;
849 : return GF_OK;
850 : }
851 : }
852 : break;
853 : }
854 : }
855 : }
856 : gf_bs_del(bs);
857 : return e;
858 : }
859 :
860 : static GF_Err mcdec_send_frame(GF_MCDecCtx *ctx, u8 *frame_buffer, u64 cts);
861 :
862 : static GF_Err mcdec_process(GF_Filter *filter)
863 : {
864 : u64 cts=0;
865 : u8 *in_buffer;
866 : u32 in_buffer_size, i, count, nb_eos;
867 : u64 min_dts;
868 : GF_Err e;
869 : GF_MCDecCtx *ctx = gf_filter_get_udta(filter);
870 : GF_FilterPacket *pck;
871 : GF_FilterPid *ref_pid = NULL;
872 : u8 *dec_frame=NULL;
873 :
874 : Bool mcdec_buffer_available = GF_FALSE;
875 :
876 : #if FILTER_FIXME
877 : if (!ctx->before_exit_registered) {
878 : ctx->before_exit_registered = GF_TRUE;
879 : if (gf_register_before_exit_function(gf_th_current(), &mcdec_exit_callback) != GF_OK) {
880 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] Failed to register exit function for the decoder thread %p, try to continue anyway...\n", gf_th_current()));
881 : }
882 : }
883 : #endif
884 :
885 :
886 : //figure out min DTS
887 : count = gf_list_count(ctx->streams);
888 : nb_eos = 0;
889 : min_dts = 0;
890 : for (i=0; i<count; i++) {
891 : u64 dts;
892 : GF_FilterPid *pid = gf_list_get(ctx->streams, i);
893 :
894 : pck = gf_filter_pid_get_packet(pid);
895 : if (!pck) {
896 : if (gf_filter_pid_is_eos(pid)) {
897 : nb_eos++;
898 : continue;
899 : } else {
900 : return GF_OK;
901 : }
902 : }
903 : dts = gf_filter_pck_get_dts(pck);
904 : dts *= 1000;
905 : dts /= gf_filter_pck_get_timescale(pck);
906 : if (!min_dts || (min_dts>dts)) {
907 : min_dts = dts;
908 : ref_pid = pid;
909 : }
910 : }
911 :
912 : if (nb_eos==count) {
913 : in_buffer = NULL;
914 : in_buffer_size = 0;
915 : } else {
916 : assert(ref_pid);
917 : pck = gf_filter_pid_get_packet(ref_pid);
918 : assert(pck);
919 :
920 : in_buffer = (u8 *) gf_filter_pck_get_data(pck, &in_buffer_size);
921 : cts = gf_filter_pck_get_cts(pck);
922 :
923 : //no reconfig but no adaptive, parse NALUs to figure out active ps
924 : if (!ctx->reconfig_needed && !ctx->is_adaptive) {
925 : mcdec_check_ps_state(ctx, in_buffer, in_buffer_size);
926 : }
927 :
928 : if (ctx->reconfig_needed) {
929 : if (ctx->codec) {
930 : AMediaCodec_flush(ctx->codec);
931 : AMediaCodec_stop(ctx->codec);
932 : }
933 : e = mcdec_init_decoder(ctx);
934 : if (e) {
935 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] Failed to reconfigure decoder: %s\n", gf_error_to_string(e) ));
936 : return e;
937 : }
938 : }
939 : }
940 :
941 : if (!ctx->inputEOS) {
942 : ssize_t inIndex = AMediaCodec_dequeueInputBuffer(ctx->codec, ctx->dequeue_timeout);
943 :
944 : if (inIndex >= 0) {
945 : size_t inSize;
946 : u32 flags = 0;
947 : Bool do_free = GF_TRUE;
948 : u8 *in_data=NULL;
949 : u32 in_data_size=0;
950 : u8 *buffer = (u8 *)AMediaCodec_getInputBuffer(ctx->codec, inIndex, &inSize);
951 :
952 : //rewrite input from isobmf to annexB - this will write the param sets if needed
953 : if (in_buffer) {
954 : mcdec_rewrite_annex_b(ctx, in_buffer, in_buffer_size, &in_data, &in_data_size);
955 :
956 : if (!in_data) {
957 : in_data = in_buffer;
958 : in_data_size = in_buffer_size;
959 : do_free = GF_FALSE;
960 : }
961 : }
962 :
963 : if (in_data_size > inSize) {
964 : GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[MCDec] The returned buffer is too small\n"));
965 : if (do_free) gf_free(in_data);
966 : return GF_OK;
967 : }
968 :
969 : if (in_data_size) {
970 : memcpy(buffer, in_data, in_data_size);
971 : gf_filter_pid_drop_packet(ref_pid);
972 : if (do_free) gf_free(in_data);
973 : } else {
974 : GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[MCDec] AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM input\n"));
975 : ctx->inputEOS = GF_TRUE;
976 : flags = AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM;
977 : }
978 :
979 : if (AMediaCodec_queueInputBuffer(ctx->codec, inIndex, 0, in_data_size, cts, flags) != AMEDIA_OK) {
980 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaCodec_queueInputBuffer failed\n"));
981 : return GF_BAD_PARAM;
982 : }
983 : mcdec_buffer_available = GF_TRUE;
984 : GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[MCDec] AMediaCodec_queueInputBuffer OK, %d bytes queued (in EOS %d)\n", in_data_size, ctx->inputEOS));
985 : }
986 : }
987 :
988 : if (!ctx->outputEOS) {
989 : u32 width, height, stride;
990 : AMediaCodecBufferInfo info;
991 :
992 : ctx->outIndex = AMediaCodec_dequeueOutputBuffer(ctx->codec, &info, ctx->dequeue_timeout);
993 :
994 : switch(ctx->outIndex) {
995 : case AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED:
996 : GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[MCDec] AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED\n"));
997 : ctx->format = AMediaCodec_getOutputFormat(ctx->codec);
998 : AMediaFormat_getInt32(ctx->format, AMEDIAFORMAT_KEY_WIDTH, &width);
999 : AMediaFormat_getInt32(ctx->format, AMEDIAFORMAT_KEY_HEIGHT, &height);
1000 : AMediaFormat_getInt32(ctx->format, AMEDIAFORMAT_KEY_STRIDE, &stride);
1001 : if((ctx->width != width) || (ctx->height != height) || (ctx->stride != stride)){
1002 : ctx->out_size = ctx->stride * ctx->height * 3 / 2;
1003 : ctx->frame_size_changed = GF_TRUE;
1004 : }
1005 : break;
1006 :
1007 : case AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED:
1008 : GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[MCDec] AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED\n"));
1009 : break;
1010 :
1011 : case AMEDIACODEC_INFO_TRY_AGAIN_LATER:
1012 : GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[MCDec] AMEDIACODEC_INFO_TRY_AGAIN_LATER\n"));
1013 : break;
1014 :
1015 : default:
1016 : if (ctx->outIndex < 0)
1017 : break;
1018 :
1019 : dec_frame = NULL;
1020 :
1021 : if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) {
1022 : GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[MCDec] AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM output\n"));
1023 : ctx->outputEOS = GF_TRUE;
1024 : }
1025 :
1026 : if (!ctx->surface_rendering) {
1027 : size_t outSize;
1028 : uint8_t * buffer = AMediaCodec_getOutputBuffer(ctx->codec, ctx->outIndex, &outSize);
1029 : dec_frame = buffer + info.offset;
1030 :
1031 : if (!dec_frame) {
1032 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaCodec_getOutputBuffer failed\n"));
1033 : break;
1034 : }
1035 : }
1036 : GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[MCDec] got output buffer CTS "LLU" (out EOS %d)\n", info.presentationTimeUs, ctx->outputEOS));
1037 :
1038 : e = mcdec_send_frame(ctx, dec_frame, info.presentationTimeUs);
1039 : if (e) return e;
1040 : break;
1041 : }
1042 : }
1043 :
1044 : if (ctx->outputEOS) gf_filter_pid_set_eos(ctx->opid);
1045 : return GF_OK;
1046 : }
1047 :
1048 : static void mcdec_hw_del(GF_Filter *filter, GF_FilterPid *pid, GF_FilterPacket *pck)
1049 : {
1050 : GF_FilterFrameInterface *frame_ifce = (GF_FilterFrameInterface *) gf_filter_pck_get_frame_interface(pck);
1051 : GF_MCDecFrame *f = frame_ifce ? frame_ifce->user_data : NULL;
1052 : if (!f) return;
1053 :
1054 : if (f->ctx->codec && !f->flushed) {
1055 : if ( AMediaCodec_releaseOutputBuffer(f->ctx->codec, f->outIndex, GF_FALSE) != AMEDIA_OK) {
1056 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] NOT Release Output Buffer Index: %d\n", f->outIndex));
1057 : }
1058 : }
1059 : f->ctx->decoded_frames_pending--;
1060 : gf_list_add(f->ctx->frames_res, f);
1061 : }
1062 :
1063 : GF_Err mcdec_hw_get_plane(GF_FilterFrameInterface *frame, u32 plane_idx, const u8 **outPlane, u32 *outStride)
1064 : {
1065 : GF_MCDecFrame *f = (GF_MCDecFrame *)frame->user_data;
1066 : if (! outPlane || !outStride) return GF_BAD_PARAM;
1067 : *outPlane = NULL;
1068 : *outStride = 0;
1069 : f->ctx->format = AMediaCodec_getOutputFormat(f->ctx->codec);
1070 :
1071 : AMediaFormat_getInt32(f->ctx->format, AMEDIAFORMAT_KEY_STRIDE, outStride);
1072 :
1073 : switch(plane_idx) {
1074 : case 0 :
1075 : *outPlane = f->frame ;
1076 : break;
1077 : case 1 :
1078 : *outPlane = f->frame + *outStride * f->ctx->height ;
1079 : *outStride/=2;
1080 : break;
1081 : case 2:
1082 : *outPlane = f->frame + 5 * *outStride * f->ctx->height/4 ;
1083 : *outStride/=2;
1084 : break;
1085 : default :
1086 : return GF_BAD_PARAM;
1087 : }
1088 :
1089 : return GF_OK;
1090 : }
1091 :
1092 : GF_Err mcdec_hw_get_gl_texture(GF_FilterFrameInterface *frame, u32 plane_idx, u32 *gl_tex_format, u32 *gl_tex_id, GF_Matrix * texcoordmatrix)
1093 : {
1094 : GF_MCDecFrame *f = (GF_MCDecFrame *)frame->user_data;
1095 : if (!gl_tex_format || !gl_tex_id) return GF_BAD_PARAM;
1096 : #ifndef MEDIACODEC_EMUL_API
1097 : *gl_tex_format = GL_TEXTURE_EXTERNAL_OES;
1098 : #endif
1099 :
1100 : *gl_tex_id = f->ctx->tex_id;
1101 :
1102 : if(!f->flushed && f->ctx->codec) {
1103 : if (AMediaCodec_releaseOutputBuffer(f->ctx->codec, f->outIndex, GF_TRUE) != AMEDIA_OK) {
1104 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] NOT Release Output Buffer Index: %d to surface\n", f->outIndex));
1105 : return GF_OK;
1106 : }
1107 : if(mcdec_update_surface(f->ctx->surfaceTex) != GF_OK) return GF_BAD_PARAM;
1108 : if(mcdec_get_transform_matrix(texcoordmatrix, f->ctx->surfaceTex) != GF_OK) return GF_BAD_PARAM;
1109 :
1110 : f->flushed = GF_TRUE;
1111 : }
1112 : return GF_OK;
1113 : }
1114 :
1115 : static GF_Err mcdec_send_frame(GF_MCDecCtx *ctx, u8 *frame_buffer, u64 cts)
1116 : {
1117 : GF_MCDecFrame *mc_frame;
1118 : GF_FilterPacket *dst_pck;
1119 :
1120 : if(ctx->outIndex < 0 || (!frame_buffer && !ctx->surface_rendering)) return GF_BAD_PARAM;
1121 :
1122 : mc_frame = gf_list_pop_front(ctx->frames_res);
1123 : if (!mc_frame) {
1124 : GF_SAFEALLOC(mc_frame, GF_MCDecFrame);
1125 : if (!mc_frame) return GF_OUT_OF_MEM;
1126 : }
1127 : memset(&mc_frame->frame_ifce, 0, sizeof(GF_FilterFrameInterface));
1128 : mc_frame->frame_ifce.user_data = mc_frame;
1129 : mc_frame->ctx = ctx;
1130 : mc_frame->frame = frame_buffer;
1131 : mc_frame->outIndex = ctx->outIndex;
1132 : mc_frame->flushed = GF_FALSE;
1133 :
1134 : if (ctx->surface_rendering) {
1135 : mc_frame->frame_ifce.get_gl_texture = mcdec_hw_get_gl_texture;
1136 : } else {
1137 : mc_frame->frame_ifce.get_plane = mcdec_hw_get_plane;
1138 : }
1139 :
1140 : if (ctx->frame_size_changed) {
1141 : mc_frame->frame_ifce.flags = GF_FRAME_IFCE_BLOCKING;
1142 : ctx->frame_size_changed = GF_FALSE;
1143 : }
1144 : ctx->decoded_frames_pending++;
1145 :
1146 :
1147 : dst_pck = gf_filter_pck_new_frame_interface(ctx->opid, &mc_frame->frame_ifce, mcdec_hw_del);
1148 : if (!dst_pck) return GF_OUT_OF_MEM;
1149 :
1150 : if (dst_pck) {
1151 : gf_filter_pck_set_cts(dst_pck, cts);
1152 : //TODO, copy properties from source packet !
1153 :
1154 : gf_filter_pck_send(dst_pck);
1155 : }
1156 :
1157 : return GF_OK;
1158 : }
1159 :
1160 : GF_Err mcdec_initialize(GF_Filter *filter)
1161 : {
1162 : GF_MCDecCtx *ctx = gf_filter_get_udta(filter);
1163 : ctx->filter = filter;
1164 :
1165 : ctx->frames_res = gf_list_new();
1166 : ctx->streams = gf_list_new();
1167 :
1168 : ctx->SPSs = gf_list_new();
1169 : ctx->PPSs = gf_list_new();
1170 : ctx->VPSs = gf_list_new();
1171 :
1172 : ctx->active_vps = -1;
1173 : ctx->active_sps = -1;
1174 : ctx->active_pps = -1;
1175 :
1176 : return GF_OK;
1177 : }
1178 :
1179 : void mcdec_finalize(GF_Filter *filter)
1180 : {
1181 : GF_MCDecCtx *ctx = gf_filter_get_udta(filter);
1182 :
1183 : if (ctx->format && AMediaFormat_delete(ctx->format) != AMEDIA_OK) {
1184 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaFormat_delete failed\n"));
1185 : }
1186 :
1187 : if (ctx->codec && AMediaCodec_delete(ctx->codec) != AMEDIA_OK) {
1188 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MCDec] AMediaCodec_delete failed\n"));
1189 : }
1190 :
1191 : if(ctx->window) {
1192 : ANativeWindow_release(ctx->window);
1193 : ctx->window = NULL;
1194 : }
1195 :
1196 : if (ctx->surfaceTex.texture_id)
1197 : mcdec_delete_surface(ctx->surfaceTex);
1198 :
1199 : if(ctx->tex_id)
1200 : glDeleteTextures (1, &ctx->tex_id);
1201 :
1202 : mcdec_reset_ps_list(ctx->SPSs);
1203 : gf_list_del(ctx->SPSs);
1204 : mcdec_reset_ps_list(ctx->PPSs);
1205 : gf_list_del(ctx->PPSs);
1206 : mcdec_reset_ps_list(ctx->VPSs);
1207 : gf_list_del(ctx->VPSs);
1208 :
1209 : while (gf_list_count(ctx->frames_res) ) {
1210 : GF_MCDecFrame *f = gf_list_pop_back(ctx->frames_res);
1211 : gf_free(f);
1212 : }
1213 : gf_list_del(ctx->frames_res);
1214 : gf_list_del(ctx->streams);
1215 : }
1216 :
1217 : #else
1218 0 : static GF_Err mcdec_process(GF_Filter *filter)
1219 : {
1220 0 : return GF_EOS;
1221 : }
1222 : #endif
1223 :
1224 :
1225 : static const GF_FilterCapability MCDecCaps[] =
1226 : {
1227 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
1228 : CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
1229 : //commented as some devices seem to have issues with this one
1230 : // CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG4_PART2),
1231 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AVC),
1232 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_HEVC),
1233 : CAP_BOOL(GF_CAPS_INPUT_EXCLUDED,GF_PROP_PID_TILE_BASE, GF_TRUE),
1234 :
1235 : CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
1236 : CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
1237 : };
1238 :
1239 : #if defined(GPAC_CONFIG_ANDROID) && defined(GPAC_HAS_MEDIACODEC)
1240 : #define OFFS(_n) #_n, offsetof(GF_MCDecCtx, _n)
1241 : #else
1242 : #define OFFS(_n) #_n, -1
1243 : #endif
1244 :
1245 : static const GF_FilterArgs MCDecArgs[] =
1246 : {
1247 : { OFFS(disable_gl), "disable OpenGL texture transfer", GF_PROP_BOOL, "false", NULL, 0},
1248 : {0}
1249 : };
1250 :
1251 : GF_FilterRegister GF_MCDecCtxRegister = {
1252 : .name = "mcdec",
1253 : GF_FS_SET_DESCRIPTION("MediaCodec decoder")
1254 : GF_FS_SET_HELP("This filter decodes video streams using hardware decoder on android devices")
1255 : .args = MCDecArgs,
1256 : SETCAPS(MCDecCaps),
1257 : #if defined(GPAC_CONFIG_ANDROID) && defined(GPAC_HAS_MEDIACODEC)
1258 : .private_size = sizeof(GF_MCDecCtx),
1259 : .initialize = mcdec_initialize,
1260 : .finalize = mcdec_finalize,
1261 : .configure_pid = mcdec_configure_pid,
1262 : #endif
1263 : .process = mcdec_process,
1264 : };
1265 :
1266 :
1267 2877 : const GF_FilterRegister *mcdec_register(GF_FilterSession *session)
1268 : {
1269 : #ifndef GPAC_CONFIG_ANDROID
1270 2877 : if (!gf_opts_get_bool("temp", "gendoc"))
1271 : return NULL;
1272 14 : GF_MCDecCtxRegister.version = "! Warning: MediaCodec SDK NOT AVAILABLE IN THIS BUILD !";
1273 :
1274 : #ifdef GPAC_ENABLE_COVERAGE
1275 : mcdec_process(NULL);
1276 : #endif
1277 :
1278 : #endif
1279 14 : return &GF_MCDecCtxRegister;
1280 : }
|