LCOV - code coverage report
Current view: top level - filters - dec_mediacodec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 4 6 66.7 %
Date: 2021-04-29 23:48:07 Functions: 1 2 50.0 %

          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             : }

Generated by: LCOV version 1.13