void DeleteXVIDDec(GF_BaseDecoder *ifcg) { XVIDCTX(); if (ctx->codec) CloseCodec(ctx->codec); gf_free(ctx); gf_free(ifcg); }
void DeleteXVIDDec(GF_BaseDecoder *ifcg) { XVIDCTX(); if (ctx->base_codec) xvid_decore(ctx->base_codec, XVID_DEC_DESTROY, NULL, NULL); if (ctx->depth_codec) xvid_decore(ctx->depth_codec, XVID_DEC_DESTROY, NULL, NULL); gf_free(ctx); gf_free(ifcg); }
static GF_Err XVID_GetCapabilities(GF_BaseDecoder *ifcg, GF_CodecCapability *capability) { XVIDCTX(); switch (capability->CapCode) { case GF_CODEC_RESILIENT: capability->cap.valueInt = 1; break; case GF_CODEC_WIDTH: capability->cap.valueInt = ctx->width; break; case GF_CODEC_HEIGHT: capability->cap.valueInt = ctx->height; break; case GF_CODEC_STRIDE: capability->cap.valueInt = ctx->width; break; case GF_CODEC_FPS: capability->cap.valueFloat = ctx->FPS; break; case GF_CODEC_PAR: capability->cap.valueInt = ctx->pixel_ar; break; case GF_CODEC_OUTPUT_SIZE: capability->cap.valueInt = ctx->out_size; break; case GF_CODEC_PIXEL_FORMAT: capability->cap.valueInt = ctx->depth_codec ? GF_PIXEL_YUVD : GF_PIXEL_YV12; break; case GF_CODEC_BUFFER_MIN: capability->cap.valueInt = 1; break; case GF_CODEC_BUFFER_MAX: capability->cap.valueInt = 4; break; /*by default we use 4 bytes padding (otherwise it happens that XviD crashes on some videos...)*/ case GF_CODEC_PADDING_BYTES: capability->cap.valueInt = 32; break; /*XviD performs frame reordering internally*/ case GF_CODEC_REORDER: capability->cap.valueInt = 1; break; case GF_CODEC_WANTS_THREAD: { const char *sOpt = gf_modules_get_option((GF_BaseInterface *)ifcg, "XviD", "Threaded"); capability->cap.valueInt = (sOpt && stricmp(sOpt, "yes")) ? 1 : 0; } break; /*not known at our level...*/ case GF_CODEC_CU_DURATION: default: capability->cap.valueInt = 0; break; } return GF_OK; }
static GF_Err XVID_ProcessData(GF_MediaDecoder *ifcg, char *inBuffer, u32 inBufferLength, u16 ES_ID, char *outBuffer, u32 *outBufferLength, u8 PaddingBits, u32 mmlevel) { unsigned char *pY, *pU, *pV; u32 i, uv_w, half_h; unsigned long pitch; XVIDCTX(); /*check not using scalabilty*/ if (ES_ID != ctx->ES_ID) return GF_BAD_PARAM; if (*outBufferLength < ctx->out_size) { *outBufferLength = ctx->out_size; return GF_BUFFER_TOO_SMALL; } if (!DecodeFrame(ctx->codec, inBuffer, inBufferLength, pY, pU, pV, pitch)) { *outBufferLength = 0; return GF_NON_COMPLIANT_BITSTREAM; } /*dispatch nothing if seeking or droping*/ switch (mmlevel) { case GF_CODEC_LEVEL_SEEK: case GF_CODEC_LEVEL_DROP: *outBufferLength = 0; return GF_OK; default: break; } *outBufferLength = ctx->out_size; for (i=0; i<ctx->height; i++) { unsigned char *src = pY + pitch*i; char *dst = outBuffer + ctx->width*i; memcpy(dst, src, sizeof(char) * ctx->width); } outBuffer += ctx->width * ctx->height; half_h = ctx->height/2; uv_w = ctx->width/2; for (i=0; i<half_h; i++) { unsigned char *src = pU + pitch/2*i; char *dst = outBuffer + i*uv_w; memcpy(dst, src, sizeof(char) * uv_w); } outBuffer += ctx->width * ctx->height / 4; for (i=0; i<half_h; i++) { unsigned char *src = pV + pitch/2*i; char *dst = outBuffer + i*uv_w; memcpy(dst, src, sizeof(char) * uv_w); } return GF_OK; }
static GF_Err XVID_DetachStream(GF_BaseDecoder *ifcg, u16 ES_ID) { XVIDCTX(); if (ctx->ES_ID != ES_ID) return GF_BAD_PARAM; if (ctx->codec) CloseCodec(ctx->codec); ctx->codec = NULL; ctx->ES_ID = 0; ctx->width = ctx->height = ctx->out_size = 0; return GF_OK; }
static GF_Err XVID_DetachStream(GF_BaseDecoder *ifcg, u16 ES_ID) { XVIDCTX(); if (ctx->base_ES_ID == ES_ID) { if (ctx->base_codec) xvid_decore(ctx->base_codec, XVID_DEC_DESTROY, NULL, NULL); ctx->base_codec = NULL; ctx->base_ES_ID = 0; ctx->width = ctx->height = ctx->out_size = 0; } else if (ctx->depth_ES_ID == ES_ID) { if (ctx->depth_codec) xvid_decore(ctx->depth_codec, XVID_DEC_DESTROY, NULL, NULL); ctx->depth_codec = NULL; ctx->depth_ES_ID = 0; if (ctx->temp_uv) gf_free(ctx->temp_uv); ctx->temp_uv = NULL; } return GF_OK; }
static GF_Err XVID_AttachStream(GF_BaseDecoder *ifcg, GF_ESD *esd) { GF_M4VDecSpecInfo dsi; GF_Err e; unsigned char *ptr; unsigned long pitch; XVIDCTX(); if (ctx->ES_ID && ctx->ES_ID!=esd->ESID) return GF_NOT_SUPPORTED; if (!esd->decoderConfig->decoderSpecificInfo || !esd->decoderConfig->decoderSpecificInfo->data) return GF_NON_COMPLIANT_BITSTREAM; /*decode DSI*/ e = gf_m4v_get_config((char *) esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi); if (e) return e; if (!dsi.width || !dsi.height) return GF_NON_COMPLIANT_BITSTREAM; GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[XviD] Attaching Stream %d - framesize %d x %d\n", esd->ESID, dsi.width, dsi.height )); ctx->codec = InitCodec(dsi.width, dsi.height, GF_4CC('x', 'v', 'i', 'd')); if (!ctx->codec) return GF_OUT_OF_MEM; GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[XviD] Decoding DecoderSpecificInfo\n")); DecodeFrame(ctx->codec, esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, ptr, ptr, ptr, pitch); /*note that this may be irrelevant when used through systems (FPS is driven by systems CTS)*/ ctx->FPS = dsi.clock_rate; ctx->FPS /= 1000; if (!ctx->FPS) ctx->FPS = 30.0f; ctx->width = dsi.width; ctx->height = dsi.height; ctx->pixel_ar = (dsi.par_num<<16) | dsi.par_den; ctx->pixel_ar = 0; ctx->ES_ID = esd->ESID; ctx->first_frame = 1; /*output in YV12 only - let the player handle conversion*/ ctx->out_size = 3 * ctx->width * ctx->height / 2; GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[XviD] Decoder setup - output size %d\n", ctx->out_size )); return GF_OK; }
static GF_Err XVID_AttachStream(GF_BaseDecoder *ifcg, GF_ESD *esd) { GF_M4VDecSpecInfo dsi; GF_Err e; void **codec; #ifdef XVID_USE_OLD_API XVID_DEC_FRAME frame; XVID_DEC_PARAM par; #else xvid_dec_frame_t frame; xvid_dec_create_t par; #endif XVIDCTX(); if (!esd->decoderConfig->decoderSpecificInfo || !esd->decoderConfig->decoderSpecificInfo->data) return GF_NON_COMPLIANT_BITSTREAM; /*locate any auxiliary video data descriptor on this stream*/ if (esd->dependsOnESID) { u32 i = 0; GF_Descriptor *d = NULL; if (esd->dependsOnESID != ctx->base_ES_ID) return GF_NOT_SUPPORTED; #ifdef XVID_USE_OLD_API return GF_NOT_SUPPORTED; #endif while ((d = gf_list_enum(esd->extensionDescriptors, &i))) { if (d->tag == GF_ODF_AUX_VIDEO_DATA) break; } if (!d) return GF_NOT_SUPPORTED; codec = &ctx->depth_codec; ctx->depth_ES_ID = esd->ESID; } else { if (ctx->base_ES_ID && ctx->base_ES_ID!=esd->ESID) return GF_NOT_SUPPORTED; codec = &ctx->base_codec; ctx->base_ES_ID = esd->ESID; } if (*codec) xvid_decore(*codec, XVID_DEC_DESTROY, NULL, NULL); /*decode DSI*/ e = gf_m4v_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi); if (e) return e; if (!dsi.width || !dsi.height) return GF_NON_COMPLIANT_BITSTREAM; memset(&par, 0, sizeof(par)); par.width = dsi.width; par.height = dsi.height; /*note that this may be irrelevant when used through systems (FPS is driven by systems CTS)*/ ctx->FPS = dsi.clock_rate; ctx->FPS /= 1000; if (!ctx->FPS) ctx->FPS = 30.0f; ctx->pixel_ar = (dsi.par_num<<16) | dsi.par_den; #ifndef XVID_USE_OLD_API par.version = XVID_VERSION; #endif if (xvid_decore(NULL, XVID_DEC_CREATE, &par, NULL) < 0) return GF_NON_COMPLIANT_BITSTREAM; ctx->width = par.width; ctx->height = par.height; *codec = par.handle; /*init decoder*/ memset(&frame, 0, sizeof(frame)); frame.bitstream = (void *) esd->decoderConfig->decoderSpecificInfo->data; frame.length = esd->decoderConfig->decoderSpecificInfo->dataLength; #ifndef XVID_USE_OLD_API frame.version = XVID_VERSION; xvid_decore(*codec, XVID_DEC_DECODE, &frame, NULL); #else /*don't perform error check, XviD doesn't like DSI only frame ...*/ xvid_decore(*codec, XVID_DEC_DECODE, &frame, NULL); #endif ctx->first_frame = 1; /*output in YV12 only - let the player handle conversion*/ if (ctx->depth_codec) { ctx->out_size = ctx->width * ctx->height * 5 / 2; ctx->temp_uv = gf_malloc(sizeof(char)*ctx->width * ctx->height / 2); } else { ctx->yuv_size = ctx->out_size = ctx->width * ctx->height * 3 / 2; } return GF_OK; }
static GF_Err XVID_ProcessData(GF_MediaDecoder *ifcg, char *inBuffer, u32 inBufferLength, u16 ES_ID, char *outBuffer, u32 *outBufferLength, u8 PaddingBits, u32 mmlevel) { #ifdef XVID_USE_OLD_API XVID_DEC_FRAME frame; #else xvid_dec_frame_t frame; #endif void *codec; s32 postproc, res; XVIDCTX(); if (!ES_ID) { *outBufferLength = 0; return GF_OK; } if (ES_ID == ctx->depth_ES_ID) { codec = ctx->depth_codec; } else { codec = ctx->base_codec; } if (!codec) return GF_OK; if (*outBufferLength < ctx->out_size) { *outBufferLength = ctx->out_size; return GF_BUFFER_TOO_SMALL; } memset(&frame, 0, sizeof(frame)); frame.bitstream = (void *) (inBuffer + ctx->offset); frame.length = inBufferLength - ctx->offset; ctx->offset = 0; #ifdef XVID_USE_OLD_API frame.colorspace = XVID_CSP_I420; frame.stride = ctx->width; frame.image = (void *) outBuffer; #else frame.version = XVID_VERSION; if (ES_ID == ctx->depth_ES_ID) { frame.output.csp = XVID_CSP_PLANAR; frame.output.stride[0] = ctx->width; frame.output.plane[0] = (void *) (outBuffer + ctx->yuv_size); frame.output.stride[1] = ctx->width/4; frame.output.plane[1] = (void *) ctx->temp_uv; frame.output.stride[2] = ctx->width/4; frame.output.plane[2] = (void *) ctx->temp_uv; } else { frame.output.csp = XVID_CSP_I420; frame.output.stride[0] = ctx->width; frame.output.plane[0] = (void *) outBuffer; } #endif /*to check, not convinced yet by results...*/ postproc = ctx->base_filters; switch (mmlevel) { case GF_CODEC_LEVEL_SEEK: case GF_CODEC_LEVEL_DROP: /*turn off all post-proc*/ #ifdef XVID_USE_OLD_API postproc &= ~XVID_DEC_DEBLOCKY; postproc &= ~XVID_DEC_DEBLOCKUV; #else postproc &= ~XVID_DEBLOCKY; postproc &= ~XVID_DEBLOCKUV; postproc &= ~XVID_FILMEFFECT; #endif break; case GF_CODEC_LEVEL_VERY_LATE: /*turn off post-proc*/ #ifdef XVID_USE_OLD_API postproc &= ~XVID_DEC_DEBLOCKY; #else postproc &= ~XVID_FILMEFFECT; postproc &= ~XVID_DEBLOCKY; #endif break; case GF_CODEC_LEVEL_LATE: #ifdef XVID_USE_OLD_API postproc &= ~XVID_DEC_DEBLOCKUV; #else postproc &= ~XVID_DEBLOCKUV; postproc &= ~XVID_FILMEFFECT; #endif break; } postproc = 0; /*xvid may keep the first I frame and force a 1-frame delay, so we simply trick it*/ if (ctx->first_frame) { outBuffer[0] = 'v'; outBuffer[1] = 'o'; outBuffer[2] = 'i'; outBuffer[3] = 'd'; } res = xvid_decore(codec, XVID_DEC_DECODE, &frame, NULL); if (res < 0) { *outBufferLength = 0; return GF_NON_COMPLIANT_BITSTREAM; } if (0 && res <= 6) { *outBufferLength = 0; return GF_OK; } /*dispatch nothing if seeking or droping*/ switch (mmlevel) { case GF_CODEC_LEVEL_SEEK: case GF_CODEC_LEVEL_DROP: if (ES_ID == ctx->base_ES_ID) *outBufferLength = 0; break; default: *outBufferLength = ctx->out_size; if (ctx->first_frame) { ctx->first_frame = 0; if ((outBuffer[0] == 'v') && (outBuffer[1] == 'o') && (outBuffer[2] == 'i') && (outBuffer[3] == 'd')) { *outBufferLength = 0; return GF_OK; } } if (res + 6 < frame.length) { ctx->offset = res; return GF_PACKED_FRAMES; } break; } return GF_OK; }