static GF_Err OSVC_AttachStream(GF_BaseDecoder *ifcg, GF_ESD *esd) { u32 i, count; s32 res; OPENSVCFRAME Picture; int Layer[4]; OSVCDec *ctx = (OSVCDec*) ifcg->privateStack; /*todo: we should check base layer of this stream is indeed our base layer*/ if (!ctx->ES_ID) { ctx->ES_ID = esd->ESID; ctx->width = ctx->height = ctx->out_size = 0; if (!esd->dependsOnESID) ctx->baseES_ID = esd->ESID; } if (esd->decoderConfig->decoderSpecificInfo && esd->decoderConfig->decoderSpecificInfo->data) { GF_AVCConfig *cfg = gf_odf_avc_cfg_read(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength); if (!cfg) return GF_NON_COMPLIANT_BITSTREAM; if (!esd->dependsOnESID) { ctx->nalu_size_length = cfg->nal_unit_size; if (SVCDecoder_init(&ctx->codec) == SVC_STATUS_ERROR) return GF_IO_ERR; } /*decode all NALUs*/ count = gf_list_count(cfg->sequenceParameterSets); SetCommandLayer(Layer, 255, 0, &res, 0);//bufindex can be reset without pb for (i=0; i<count; i++) { u32 w=0, h=0, sid; s32 par_n=0, par_d=0; GF_AVCConfigSlot *slc = gf_list_get(cfg->sequenceParameterSets, i); #ifndef GPAC_DISABLE_AV_PARSERS gf_avc_get_sps_info(slc->data, slc->size, &sid, &w, &h, &par_n, &par_d); #endif /*by default use the base layer*/ if (!i) { if ((ctx->width<w) || (ctx->height<h)) { ctx->width = w; ctx->height = h; if ( ((s32)par_n>0) && ((s32)par_d>0) ) ctx->pixel_ar = (par_n<<16) || par_d; } } res = decodeNAL(ctx->codec, (unsigned char *) slc->data, slc->size, &Picture, Layer); if (res<0) { GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[SVC Decoder] Error decoding SPS %d\n", res)); } GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[SVC Decoder] Attach: SPS id=\"%d\" code=\"%d\" size=\"%d\"\n", slc->id, slc->data[0] & 0x1F, slc->size)); } count = gf_list_count(cfg->pictureParameterSets); for (i=0; i<count; i++) { u32 sps_id, pps_id; GF_AVCConfigSlot *slc = gf_list_get(cfg->pictureParameterSets, i); gf_avc_get_pps_info(slc->data, slc->size, &pps_id, &sps_id); res = decodeNAL(ctx->codec, (unsigned char *) slc->data, slc->size, &Picture, Layer); if (res<0) { GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[SVC Decoder] Error decoding PPS %d\n", res)); } GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[SVC Decoder] Attach: PPS id=\"%d\" code=\"%d\" size=\"%d\" sps_id=\"%d\"\n", pps_id, slc->data[0] & 0x1F, slc->size, sps_id)); } ctx->state_found = 1; gf_odf_avc_cfg_del(cfg); } else { if (ctx->nalu_size_length) { return GF_NOT_SUPPORTED; } ctx->nalu_size_length = 0; if (!esd->dependsOnESID) { if (SVCDecoder_init(&ctx->codec) == SVC_STATUS_ERROR) return GF_IO_ERR; } ctx->pixel_ar = (1<<16) || 1; } ctx->stride = ctx->width + 32; ctx->CurrentDqId = ctx->MaxDqId = 0; ctx->out_size = ctx->stride * ctx->height * 3 / 2; return GF_OK; }
static GF_Err OSVC_AttachStream(GF_BaseDecoder *ifcg, GF_ESD *esd) { u32 i, count; s32 res; OPENSVCFRAME Picture; int Layer[4]; OSVCDec *ctx = (OSVCDec*) ifcg->privateStack; /*not supported in this version*/ if (esd->dependsOnESID) return GF_NOT_SUPPORTED; ctx->ES_ID = esd->ESID; ctx->width = ctx->height = ctx->out_size = 0; if (esd->decoderConfig->decoderSpecificInfo && esd->decoderConfig->decoderSpecificInfo->data) { GF_AVCConfig *cfg = gf_odf_avc_cfg_read(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength); if (!cfg) return GF_NON_COMPLIANT_BITSTREAM; ctx->nalu_size_length = cfg->nal_unit_size; if (SVCDecoder_init(&ctx->codec) == SVC_STATUS_ERROR) return GF_IO_ERR; /*decode all NALUs*/ count = gf_list_count(cfg->sequenceParameterSets); SetCommandLayer(Layer, 255, 0, &i, 0);//bufindex can be reset without pb for (i=0; i<count; i++) { u32 w, h, par_n, par_d; GF_AVCConfigSlot *slc = gf_list_get(cfg->sequenceParameterSets, i); gf_avc_get_sps_info(slc->data, slc->size, &slc->id, &w, &h, &par_n, &par_d); /*by default use the base layer*/ if (!i) { if ((ctx->width<w) || (ctx->height<h)) { ctx->width = w; ctx->height = h; if ( ((s32)par_n>0) && ((s32)par_d>0) ) ctx->pixel_ar = (par_n<<16) || par_d; } } res = decodeNAL(ctx->codec, slc->data, slc->size, &Picture, Layer); if (res<0) { GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[SVC Decoder] Error decoding SPS %d\n", res)); } } count = gf_list_count(cfg->pictureParameterSets); for (i=0; i<count; i++) { GF_AVCConfigSlot *slc = gf_list_get(cfg->pictureParameterSets, i); res = decodeNAL(ctx->codec, slc->data, slc->size, &Picture, Layer); if (res<0) { GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[SVC Decoder] Error decoding PPS %d\n", res)); } } gf_odf_avc_cfg_del(cfg); } else { ctx->nalu_size_length = 0; if (SVCDecoder_init(&ctx->codec) == SVC_STATUS_ERROR) return GF_IO_ERR; } ctx->stride = ctx->width + 32; ctx->layer = 0; ctx->CurrDqId = ctx->layer; ctx->out_size = ctx->stride * ctx->height * 3 / 2; return GF_OK; }
static GF_Err OSVC_ProcessData(GF_MediaDecoder *ifcg, char *inBuffer, u32 inBufferLength, u16 ES_ID, u32 *CTS, char *outBuffer, u32 *outBufferLength, u8 PaddingBits, u32 mmlevel) { s32 got_pic; OPENSVCFRAME pic; int Layer[4]; u32 i, nalu_size, sc_size; u8 *ptr; OSVCDec *ctx = (OSVCDec*) ifcg->privateStack; u32 curMaxDqId = ctx->MaxDqId; if (!ES_ID || !ctx->codec) { *outBufferLength = 0; return GF_OK; } if (*outBufferLength < ctx->out_size) { *outBufferLength = ctx->out_size; return GF_BUFFER_TOO_SMALL; } ctx->MaxDqId = GetDqIdMax((unsigned char *) inBuffer, inBufferLength, ctx->nalu_size_length, ctx->DqIdTable, ctx->nalu_size_length ? 1 : 0); if (!ctx->init_layer_set) { //AVC stream in a h264 file if (ctx->MaxDqId == -1) ctx->MaxDqId = 0; ctx->CurrentDqId = ctx->MaxDqId; ctx->init_layer_set = 1; } if (curMaxDqId != ctx->MaxDqId) ctx->CurrentDqId = ctx->MaxDqId; /*decode only current layer*/ SetCommandLayer(Layer, ctx->MaxDqId, ctx->CurrentDqId, &ctx->TemporalCom, ctx->TemporalId); got_pic = 0; nalu_size = 0; ptr = (u8 *) inBuffer; if (!ctx->nalu_size_length) { u32 size; sc_size = 0; size = gf_media_nalu_next_start_code((u8 *) inBuffer, inBufferLength, &sc_size); if (sc_size) { ptr += size+sc_size; assert(inBufferLength >= size+sc_size); inBufferLength -= size+sc_size; } else { /*no annex-B start-code found, discard */ *outBufferLength = 0; return GF_OK; } } while (inBufferLength) { if (ctx->nalu_size_length) { for (i=0; i<ctx->nalu_size_length; i++) { nalu_size = (nalu_size<<8) + ptr[i]; } ptr += ctx->nalu_size_length; } else { u32 sc_size; nalu_size = gf_media_nalu_next_start_code(ptr, inBufferLength, &sc_size); } #ifndef GPAC_DISABLE_LOG switch (ptr[0] & 0x1F) { case GF_AVC_NALU_SEQ_PARAM: case GF_AVC_NALU_SVC_SUBSEQ_PARAM: { u32 sps_id; gf_avc_get_sps_info((char *)ptr, nalu_size, &sps_id, NULL, NULL, NULL, NULL); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[SVC Decoder] ES%d: SPS id=\"%d\" code=\"%d\" size=\"%d\"\n", ES_ID, sps_id, ptr[0] & 0x1F, nalu_size)); } break; case GF_AVC_NALU_PIC_PARAM: { u32 sps_id, pps_id; gf_avc_get_pps_info((char *)ptr, nalu_size, &pps_id, &sps_id); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[SVC Decoder] ES%d: PPS id=\"%d\" code=\"%d\" size=\"%d\" sps_id=\"%d\"\n", ES_ID, pps_id, ptr[0] & 0x1F, nalu_size, sps_id)); } break; default: GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[SVC Decoder] ES%d: NALU code=\"%d\" size=\"%d\"\n", ES_ID, ptr[0] & 0x1F, nalu_size)); } #endif if (!ctx->state_found) { u8 nal_type = (ptr[0] & 0x1F) ; switch (nal_type) { case GF_AVC_NALU_SEQ_PARAM: case GF_AVC_NALU_PIC_PARAM: if (ctx->baseES_ID == ES_ID) ctx->state_found = 1; break; } } if (ctx->state_found) { if (!got_pic) got_pic = decodeNAL(ctx->codec, ptr, nalu_size, &pic, Layer); else decodeNAL(ctx->codec, ptr, nalu_size, &pic, Layer); } ptr += nalu_size; if (ctx->nalu_size_length) { if (inBufferLength < nalu_size + ctx->nalu_size_length) break; inBufferLength -= nalu_size + ctx->nalu_size_length; } else { if (!sc_size || (inBufferLength < nalu_size + sc_size)) break; inBufferLength -= nalu_size + sc_size; ptr += sc_size; } } if (got_pic!=1) { *outBufferLength = 0; return GF_OK; } if ((curMaxDqId != ctx->MaxDqId) || (pic.Width != ctx->width) || (pic.Height!=ctx->height)) { GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[SVC Decoder] Resizing from %dx%d to %dx%d\n", ctx->width, ctx->height, pic.Width, pic.Height )); ctx->width = pic.Width; ctx->stride = pic.Width + 32; ctx->height = pic.Height; ctx->out_size = ctx->stride * ctx->height * 3 / 2; /*always force layer resize*/ *outBufferLength = ctx->out_size; return GF_BUFFER_TOO_SMALL; } *outBufferLength = ctx->out_size; memcpy(outBuffer, pic.pY[0], ctx->stride*ctx->height); memcpy(outBuffer + ctx->stride * ctx->height, pic.pU[0], ctx->stride*ctx->height/4); memcpy(outBuffer + 5*ctx->stride * ctx->height/4, pic.pV[0], ctx->stride*ctx->height/4); return GF_OK; }
static GF_Err OSVC_ProcessData(GF_MediaDecoder *ifcg, char *inBuffer, u32 inBufferLength, u16 ES_ID, char *outBuffer, u32 *outBufferLength, u8 PaddingBits, u32 mmlevel) { s32 got_pic; OPENSVCFRAME pic; int Layer[4]; OSVCDec *ctx = (OSVCDec*) ifcg->privateStack; if (!ES_ID || (ES_ID!=ctx->ES_ID) || !ctx->codec) { *outBufferLength = 0; return GF_OK; } if (*outBufferLength < ctx->out_size) { *outBufferLength = ctx->out_size; return GF_BUFFER_TOO_SMALL; } got_pic = 0; if (ctx->nalu_size_length) { u32 i, nalu_size = 0; u8 *ptr = inBuffer; ctx->MaxDqId = GetDqIdMax(inBuffer, inBufferLength, ctx->nalu_size_length, ctx->DqIdTable, 1); if(!ctx->InitParseAU){ if (ctx->MaxDqId == -1) { //AVC stream in a h264 file ctx->MaxDqId = 0; } else { //Firts time only, we parse the first AU to know the file configuration //does not need to ba called again ever after, unless SPS or PPS changed ParseAuPlayers(ctx->codec, inBuffer, inBufferLength, ctx->nalu_size_length, 1); } ctx->InitParseAU = 1; } SetCommandLayer(Layer, ctx->MaxDqId, ctx->CurrDqId, &ctx->TemporalCom, ctx->TemporalId); while (inBufferLength) { for (i=0; i<ctx->nalu_size_length; i++) { nalu_size = (nalu_size<<8) + ptr[i]; } ptr += ctx->nalu_size_length; if (!got_pic) got_pic = decodeNAL(ctx->codec, ptr, nalu_size, &pic, Layer); else decodeNAL(ctx->codec, ptr, nalu_size, &pic, Layer); ptr += nalu_size; if (inBufferLength < nalu_size + ctx->nalu_size_length) break; inBufferLength -= nalu_size + ctx->nalu_size_length; } } else { } if (got_pic!=1) return GF_OK; if ((pic.Width != ctx->width) || (pic.Height!=ctx->height)) { ctx->width = pic.Width; ctx->stride = pic.Width + 32; ctx->height = pic.Height; ctx->out_size = ctx->stride * ctx->height * 3 / 2; /*always force layer resize*/ *outBufferLength = ctx->out_size; return GF_BUFFER_TOO_SMALL; } *outBufferLength = ctx->out_size; memcpy(outBuffer, pic.pY[0], ctx->stride*ctx->height); memcpy(outBuffer + ctx->stride * ctx->height, pic.pU[0], ctx->stride*ctx->height/4); memcpy(outBuffer + 5*ctx->stride * ctx->height/4, pic.pV[0], ctx->stride*ctx->height/4); return GF_OK; }