static int setup(VideoDecoder *vdec, Movie *m, Image *p, int w, int h) { struct videodecoder_divx *vdm = (struct videodecoder_divx *)vdec->opaque; DEC_INIT dec_init; DivXBitmapInfoHeader bih; int inst, quality; if (memory_alloc(image_rendered_image(p), image_bpl(p) * image_height(p)) == NULL) { err_message("No enough memory for image body (%d bytes).\n", image_bpl(p) * image_height(p)); return 0; } memset(&dec_init, 0, sizeof(dec_init)); dec_init.codec_version = vdm->input_format; dec_init.smooth_playback = 0; decore(&vdm->dec_handle, DEC_OPT_INIT, &dec_init, NULL); inst = DEC_ADJ_POSTPROCESSING | DEC_ADJ_SET; quality = 0; // 0-60 decore(vdm->dec_handle, DEC_OPT_ADJUST, &inst, &quality); bih.biCompression = m->out_fourcc; bih.biBitCount = m->out_bitcount; bih.biSize = sizeof(DivXBitmapInfoHeader); bih.biWidth = m->width; bih.biHeight = m->height; decore(vdm->dec_handle, DEC_OPT_SETOUT, &bih, NULL); return 1; }
static void destroy(VideoDecoder *vdec) { struct videodecoder_divx *vdm = (struct videodecoder_divx *)vdec->opaque; if (vdm) { decore(vdm->dec_handle, DEC_OPT_RELEASE, NULL, NULL); free(vdm); } _videodecoder_destroy(vdec); }
void DeleteXVIDDec(BaseDecoder *ifcg) { DIVXCTX(); if (ctx->codec) { if (decore (ctx->codec, DEC_OPT_RELEASE, 0, 0) != DEC_OK) { printf ("Decore >DEC_OPT_RELEASE< returned \n"); } } DIVX_is_init = 0; free(ctx); free(ifcg); }
//--------------------------------------------------------------------------- // 函数: DivXDecode // 功能: 解码 // 参数: void // 返回: void //--------------------------------------------------------------------------- void KLMp4Video::DivXDecode(BOOL bRender) { WaitForSingleObject( m_hMutex, INFINITE); DEC_FRAME dec_frame; dec_frame.length = m_nFrameSize; dec_frame.bitstream = m_pVideo; dec_frame.bmp = m_pFrame; dec_frame.render_flag = bRender; decore(m_dwHandle, 0, &dec_frame, NULL); ReleaseMutex(m_hMutex); }
static M4Err DIVX_DetachStream(BaseDecoder *ifcg, u16 ES_ID) { DIVXCTX(); if (ctx->ES_ID != ES_ID) return M4BadParam; if (ctx->codec) { if (decore (ctx->codec, DEC_OPT_RELEASE, 0, 0) != DEC_OK) { printf ("Decore >DEC_OPT_RELEASE< returned \n"); } } DIVX_is_init = 0; ctx->codec = NULL; ctx->ES_ID = 0; ctx->width = ctx->height = ctx->out_size = 0; return M4OK; }
//--------------------------------------------------------------------------- // 函数: DivXExit // 功能: 释放解码器 // 参数: void // 返回: void //--------------------------------------------------------------------------- void KLMp4Video::DivXExit() { if (m_dwHandle) { decore(m_dwHandle, DEC_OPT_RELEASE, NULL, NULL); m_dwHandle = 0; } if(m_pVideo) { delete[] m_pVideo; m_pVideo = NULL; } if(m_pFrame) { delete[] m_pFrame; m_pFrame = NULL; } }
static VideoDecoderStatus decode(VideoDecoder *vdec, Movie *m, Image *p, DemuxedPacket *dp, unsigned int len, unsigned int *used_r) { struct videodecoder_divx *vdm = (struct videodecoder_divx *)vdec->opaque; unsigned char *buf = dp->data; int res; if (len == 0) return VD_NEED_MORE_DATA; *used_r = len; vdm->dec_frame.length = len; vdm->dec_frame.bitstream = buf; vdm->dec_frame.bmp = memory_ptr(image_rendered_image(p)); vdm->dec_frame.render_flag = vdm->to_skip > 0 ? 0 : 1; vdm->dec_frame.stride = 0; pthread_mutex_lock(&vdec->update_mutex); if ((res = decore(vdm->dec_handle, DEC_OPT_FRAME, &vdm->dec_frame, NULL)) != DEC_OK) { if (res == DEC_BAD_FORMAT) { err_message("OPT_FRAME returns DEC_BAD_FORMAT\n"); } else { err_message("OPT_FRAME returns %d\n", res); } pthread_mutex_unlock(&vdec->update_mutex); return VD_ERROR; } m->current_frame++; if (vdm->to_skip > 0) { vdm->to_skip--; pthread_mutex_unlock(&vdec->update_mutex); return VD_OK; } vdec->ts_base = dp->ts_base; vdec->pts = m->current_frame * 1000 / rational_to_double(m->framerate); vdec->to_render++; while (m->status == _PLAY && vdec->to_render > 0) pthread_cond_wait(&vdec->update_cond, &vdec->update_mutex); pthread_mutex_unlock(&vdec->update_mutex); return VD_OK; }
static M4Err DIVX_ProcessData(MediaDecoder *ifcg, unsigned char *inBuffer, u32 inBufferLength, u16 ES_ID, unsigned char *outBuffer, u32 *outBufferLength, u8 PaddingBits, u32 mmlevel) { DIVXCTX(); /*check not using scalabilty*/ if (ES_ID != ctx->ES_ID) return M4BadParam; if (*outBufferLength < ctx->out_size) { *outBufferLength = ctx->out_size; return M4BufferTooSmall; } ctx->df.bitstream = (void *) inBuffer; ctx->df.length = inBufferLength; ctx->df.bmp = (void *) outBuffer; ctx->df.render_flag = 1; ctx->df.skip_decoding = 0; ctx->df.stride = ctx->width; if (decore (ctx->codec, DEC_OPT_FRAME, &ctx->df, 0) != DEC_OK) { *outBufferLength = 0; return M4NonCompliantBitStream; } /*dispatch nothing if seeking or droping*/ switch (mmlevel) { case MM_LEVEL_SEEK: case MM_LEVEL_DROP: *outBufferLength = 0; break; default: *outBufferLength = ctx->out_size; break; } return M4OK; }
static M4Err DIVX_AttachStream(BaseDecoder *ifcg, u16 ES_ID, unsigned char *decSpecInfo, u32 decSpecInfoSize, u16 DependsOnES_ID, u32 objectTypeIndication, Bool UpStream) { M4VDecoderSpecificInfo dsi; M4Err e; DIVXCTX(); if (ctx->ES_ID && ctx->ES_ID!=ES_ID) return M4NotSupported; if (!decSpecInfoSize || !decSpecInfo) return M4NonCompliantBitStream; // if (ctx->codec) DIVX_decore(ctx->codec, DIVX_DEC_DESTROY, NULL, NULL); if (ctx->codec) decore(ctx->codec, DEC_OPT_RELEASE, NULL, NULL); /*decode DSI*/ e = M4V_GetConfig(decSpecInfo, decSpecInfoSize, &dsi); if (e) return e; if (!dsi.width || !dsi.height) return M4NonCompliantBitStream; if (!DIVX_is_init) { DivXBitmapInfoHeader bi; DEC_VOL_INFO dv; DEC_INIT di; di.alloc = NULL; di.free = NULL; di.flag_logo = 0; if (decore(&(ctx->codec), DEC_OPT_INIT, &di, 0) != DEC_OK) { printf("Decore >DEC_OPT_INIT< failed\n"); } ctx->df.render_flag = 1; ctx->df.skip_decoding = 0; ctx->df.length = decSpecInfoSize; ctx->df.bitstream = (void *) decSpecInfo; // Always call DEC_OPT_INIT_VOL to ensure use of values from m4v bitstream. if (decore (ctx->codec, DEC_OPT_INIT_VOL, &ctx->df, &dv) != DEC_OK) { printf(">Decore >DEC_OPT_INIT_VOL< failed\n"); } bi.biSize = sizeof (bi); bi.biWidth = dsi.width; bi.biHeight = dsi.height; // bi.biCompression = SWAPP_BYTES(M4PF_YV12);/*mmioFOURCC('I', 'Y', 'U', 'V');*/ bi.biCompression = mmioFOURCC('I', '4', '2', '0'); /*frame.colorspace = DIVX_CSP_I420;*/ if (decore (ctx->codec, DEC_OPT_SETOUT, &bi, 0) != DEC_OK) { printf ("Decore >DEC_OPT_SETOUT< failed \n"); } ctx->df.stride = dsi.width; DIVX_is_init = 1; } ctx->df.bmp = NULL; ctx->df.render_flag = 0; ctx->df.skip_decoding = 0; // if (decore (ctx->codec, DEC_OPT_FRAME, &ctx->df, 0) != DEC_OK) { // return M4NonCompliantBitStream; // } ctx->width = dsi.width; ctx->height = dsi.height; ctx->ES_ID = ES_ID; /*output in YV12 only - let the player handle conversion*/ ctx->out_size = ctx->width * ctx->height * 3 / 2; return M4OK; }
//--------------------------------------------------------------------------- // 函数: DivXInit // 功能: 初始化解码器 // 参数: void // 返回: void //--------------------------------------------------------------------------- BOOL KLMp4Video::DivXInit() { char szMethod[8]; BITMAPINFOHEADER BmpInfoHead; // check avi compress method m_AviFile.GetCompressMethod(szMethod); if (memcmp(szMethod, "divx", 4) != 0) { return FALSE; } // get frame delay m_nFrameRate = m_AviFile.FrameRate(); m_nFrameTime = (1000 + m_nFrameRate - 1) / m_nFrameRate; // get bitmap info header m_AviFile.GetBitmapInfoHeader(&BmpInfoHead); // check compress method if (memcmp(&BmpInfoHead.biCompression, "DIVX", 4) != 0) { return FALSE; } // get frame width an height m_nWidth = BmpInfoHead.biWidth; m_nHeight = BmpInfoHead.biHeight; if(m_nWidth < m_nHeight) return FALSE; // get video buffer if(!m_pVideo) m_pVideo = (LPBYTE)new BYTE[m_nWidth * m_nHeight * 4]; if(!m_pVideo) return FALSE; // get frame buffer if(!m_pFrame) m_pFrame = (LPBYTE)new BYTE[m_nWidth * m_nHeight * 4]; if(!m_pFrame) { delete[] m_pVideo; m_pVideo = NULL; return FALSE; } // get a unique decore handle if (m_dwHandle == 0) m_dwHandle = GetTickCount(); // init decore DEC_PARAM dec_param; dec_param.x_dim = m_nWidth; dec_param.y_dim = m_nHeight; dec_param.color_depth = NULL; dec_param.output_format = RGB32; if (decore(m_dwHandle, DEC_OPT_INIT, &dec_param, NULL) != DEC_OK) { return FALSE; } return TRUE; }