Exemplo n.º 1
0
GF_Err MCDec_InitHevcDecoder(MCDec *ctx) 
{
    u32 i, j;
    GF_HEVCConfig *cfg = NULL;

    ctx->ES_ID = ctx->esd->ESID;
    ctx->width = ctx->height = ctx->out_size = ctx->luma_bpp = ctx->chroma_bpp = ctx->chroma_format_idc = 0;

    if (ctx->esd->decoderConfig->decoderSpecificInfo && ctx->esd->decoderConfig->decoderSpecificInfo->data) {
        HEVCState hevc;
        memset(&hevc, 0, sizeof(HEVCState));

        cfg = gf_odf_hevc_cfg_read(ctx->esd->decoderConfig->decoderSpecificInfo->data, ctx->esd->decoderConfig->decoderSpecificInfo->dataLength, GF_FALSE);
        if (!cfg) return GF_NON_COMPLIANT_BITSTREAM;
        ctx->nalu_size_length = cfg->nal_unit_size;

        for (i=0; i< gf_list_count(cfg->param_array); i++) {
            GF_HEVCParamArray *ar = (GF_HEVCParamArray *)gf_list_get(cfg->param_array, i);
            for (j=0; j< gf_list_count(ar->nalus); j++) {
                GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(ar->nalus, j);
                s32 idx;
                u16 hdr = sl->data[0] << 8 | sl->data[1];

                if (ar->type==GF_HEVC_NALU_SEQ_PARAM) {
                    idx = gf_media_hevc_read_sps(sl->data, sl->size, &hevc);
                    ctx->width = MAX(hevc.sps[idx].width, ctx->width);
                    ctx->height = MAX(hevc.sps[idx].height, ctx->height);
                    ctx->luma_bpp = MAX(hevc.sps[idx].bit_depth_luma, ctx->luma_bpp);
                    ctx->chroma_bpp = MAX(hevc.sps[idx].bit_depth_chroma, ctx->chroma_bpp);
                    ctx->chroma_format_idc  = hevc.sps[idx].chroma_format_idc;

                    ctx->sps = (char *) malloc(4 + sl->size);
                    ctx->sps_size = sl->size;
                    prependStartCode(sl->data, ctx->sps, &ctx->sps_size);
                }
                else if (ar->type==GF_HEVC_NALU_VID_PARAM) {
                    gf_media_hevc_read_vps(sl->data, sl->size, &hevc);

                    ctx->vps = (char *) malloc(4 + sl->size);
                    ctx->vps_size = sl->size;
                    prependStartCode(sl->data, ctx->vps, &ctx->vps_size);
                }
                else if (ar->type==GF_HEVC_NALU_PIC_PARAM) {
                    gf_media_hevc_read_pps(sl->data, sl->size, &hevc);

                    ctx->pps = (char *) malloc(4 + sl->size);
                    ctx->pps_size = sl->size;
                    prependStartCode(sl->data, ctx->pps, &ctx->pps_size);          
                }
            }
        }
        gf_odf_hevc_cfg_del(cfg);
    } else {
        ctx->nalu_size_length = 0;
    }

    ctx->stride = ((ctx->luma_bpp==8) && (ctx->chroma_bpp==8)) ? ctx->width : ctx->width * 2;
    if ( ctx->chroma_format_idc  == 1) { // 4:2:0
        ctx->out_size = ctx->stride * ctx->height * 3 / 2;
    }
    else if ( ctx->chroma_format_idc  == 2) { // 4:2:2
        ctx->out_size = ctx->stride * ctx->height * 2 ;
    }
    else if ( ctx->chroma_format_idc  == 3) { // 4:4:4
        ctx->out_size = ctx->stride * ctx->height * 3;
    }
    else {
        return GF_NOT_SUPPORTED;
    }
    
    ctx->mime = "video/hevc";
    
    u32 csd0_size = ctx->sps_size + ctx-> pps_size + ctx->vps_size;
    char *csd0 = (char *) malloc(csd0_size);

    u32 k;

    for(k = 0; k < csd0_size; k++) {

       if(k < ctx->vps_size) {
            csd0[k] = ctx->vps[k];
       }
       else if (k < ctx-> vps_size + ctx->sps_size ) {
            csd0[k] = ctx->sps[k - ctx->vps_size];
       }
       else csd0[k] = ctx->pps[k - ctx->vps_size - ctx->sps_size];
    }

    AMediaFormat_setBuffer(ctx->format, "csd-0", csd0, csd0_size);
    return GF_OK;
}
Exemplo n.º 2
0
static GF_Err HEVC_ConfigureStream(HEVCDec *ctx, GF_ESD *esd)
{
	u32 i, j;
	GF_HEVCConfig *cfg = NULL;
	ctx->ES_ID = esd->ESID;
	ctx->width = ctx->height = ctx->out_size = ctx->luma_bpp = ctx->chroma_bpp = ctx->chroma_format_idc = 0;

	ctx->nb_layers = 1;

	if (esd->decoderConfig->decoderSpecificInfo && esd->decoderConfig->decoderSpecificInfo->data) {
		HEVCState hevc;
		memset(&hevc, 0, sizeof(HEVCState));

		cfg = gf_odf_hevc_cfg_read(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, GF_FALSE);
		if (!cfg) return GF_NON_COMPLIANT_BITSTREAM;
		ctx->nalu_size_length = cfg->nal_unit_size;

		for (i=0; i< gf_list_count(cfg->param_array); i++) {
			GF_HEVCParamArray *ar = (GF_HEVCParamArray *)gf_list_get(cfg->param_array, i);
			for (j=0; j< gf_list_count(ar->nalus); j++) {
				GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(ar->nalus, j);
				s32 idx;
				u16 hdr = sl->data[0] << 8 | sl->data[1];

				if (ar->type==GF_HEVC_NALU_SEQ_PARAM) {
					idx = gf_media_hevc_read_sps(sl->data, sl->size, &hevc);
					ctx->width = MAX(hevc.sps[idx].width, ctx->width);
					ctx->height = MAX(hevc.sps[idx].height, ctx->height);
					ctx->luma_bpp = MAX(hevc.sps[idx].bit_depth_luma, ctx->luma_bpp);
					ctx->chroma_bpp = MAX(hevc.sps[idx].bit_depth_chroma, ctx->chroma_bpp);
					ctx->chroma_format_idc  = hevc.sps[idx].chroma_format_idc;
					
					if (hdr & 0x1f8) {
						ctx->nb_layers ++;
					}
				}
				else if (ar->type==GF_HEVC_NALU_VID_PARAM) {
					gf_media_hevc_read_vps(sl->data, sl->size, &hevc);
				}
				else if (ar->type==GF_HEVC_NALU_PIC_PARAM) {
					gf_media_hevc_read_pps(sl->data, sl->size, &hevc);
				}
			}
		}
		gf_odf_hevc_cfg_del(cfg);
	} else {
		ctx->nalu_size_length = 0;
	}

	ctx->openHevcHandle = libOpenHevcInit(ctx->nb_threads, ctx->threading_type);

#ifndef GPAC_DISABLE_LOG
	if (gf_log_tool_level_on(GF_LOG_CODEC, GF_LOG_DEBUG) ) {
		libOpenHevcSetDebugMode(ctx->openHevcHandle, 1);
	}
#endif


	if (esd->decoderConfig && esd->decoderConfig->decoderSpecificInfo && esd->decoderConfig->decoderSpecificInfo->data) {
		libOpenHevcSetActiveDecoders(ctx->openHevcHandle, 1/*ctx->nb_layers*/);
		libOpenHevcSetViewLayers(ctx->openHevcHandle, ctx->nb_layers-1);

		libOpenHevcCopyExtraData(ctx->openHevcHandle, (u8 *) esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength);
	} else {
		//hardcoded values: 2 layers max, display layer 0
		libOpenHevcSetActiveDecoders(ctx->openHevcHandle, 1/*ctx->nb_layers*/);
		libOpenHevcSetViewLayers(ctx->openHevcHandle, 0/*ctx->nb_layers-1*/);
	}

	libOpenHevcStartDecoder(ctx->openHevcHandle);


	ctx->stride = ((ctx->luma_bpp==8) && (ctx->chroma_bpp==8)) ? ctx->width : ctx->width * 2;
	if ( ctx->chroma_format_idc  == 1) { // 4:2:0
		ctx->out_size = ctx->stride * ctx->height * 3 / 2;
	}
	else if ( ctx->chroma_format_idc  == 2) { // 4:2:2
		ctx->out_size = ctx->stride * ctx->height * 2 ;
	}
	else if ( ctx->chroma_format_idc  == 3) { // 4:4:4
		ctx->out_size = ctx->stride * ctx->height * 3;
	}
	else {
		return GF_NOT_SUPPORTED;
	}
	
   
   
	if (ctx->output_as_8bit && (ctx->stride>ctx->width)) {
		ctx->stride /=2;
		ctx->out_size /= 2;
		ctx->chroma_bpp = ctx->luma_bpp = 8;
		ctx->conv_to_8bit = GF_TRUE;
		ctx->pack_mode = GF_FALSE;
	}
	ctx->dec_frames = 0;
	return GF_OK;
}
Exemplo n.º 3
0
/**
 * A function which takes FFmpeg H265 extradata (SPS/PPS) and bring them ready to be pushed to the MP4 muxer.
 * @param extradata
 * @param extradata_size
 * @param dstcfg
 * @returns GF_OK is the extradata was parsed and is valid, other values otherwise.
 */
