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