static GF_Err HEVC_AttachStream(GF_BaseDecoder *ifcg, GF_ESD *esd) { GF_SystemRTInfo rti; const char *sOpt; u32 nb_threads = 1; HEVCDec *ctx = (HEVCDec*) ifcg->privateStack; if (gf_sys_get_rti(0, &rti, 0) ) { nb_threads = (rti.nb_cores>1) ? rti.nb_cores-1 : 1; } sOpt = gf_modules_get_option((GF_BaseInterface *)ifcg, "OpenHEVC", "NumThreads"); if (!sOpt) { char szO[100]; sprintf(szO, "%d", nb_threads); gf_modules_set_option((GF_BaseInterface *)ifcg, "OpenHEVC", "NumThreads", szO); ctx->nb_threads = nb_threads; GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[OpenHEVC] Initializing with %d threads\n", ctx->nb_threads)); } else { ctx->nb_threads = atoi(sOpt); if (ctx->nb_threads > nb_threads) { GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[OpenHEVC] Initializing with %d threads but only %d available cores detected on the system\n", ctx->nb_threads, rti.nb_cores)); } } sOpt = gf_modules_get_option((GF_BaseInterface *)ifcg, "OpenHEVC", "ThreadingType"); if (sOpt && !strcmp(sOpt, "wpp")) ctx->threading_type = 2; else if (sOpt && !strcmp(sOpt, "frame+wpp")) ctx->threading_type = 4; else { ctx->threading_type = 1; if (!sOpt) gf_modules_set_option((GF_BaseInterface *)ifcg, "OpenHEVC", "ThreadingType", "frame"); } sOpt = gf_modules_get_option((GF_BaseInterface *)ifcg, "Systems", "Output8bit"); if (!sOpt) gf_modules_set_option((GF_BaseInterface *)ifcg, "Systems", "Output8bit", (ctx->display_bpp>8) ? "no" : "yes"); if (sOpt && !strcmp(sOpt, "yes")) ctx->output_as_8bit = GF_TRUE; sOpt = gf_modules_get_option((GF_BaseInterface *)ifcg, "OpenHEVC", "CBUnits"); if (!sOpt) gf_modules_set_option((GF_BaseInterface *)ifcg, "OpenHEVC", "CBUnits", "4"); if (sOpt) ctx->output_cb_size = atoi(sOpt); if (!ctx->output_cb_size) ctx->output_cb_size = 4; sOpt = gf_modules_get_option((GF_BaseInterface *)ifcg, "OpenHEVC", "PackHFR"); if (sOpt && !strcmp(sOpt, "yes") ) ctx->pack_mode = GF_TRUE; else if (!sOpt) gf_modules_set_option((GF_BaseInterface *)ifcg, "OpenHEVC", "PackHFR", "no"); if (!ctx->raw_out) { sOpt = gf_modules_get_option((GF_BaseInterface *)ifcg, "OpenHEVC", "InputRipFile"); if (sOpt) ctx->raw_out = fopen(sOpt, "wb"); } /*RTP case: configure enhancement now*/ if (esd->dependsOnESID) { HEVC_ConfigurationScalableStream(ctx, esd); return GF_OK; } ctx->esd = esd; return HEVC_ConfigureStream(ctx, esd); }
static GF_Err HEVC_ProcessData(GF_MediaDecoder *ifcg, char *inBuffer, u32 inBufferLength, u16 ES_ID, u32 *CTS, char *outBuffer, u32 *outBufferLength, u8 PaddingBits, u32 mmlevel) { GF_Err e; int got_pic; HEVCDec *ctx = (HEVCDec*) ifcg->privateStack; if (!inBuffer) { if ( libOpenHevcDecode(ctx->openHevcHandle, NULL, 0, 0) ) { return HEVC_flush_picture(ctx, outBuffer, outBufferLength, CTS); } //quick hack, we have an issue with openHEVC resuming after being flushed ... ctx->had_pic = GF_FALSE; libOpenHevcClose(ctx->openHevcHandle); ctx->openHevcHandle = NULL; ctx->is_init = GF_FALSE; HEVC_ConfigureStream(ctx, ctx->esd); return GF_OK; } if (!ES_ID) { *outBufferLength = 0; return GF_OK; } if (*outBufferLength < ctx->out_size) { *outBufferLength = ctx->out_size; return GF_BUFFER_TOO_SMALL; } *outBufferLength = 0; if (ctx->had_pic) { ctx->had_pic = GF_FALSE; return HEVC_flush_picture(ctx, outBuffer, outBufferLength, CTS); } ctx->dec_frames++; got_pic = libOpenHevcDecode(ctx->openHevcHandle, (u8 *) inBuffer, inBufferLength, *CTS); if (ctx->raw_out) fwrite((u8 *) inBuffer, 1, inBufferLength, ctx->raw_out); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[HEVC Decoder] Decode CTS %d - size %d - got pic %d\n", *CTS, inBufferLength, got_pic)); if (got_pic>0) { e = HEVC_flush_picture(ctx, outBuffer, outBufferLength, CTS); if (e) return e; got_pic = 0; } return GF_OK; }
static GF_Err HEVC_SetCapabilities(GF_BaseDecoder *ifcg, GF_CodecCapability capability) { HEVCDec *ctx = (HEVCDec*) ifcg->privateStack; switch (capability.CapCode) { case GF_CODEC_DISPLAY_BPP: ctx->display_bpp = capability.cap.valueInt; return GF_OK; case GF_CODEC_WAIT_RAP: if (ctx->dec_frames) { //quick hack, we have an issue with openHEVC resuming after being flushed ... ctx->had_pic = GF_FALSE; libOpenHevcClose(ctx->openHevcHandle); ctx->openHevcHandle = NULL; ctx->is_init = GF_FALSE; HEVC_ConfigureStream(ctx, ctx->esd); } return GF_OK; case GF_CODEC_MEDIA_SWITCH_QUALITY: if (ctx->nb_layers==1) return GF_OK; /*switch up*/ if (capability.cap.valueInt > 0) { libOpenHevcSetViewLayers(ctx->openHevcHandle, 1); libOpenHevcSetActiveDecoders(ctx->openHevcHandle, 1); } else { libOpenHevcSetViewLayers(ctx->openHevcHandle, 0); libOpenHevcSetActiveDecoders(ctx->openHevcHandle, 0); } return GF_OK; case GF_CODEC_RAW_MEMORY: ctx->direct_output = GF_TRUE; ctx->pack_mode = GF_FALSE; if (ctx->conv_to_8bit && ctx->out_size) ctx->conv_buffer = (char*)gf_realloc(ctx->conv_buffer, sizeof(char)*ctx->out_size); return GF_OK; } /*return unsupported to avoid confusion by the player (like color space changing ...) */ return GF_NOT_SUPPORTED; }