static GF_Err MCDec_ProcessData(GF_MediaDecoder *ifcg, char *inBuffer, u32 inBufferLength, u16 ES_ID, u32 *CTS, char *outBuffer, u32 *outBufferLength, u8 PaddingBits, u32 mmlevel) { MCDec *ctx = (MCDec *)ifcg->privateStack; ctx->nalu_size_length = 0; Bool mcdec_buffer_available = GF_FALSE; if (!ctx->reconfig_needed) MCDec_ParseNALs(ctx, inBuffer, inBufferLength, NULL, NULL); if (ctx->reconfig_needed) { if (ctx->raw_frame_dispatch && ctx->decoded_frames_pending) { *outBufferLength = 1; return GF_BUFFER_TOO_SMALL; } if (ctx->codec) { AMediaCodec_flush(ctx->codec); AMediaCodec_stop(ctx->codec); AMediaCodec_delete(ctx->codec); ctx->codec = NULL; } MCDec_InitDecoder(ctx); if (ctx->out_size != *outBufferLength) { *outBufferLength = ctx->out_size; return GF_BUFFER_TOO_SMALL; } } if(!ctx->inputEOS) { ssize_t inIndex = AMediaCodec_dequeueInputBuffer(ctx->codec,ctx->dequeue_timeout); if (inIndex >= 0) { size_t inSize; char *buffer = (char *)AMediaCodec_getInputBuffer(ctx->codec, inIndex, &inSize); if (inBufferLength > inSize) { GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC,("The returned buffer is too small")); return GF_BUFFER_TOO_SMALL; } switch (ctx->esd->decoderConfig->objectTypeIndication) { case GPAC_OTI_VIDEO_AVC: memcpy(buffer, inBuffer, inBufferLength); break; case GPAC_OTI_VIDEO_HEVC: if(inBuffer[4] == 0x40) { //check for vps u32 start = ctx->vps_size + ctx->sps_size + ctx->pps_size; u32 i; for (i = start; i < inBufferLength ; ++i) { buffer[i - start] = inBuffer[i]; } buffer[0] = 0x00; buffer[1] = 0x00; buffer[2] = 0x00; buffer[3] = 0x01; } else { memcpy(buffer, inBuffer, inBufferLength); } break; default: memcpy(buffer, inBuffer, inBufferLength); break; } if(!inBuffer || inBufferLength == 0){ GF_LOG(GF_LOG_INFO, GF_LOG_CODEC,("AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM input")); ctx->inputEOS = GF_TRUE; } if(AMediaCodec_queueInputBuffer(ctx->codec, inIndex, 0, inBufferLength, *CTS, inBuffer ? 0 : AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM ) != AMEDIA_OK) { GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC,("AMediaCodec_queueInputBuffer failed")); return GF_BAD_PARAM; } mcdec_buffer_available = GF_TRUE; } } if(!ctx->outputEOS) { ctx->outIndex = AMediaCodec_dequeueOutputBuffer(ctx->codec, &ctx->info, ctx->dequeue_timeout); *outBufferLength=0; switch(ctx->outIndex) { case AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED: GF_LOG(GF_LOG_INFO, GF_LOG_CODEC,("AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED")); ctx->format = AMediaCodec_getOutputFormat(ctx->codec); break; case AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED: GF_LOG(GF_LOG_INFO, GF_LOG_CODEC,("AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED")); break; case AMEDIACODEC_INFO_TRY_AGAIN_LATER: GF_LOG(GF_LOG_INFO, GF_LOG_CODEC,("AMEDIACODEC_INFO_TRY_AGAIN_LATER")); break; default: if (ctx->outIndex >= 0) { *CTS = ctx->info.presentationTimeUs; if(ctx->info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) { GF_LOG(GF_LOG_INFO, GF_LOG_CODEC,("AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM output")); ctx->outputEOS = true; } if(!ctx->surface_rendering) { size_t outSize; uint8_t * buffer = AMediaCodec_getOutputBuffer(ctx->codec, ctx->outIndex, &outSize); ctx->frame = buffer + ctx->info.offset; if(!ctx->frame) { GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC,("AMediaCodec_getOutputBuffer failed")); *outBufferLength = 0; } } if(ctx->surface_rendering || ctx->frame) { if(ctx->info.size < ctx->out_size) *outBufferLength = ctx->info.size; else *outBufferLength = ctx->out_size; } } break; } } return (mcdec_buffer_available) ? GF_OK : GF_CODEC_BUFFER_UNAVAILABLE; }
static void enc_uninit(MSFilter *f){ EncData *d=(EncData*)f->data; AMediaCodec_stop(d->codec); AMediaCodec_delete(d->codec); ms_free(d); }