static GF_Err hevc_import_ffextradata(const u8 *extradata, const u64 extradata_size, GF_HEVCConfig *dst_cfg)
{
#ifdef GPAC_DISABLE_AV_PARSERS
	return GF_OK;
#else
	HEVCState hevc;
	GF_HEVCParamArray *vpss = NULL, *spss = NULL, *ppss = NULL;
	GF_BitStream *bs;
	char *buffer = NULL;
	u32 buffer_size = 0;
	if (!extradata || (extradata_size < sizeof(u32)))
		return GF_BAD_PARAM;
	bs = gf_bs_new(extradata, extradata_size, GF_BITSTREAM_READ);
	if (!bs)
		return GF_BAD_PARAM;

	memset(&hevc, 0, sizeof(HEVCState));
	hevc.sps_active_idx = -1;

	while (gf_bs_available(bs)) {
		s32 idx;
		GF_AVCConfigSlot *slc;
		u8 nal_unit_type, temporal_id, layer_id;
		u64 nal_start;
		u32 nal_size;

		if (gf_bs_read_u32(bs) != 0x00000001) {
			gf_bs_del(bs);
			return GF_BAD_PARAM;
		}
		nal_start = gf_bs_get_position(bs);
		nal_size = gf_media_nalu_next_start_code_bs(bs);
		if (nal_start + nal_size > extradata_size) {
			gf_bs_del(bs);
			return GF_BAD_PARAM;
		}

		if (nal_size > buffer_size) {
			buffer = (char*)gf_realloc(buffer, nal_size);
			buffer_size = nal_size;
		}
		gf_bs_read_data(bs, buffer, nal_size);
		gf_bs_seek(bs, nal_start);

		gf_media_hevc_parse_nalu(bs, &hevc, &nal_unit_type, &temporal_id, &layer_id);
		if (layer_id) {
			gf_bs_del(bs);
			gf_free(buffer);
			return GF_BAD_PARAM;
		}

		switch (nal_unit_type) {
		case GF_HEVC_NALU_VID_PARAM:
			idx = gf_media_hevc_read_vps(buffer, nal_size , &hevc);
			if (idx < 0) {
				gf_bs_del(bs);
				gf_free(buffer);
				return GF_BAD_PARAM;
			}

			assert(hevc.vps[idx].state == 1); //we don't expect multiple VPS
			if (hevc.vps[idx].state == 1) {
				hevc.vps[idx].state = 2;
				hevc.vps[idx].crc = gf_crc_32(buffer, nal_size);

				dst_cfg->avgFrameRate = hevc.vps[idx].rates[0].avg_pic_rate;
				dst_cfg->constantFrameRate = hevc.vps[idx].rates[0].constand_pic_rate_idc;
				dst_cfg->numTemporalLayers = hevc.vps[idx].max_sub_layers;
				dst_cfg->temporalIdNested = hevc.vps[idx].temporal_id_nesting;

				if (!vpss) {
					GF_SAFEALLOC(vpss, GF_HEVCParamArray);
					vpss->nalus = gf_list_new();
					gf_list_add(dst_cfg->param_array, vpss);
					vpss->array_completeness = 1;
					vpss->type = GF_HEVC_NALU_VID_PARAM;
				}

				slc = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot));
				slc->size = nal_size;
				slc->id = idx;
				slc->data = (char*)gf_malloc(sizeof(char)*slc->size);
				memcpy(slc->data, buffer, sizeof(char)*slc->size);

				gf_list_add(vpss->nalus, slc);
			}
			break;
		case GF_HEVC_NALU_SEQ_PARAM:
			idx = gf_media_hevc_read_sps(buffer, nal_size, &hevc);
			if (idx < 0) {
				gf_bs_del(bs);
				gf_free(buffer);
				return GF_BAD_PARAM;
			}

			assert(!(hevc.sps[idx].state & AVC_SPS_DECLARED)); //we don't expect multiple SPS
			if ((hevc.sps[idx].state & AVC_SPS_PARSED) && !(hevc.sps[idx].state & AVC_SPS_DECLARED)) {
				hevc.sps[idx].state |= AVC_SPS_DECLARED;
				hevc.sps[idx].crc = gf_crc_32(buffer, nal_size);
			}

			dst_cfg->configurationVersion = 1;
			dst_cfg->profile_space = hevc.sps[idx].ptl.profile_space;
			dst_cfg->tier_flag = hevc.sps[idx].ptl.tier_flag;
			dst_cfg->profile_idc = hevc.sps[idx].ptl.profile_idc;
			dst_cfg->general_profile_compatibility_flags = hevc.sps[idx].ptl.profile_compatibility_flag;
			dst_cfg->progressive_source_flag = hevc.sps[idx].ptl.general_progressive_source_flag;
			dst_cfg->interlaced_source_flag = hevc.sps[idx].ptl.general_interlaced_source_flag;
			dst_cfg->non_packed_constraint_flag = hevc.sps[idx].ptl.general_non_packed_constraint_flag;
			dst_cfg->frame_only_constraint_flag = hevc.sps[idx].ptl.general_frame_only_constraint_flag;

			dst_cfg->constraint_indicator_flags = hevc.sps[idx].ptl.general_reserved_44bits;
			dst_cfg->level_idc = hevc.sps[idx].ptl.level_idc;

			dst_cfg->chromaFormat = hevc.sps[idx].chroma_format_idc;
			dst_cfg->luma_bit_depth = hevc.sps[idx].bit_depth_luma;
			dst_cfg->chroma_bit_depth = hevc.sps[idx].bit_depth_chroma;

			if (!spss) {
				GF_SAFEALLOC(spss, GF_HEVCParamArray);
				spss->nalus = gf_list_new();
				gf_list_add(dst_cfg->param_array, spss);
				spss->array_completeness = 1;
				spss->type = GF_HEVC_NALU_SEQ_PARAM;
			}

			slc = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot));
			slc->size = nal_size;
			slc->id = idx;
			slc->data = (char*)gf_malloc(sizeof(char)*slc->size);
			memcpy(slc->data, buffer, sizeof(char)*slc->size);
			gf_list_add(spss->nalus, slc);
			break;
		case GF_HEVC_NALU_PIC_PARAM:
			idx = gf_media_hevc_read_pps(buffer, nal_size, &hevc);
			if (idx < 0) {
				gf_bs_del(bs);
				gf_free(buffer);
				return GF_BAD_PARAM;
			}

			assert(hevc.pps[idx].state == 1); //we don't expect multiple PPS
			if (hevc.pps[idx].state == 1) {
				hevc.pps[idx].state = 2;
				hevc.pps[idx].crc = gf_crc_32(buffer, nal_size);

				if (!ppss) {
					GF_SAFEALLOC(ppss, GF_HEVCParamArray);
					ppss->nalus = gf_list_new();
					gf_list_add(dst_cfg->param_array, ppss);
					ppss->array_completeness = 1;
					ppss->type = GF_HEVC_NALU_PIC_PARAM;
				}

				slc = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot));
				slc->size = nal_size;
				slc->id = idx;
				slc->data = (char*)gf_malloc(sizeof(char)*slc->size);
				memcpy(slc->data, buffer, sizeof(char)*slc->size);

				gf_list_add(ppss->nalus, slc);
			}
			break;
		default:
			break;
		}

		if (gf_bs_seek(bs, nal_start+nal_size)) {
			assert(nal_start+nal_size <= gf_bs_get_size(bs));
			break;
		}
	}

	gf_bs_del(bs);
	gf_free(buffer);

	return GF_OK;
#endif
}