?? fileplayer.cpp.svn-base
字號:
/***************************************** Copyright (c) 2001-2003 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************/#ifndef ALLOW_OS_CODE#define ALLOW_OS_CODE 1#endif //ALLOW_OS_CODE#include "common.h"#include "fileplayer.h"#include "em86xx.h"#include "gui/gui.h"#include "rmasfdemux/include/wmdrmopl.h"#include "rmlibcw/include/rmlibcw.h"#ifdef WITH_MONO//#define USE_SAME_THREAD#define MONODBG ENABLEextern RMbool g_useKeyboard;extern typeCuracaoContext context;#include "rmdef/rmdef.h"#include "rmlibcw/include/rmfile.h"#include "rmvdemux/include/rmvdemuxapi.h"#define ERROR_CLEANUP(i) do { error = (i); goto cleanup; } while(0)#ifndef USE_SAME_THREADstatic RMthread g_thread = NULL;static RMthread g_subthread = NULL;#endifstatic struct playback_cmdline play_opt;static struct video_cmdline video_opt;static struct audio_cmdline audio_opt;static struct demux_cmdline demux_opt;// osd for mp4 subtitlesstruct osd_subtitles_context{ struct DCCVideoSource *pSPU_double_buffer_source; struct OSDdoubleBuffer doubleBuffer;};static struct osd_subtitles_context osd_subt;// callback for the application to receive dcc contextvoid RMDCCInfo(struct dcc_context *dcc_info){ context.decoder->SetDCCInfo(dcc_info); context.player->SetState(STATE_PLAY, 0); context.player->SetSampleType(); // notify gui of initialization context.gui->Notify(CURACAO_MESSAGE_DECODER_INITIALIZED, NULL);}// callback for the application to act upon receiving EOSvoid RMEOSCallback(){ // notify gui of EOS printf("received EOS\n"); context.gui->Notify(CURACAO_MESSAGE_EOS, NULL);}// callback to pass stream information to the application, DRM protected, number of chapters, etcvoid RMFileStreamInfoCallback(struct RMFileStreamInfo *streamInfo){ RMDBGLOG((ENABLE, "got stream info!\n")); context.player->SetStreamInfo(streamInfo);}// these functions need implementations (see mono/mono.c as a sample)RMstatus RMInitSPU(RMuint32 width, RMuint32 height){ struct DCCOSDProfile osdProfile; RMstatus status = RM_OK; osdProfile.ColorSpace = EMhwlibColorSpace_YUV_601; osdProfile.SamplingMode = EMhwlibSamplingMode_444; osdProfile.ColorMode = EMhwlibColorMode_TrueColor; osdProfile.ColorFormat = EMhwlibColorFormat_32BPP; // unused osdProfile.PixelAspectRatio.X = 1; osdProfile.PixelAspectRatio.Y = 1; osdProfile.Width = width; // should be the dimensions from the track, but they are wrong, so we hard code osdProfile.Height = height; RMDBGLOG((ENABLE, "RMinitSPU(%lu x %lu)\n", width, height)); // make sure we don't already have a buffer if (osd_subt.pSPU_double_buffer_source) { RMDBGLOG((ENABLE, "doubleBuffer already exists\n")); status = RMCloseSPU(); if (status != RM_OK) return status; } // Init SPU DoubleBuffer OSD status = RMInitDoubleBufferOSD(NULL, osdProfile, &(osd_subt.doubleBuffer)); if (status != RM_OK) { RMDBGLOG((ENABLE, "cant init doubleBufferOSD\n")); // allow playing even if SPU cannot be shown return RMCloseSPU(); } return RM_OK;}RMstatus RMInitDoubleBufferOSD(RMuint32 *moduleID, struct DCCOSDProfile osdProfile, struct OSDdoubleBuffer *doubleBuffer){ enum EMhwlibMixerSourceState state; RMuint32 mixer, scaler, src_index, mixer_src; struct EMhwlibDisplayWindow window; RMuint32 pic_luma_addr[2], pic_addr[2], pic_luma_size[2], surface_addr; RMuint8 *buf_map; RMuint32 buf_addr, buf_size; RMstatus err; struct RUA *pRUA = (RUA *) context.decoder->GetRUAInstance(); struct DCC *pDCC = (DCC *) context.decoder->GetDCCInstance(); RMDBGLOG((ENABLE, "init doubleBuffer OSD, size %lu x %lu\n", osdProfile.Width, osdProfile.Height)); mixer = EMHWLIB_MODULE(DispMainMixer, 0); scaler = EMHWLIB_MODULE(DispGFXMultiScaler,0); // set a NULL surface, this will force a full register update when next surface is set err = DCCSetSurfaceSource(pDCC, scaler, NULL); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot unset gfx scaler's surface\n")); return err; } err = RUAExchangeProperty(pRUA, mixer, RMGenericPropertyID_MixerSourceIndex, &scaler, sizeof(scaler), &src_index, sizeof(src_index)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot get scaler index\n")); return err; } mixer_src = EMHWLIB_TARGET_MODULE((enum RMcategoryID)mixer, 0 , src_index); state = EMhwlibMixerSourceState_Master; window.X = 0; window.Y = 0; window.Width = 4096; window.Height = 4096; window.XPositionMode = EMhwlibDisplayWindowPositionMode_FrontEdgeToBorder; window.YPositionMode = EMhwlibDisplayWindowPositionMode_FrontEdgeToBorder; window.XMode = EMhwlibDisplayWindowValueMode_Relative; window.YMode = EMhwlibDisplayWindowValueMode_Relative; window.WidthMode = EMhwlibDisplayWindowValueMode_Relative; window.HeightMode = EMhwlibDisplayWindowValueMode_Relative; RUASetProperty(pRUA, mixer_src, RMGenericPropertyID_MixerSourceWindow, &window, sizeof(window), 0); window.X = 0; window.Y = 0; window.Width = 4096; window.Height = 4096; window.XPositionMode = EMhwlibDisplayWindowPositionMode_FrontEdgeToBorder; window.YPositionMode = EMhwlibDisplayWindowPositionMode_FrontEdgeToBorder; window.XMode = EMhwlibDisplayWindowValueMode_Relative; window.YMode = EMhwlibDisplayWindowValueMode_Relative; window.WidthMode = EMhwlibDisplayWindowValueMode_Relative; window.HeightMode = EMhwlibDisplayWindowValueMode_Relative; RUASetProperty(pRUA, scaler, RMGenericPropertyID_ScalerInputWindow, &window, sizeof(window), 0); while((err = RUASetProperty(pRUA, mixer_src, RMGenericPropertyID_MixerSourceState, &state, sizeof(state), 0))==RM_PENDING); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot set scaler's state on mixer\n")); return err; } while ((err = RUASetProperty(pRUA, mixer, RMGenericPropertyID_Validate, NULL, 0, 0)) == RM_PENDING); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot validate mixer\n")); return err; } while ((err = RUASetProperty(pRUA, scaler, RMGenericPropertyID_Validate, NULL, 0, 0)) == RM_PENDING); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot validate mixer\n")); return err; } err = DCCOpenMultiplePictureOSDVideoSource(pDCC, &osdProfile, 2, &(osd_subt.pSPU_double_buffer_source)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot open OSD decoder %d\n", err)); return err; } err = DCCGetOSDSurfaceInfo(pDCC, osd_subt.pSPU_double_buffer_source, NULL, &surface_addr, NULL); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot get surface address %d\n", err)); return err; } err = DCCGetOSDPictureInfo(osd_subt.pSPU_double_buffer_source, 0, &(pic_addr[0]), &(pic_luma_addr[0]), &(pic_luma_size[0]), NULL, NULL); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot get osd buffer info %d\n", err)); return err; } err = DCCGetOSDPictureInfo(osd_subt.pSPU_double_buffer_source, 1, &(pic_addr[1]), &(pic_luma_addr[1]), &(pic_luma_size[1]), NULL, NULL); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot get osd buffer info %d\n", err)); return err; } // first pic (for double buffering) buf_size = pic_luma_size[0]; buf_addr = pic_luma_addr[0]; err = RUALock(pRUA, buf_addr, buf_size); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error locking OSD buffer at 0x%08lX (0x%08lX bytes)\n", buf_addr, buf_size)); return err; } buf_map = RUAMap(pRUA, buf_addr, buf_size); if (buf_map == NULL) { RMDBGLOG((ENABLE, "Error mapping OSD buffer at 0x%08lX (0x%08lX bytes)\n", buf_addr, buf_size)); return RM_ERROR; } memset(buf_map, 0x80, buf_size); doubleBuffer->buf0 = buf_map; doubleBuffer->buf0Size = buf_size; doubleBuffer->buf0Addr = buf_addr; doubleBuffer->isBuf0inUse = FALSE; doubleBuffer->buf0Cleared = FALSE; doubleBuffer->width = osdProfile.Width; doubleBuffer->height = osdProfile.Height; RUAUnMap(pRUA, buf_map, buf_size); err = RUAUnLock(pRUA, buf_addr, buf_size); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error unlocking OSD buffer at 0x%08lX (0x%08lX bytes)\n", buf_addr, buf_size)); return err; } // second pic buf_size = pic_luma_size[1]; buf_addr = pic_luma_addr[1]; err = RUALock(pRUA, buf_addr, buf_size); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error locking OSD buffer at 0x%08lX (0x%08lX bytes)\n", buf_addr, buf_size)); return err; } buf_map = RUAMap(pRUA, buf_addr, buf_size); if (buf_map == NULL) { RMDBGLOG((ENABLE, "Error mapping OSD buffer at 0x%08lX (0x%08lX bytes)\n", buf_addr, buf_size)); return RM_ERROR; } memset(buf_map, 0x90, buf_size); doubleBuffer->buf1 = buf_map; doubleBuffer->buf1Size = buf_size; doubleBuffer->buf1Addr = buf_addr; doubleBuffer->isBuf1inUse = FALSE; doubleBuffer->buf1Cleared = FALSE; RUAUnMap(pRUA, buf_map, buf_size); err = RUAUnLock(pRUA, buf_addr, buf_size); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error unlocking OSD buffer at 0x%08lX (0x%08lX bytes)\n", buf_addr, buf_size)); return err; } RMDBGLOG((ENABLE, "bitmap size %lu, buf0 @0x%lx, buf1 @0x%lx\n", buf_size, doubleBuffer->buf0, doubleBuffer->buf1)); // possibly clean it before this with a fill err = DCCSetSurfaceSource(pDCC, scaler, osd_subt.pSPU_double_buffer_source); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot set the surface source %d\n", err)); return RM_ERROR; } err = DCCEnableVideoSource(osd_subt.pSPU_double_buffer_source, TRUE); if (RMFAILED(err)){ RMDBGLOG((ENABLE,"Error enabling OSD buffer : %d\n",err)); return err; } while ((err = RUASetProperty(pRUA, scaler, RMGenericPropertyID_Validate, NULL, 0, 0)) == RM_PENDING); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot validate scaler input window %d\n", err)); return err; } //err = DCCInsertPictureInMultiplePictureOSDVideoSource(osd_subt.pSPU_double_buffer_source, 0); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot insert picture inside surface %d\n", err)); return err; } return RM_OK;}RMstatus RMCloseSPU(void){ if (osd_subt.pSPU_double_buffer_source) { RMstatus status; RMDBGLOG((ENABLE, "closing doubleBufferOSD\n")); RMuint8 to_try = 0; while((status = DCCCloseVideoSource(osd_subt.pSPU_double_buffer_source)) == RM_PENDING && ++to_try < 10 /*arbitrary*/) { RMDBGLOG((ENABLE, "oh that sucks\n")); } if (RMFAILED(status)) { RMDBGLOG((ENABLE, "Cannot close SPU doubleBuffer source %d\n", status)); return status; } osd_subt.pSPU_double_buffer_source = NULL; } return RM_OK;}RMstatus RMBlendSPU(RMuint8 *buffer){ RMstatus err; RMuint8 *buf_map; RMuint32 buf_size, buf_addr; RMuint32 blendPic = 0; struct RUA *pRUA = (RUA *) context.decoder->GetRUAInstance(); if (!osd_subt.pSPU_double_buffer_source) { RMDBGLOG((ENABLE, "there's no double buffer for spu!\n")); return RM_ERROR; } if (!osd_subt.doubleBuffer.isBuf0inUse) { //blend buf0: copy *buffer into doublebufffer and activate it RMDBGLOG((ENABLE, "blending buf0\n")); buf_size = osd_subt.doubleBuffer.buf0Size; buf_addr = osd_subt.doubleBuffer.buf0Addr; osd_subt.doubleBuffer.isBuf0inUse = TRUE; osd_subt.doubleBuffer.buf0Cleared = FALSE; blendPic = 0; osd_subt.doubleBuffer.isBuf1inUse = FALSE; } else if (!osd_subt.doubleBuffer.isBuf1inUse) { RMDBGLOG((ENABLE, "blending buf1\n")); buf_size = osd_subt.doubleBuffer.buf1Size; buf_addr = osd_subt.doubleBuffer.buf1Addr; osd_subt.doubleBuffer.isBuf1inUse = TRUE; osd_subt.doubleBuffer.buf1Cleared = FALSE; blendPic = 1; osd_subt.doubleBuffer.isBuf0inUse = FALSE; } else { RMDBGLOG((ENABLE, "no buffer available for double buffer rendering\n")); return RM_ERROR; } err = RUALock(pRUA, buf_addr, buf_size); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error locking OSD buffer at 0x%08lX (0x%08lX bytes)\n", buf_addr, buf_size)); return err; } buf_map = RUAMap(pRUA, buf_addr, buf_size); if (buf_map == NULL) { RMDBGLOG((ENABLE, "Error mapping OSD buffer at 0x%08lX (0x%08lX bytes)\n", buf_addr, buf_size)); return RM_ERROR; } // reorder Y,V,U,A planes into UYVA,UYVA,... pixels { RMuint32 bitmap_size = osd_subt.doubleBuffer.width * osd_subt.doubleBuffer.height; RMuint8 *buf_Y = buffer; RMuint8 *buf_V = buf_Y + (bitmap_size); RMuint8 *buf_U = buf_V + (bitmap_size); RMuint8 *buf_A = buf_U + (bitmap_size); RMuint32 i = 0; while (i < (bitmap_size*4)) { *(buf_map+i) = *buf_U++; // bleu *(buf_map+i+1) = *buf_Y++; *(buf_map+i+2) = *buf_V++; // rouge? // alpha values are in the [0,16] range, convert them to [0,255] if (*buf_A) *(buf_map+i+3) = RMmin(*buf_A * 16, 255); else *(buf_map+i+3) = 0; buf_A++; i+=4; } } RUAUnMap(pRUA, buf_map, buf_size); err = RUAUnLock(pRUA, buf_addr, buf_size); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error unlocking OSD buffer at 0x%08lX (0x%08lX bytes)\n", buf_addr, buf_size)); return err; } err = DCCInsertPictureInMultiplePictureOSDVideoSource(osd_subt.pSPU_double_buffer_source, blendPic); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot insert picture inside surface %d\n", err)); return err; } return RM_OK;}RMstatus RMClearSPU(){ RMstatus err; RMuint8 *buf_map; RMuint32 buf_size, buf_addr; RMuint32 blendPic = 0; struct RUA *pRUA = (RUA *) context.decoder->GetRUAInstance(); if (!osd_subt.pSPU_double_buffer_source) return RM_ERROR; if (osd_subt.doubleBuffer.buf0Cleared) return RM_OK; RMDBGLOG((ENABLE, "clearSPU\n")); buf_size = osd_subt.doubleBuffer.buf0Size; buf_addr = osd_subt.doubleBuffer.buf0Addr; osd_subt.doubleBuffer.isBuf0inUse = FALSE; osd_subt.doubleBuffer.buf0Cleared = TRUE; blendPic = 0; osd_subt.doubleBuffer.isBuf1inUse = FALSE; err = RUALock(pRUA, buf_addr, buf_size); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error locking OSD buffer at 0x%08lX (0x%08lX bytes)\n", buf_addr, buf_size)); return err; } buf_map = RUAMap(pRUA, buf_addr, buf_size); if (buf_map == NULL) { RMDBGLOG((ENABLE, "Error mapping OSD buffer at 0x%08lX (0x%08lX bytes)\n", buf_addr, buf_size)); return RM_ERROR; } // clear buffer memset(buf_map, 0, buf_size); RUAUnMap(pRUA, buf_map, buf_size); err = RUAUnLock(pRUA, buf_addr, buf_size); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error unlocking OSD buffer at 0x%08lX (0x%08lX bytes)\n", buf_addr, buf_size)); return err; } err = DCCInsertPictureInMultiplePictureOSDVideoSource(osd_subt.pSPU_double_buffer_source, blendPic); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot insert picture inside surface %d\n", err)); return err; } return RM_OK;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -