HRESULT CSubtitleInputPin::CompleteConnect(IPin* pReceivePin) { CAutoLock cAutoLock(m_pSubLock); XY_LOG_DEBUG(XY_LOG_VAR_2_STR(pReceivePin)); delete m_helper; m_helper = NULL; m_helper = CreateHelper(m_mt, pReceivePin); if (!m_helper) { XY_LOG_ERROR("Failed to Create helper. "); return E_FAIL; } AddSubStream(m_helper->GetSubStream()); return __super::CompleteConnect(pReceivePin); }
void CompositionObject::InitColor(const SubPicDesc& spd) { #define COMBINE_AYUV(a, y, u, v) ((((((((int)(a))<<8)|y)<<8)|u)<<8)|v) //fix me: move all color conv function into color_conv_table or dsutil #define FULL_TYPE(x,y) (((x)<<8)|y) int paletteNumber = m_Palette.GetCount(); if (m_colorType!=spd.type) { m_colorType = -1; ColorConvTable::YuvMatrixType cur_type; ColorConvTable::YuvRangeType cur_range; if (m_OriginalColorType==YUV_Rec601) { cur_type = ColorConvTable::BT601; } else if (m_OriginalColorType==YUV_Rec709) { cur_type = ColorConvTable::BT709; } else { XY_LOG_ERROR("Not supported"); ASSERT(0); return; } if (m_OriginalYuvRangeType==RANGE_TV) { cur_range = ColorConvTable::RANGE_TV; } else if (m_OriginalYuvRangeType==RANGE_PC) { cur_range = ColorConvTable::RANGE_PC; } else { XY_LOG_ERROR("Not supported"); ASSERT(0); return; } m_colorType = spd.type; switch(spd.type) { case MSP_AYUV_PLANAR: case MSP_AYUV: if (FULL_TYPE(cur_type,cur_range)== FULL_TYPE(ColorConvTable::GetDefaultYUVType(), ColorConvTable::GetDefaultRangeType())) { for (int i=0;i<paletteNumber;i++) { m_Colors[m_Palette[i].entry_id] = COMBINE_AYUV(m_Palette[i].T, m_Palette[i].Y, m_Palette[i].Cb , m_Palette[i].Cr); } } else if (cur_type==ColorConvTable::GetDefaultYUVType()) { if (cur_range==ColorConvTable::RANGE_PC) { for (int i=0;i<paletteNumber;i++) { m_Colors[m_Palette[i].entry_id] = ColorConvTable::A8Y8U8V8_PC_To_TV(m_Palette[i].T, m_Palette[i].Y , m_Palette[i].Cb, m_Palette[i].Cr); } } else if (cur_range==ColorConvTable::RANGE_TV) { for (int i=0;i<paletteNumber;i++) { m_Colors[m_Palette[i].entry_id] = ColorConvTable::A8Y8U8V8_TV_To_PC(m_Palette[i].T, m_Palette[i].Y , m_Palette[i].Cb, m_Palette[i].Cr); } } } else if (FULL_TYPE(cur_type,cur_range)== FULL_TYPE(ColorConvTable::BT709, ColorConvTable::RANGE_TV)) { for (int i=0;i<paletteNumber;i++) { DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_TV_BT709(m_Palette[i].T, m_Palette[i].Y , m_Palette[i].Cb, m_Palette[i].Cr); m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Ayuv(argb); } } else if (FULL_TYPE(cur_type,cur_range)== FULL_TYPE(ColorConvTable::BT709, ColorConvTable::RANGE_PC)) { for (int i=0;i<paletteNumber;i++) { DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_PC_BT709(m_Palette[i].T, m_Palette[i].Y , m_Palette[i].Cb, m_Palette[i].Cr); m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Ayuv(argb); } } else if (FULL_TYPE(cur_type,cur_range)== FULL_TYPE(ColorConvTable::BT601, ColorConvTable::RANGE_TV)) { for (int i=0;i<paletteNumber;i++) { DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_TV_BT601(m_Palette[i].T, m_Palette[i].Y , m_Palette[i].Cb, m_Palette[i].Cr); m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Ayuv(argb); } } else if (FULL_TYPE(cur_type,cur_range)== FULL_TYPE(ColorConvTable::BT601, ColorConvTable::RANGE_PC)) { for (int i=0;i<paletteNumber;i++) { DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_PC_BT601(m_Palette[i].T, m_Palette[i].Y , m_Palette[i].Cb, m_Palette[i].Cr); m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Ayuv(argb); } } else { XY_LOG_ERROR("Not supported"); ASSERT(0); return; } break; case MSP_XY_AUYV: if (FULL_TYPE(cur_type,cur_range)== FULL_TYPE(ColorConvTable::GetDefaultYUVType(), ColorConvTable::GetDefaultRangeType())) { for (int i=0;i<paletteNumber;i++) { m_Colors[m_Palette[i].entry_id] = COMBINE_AYUV(m_Palette[i].T, m_Palette[i].Cb, m_Palette[i].Y , m_Palette[i].Cr); } } else if (cur_type==ColorConvTable::GetDefaultYUVType()) { if (cur_range==ColorConvTable::RANGE_PC) { for (int i=0;i<paletteNumber;i++) { DWORD ayuv = ColorConvTable::A8Y8U8V8_PC_To_TV(m_Palette[i].T, m_Palette[i].Y , m_Palette[i].Cb, m_Palette[i].Cr); m_Colors[m_Palette[i].entry_id] = ColorConvTable::Ayuv2Auyv(ayuv); } } else if (cur_range==ColorConvTable::RANGE_TV) { for (int i=0;i<paletteNumber;i++) { DWORD ayuv = ColorConvTable::A8Y8U8V8_TV_To_PC(m_Palette[i].T, m_Palette[i].Y , m_Palette[i].Cb, m_Palette[i].Cr); m_Colors[m_Palette[i].entry_id] = ColorConvTable::Ayuv2Auyv(ayuv); } } } else if (FULL_TYPE(cur_type,cur_range)== FULL_TYPE(ColorConvTable::BT709, ColorConvTable::RANGE_TV)) { for (int i=0;i<paletteNumber;i++) { DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_TV_BT709(m_Palette[i].T, m_Palette[i].Y , m_Palette[i].Cb, m_Palette[i].Cr); m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Auyv(argb); } } else if (FULL_TYPE(cur_type,cur_range)== FULL_TYPE(ColorConvTable::BT709, ColorConvTable::RANGE_PC)) { for (int i=0;i<paletteNumber;i++) { DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_PC_BT709(m_Palette[i].T, m_Palette[i].Y , m_Palette[i].Cb, m_Palette[i].Cr); m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Auyv(argb); } } else if (FULL_TYPE(cur_type,cur_range)== FULL_TYPE(ColorConvTable::BT601, ColorConvTable::RANGE_TV)) { for (int i=0;i<paletteNumber;i++) { DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_TV_BT601(m_Palette[i].T, m_Palette[i].Y , m_Palette[i].Cb, m_Palette[i].Cr); m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Auyv(argb); } } else if (FULL_TYPE(cur_type,cur_range)== FULL_TYPE(ColorConvTable::BT601, ColorConvTable::RANGE_PC)) { for (int i=0;i<paletteNumber;i++) { DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_PC_BT601(m_Palette[i].T, m_Palette[i].Y , m_Palette[i].Cb, m_Palette[i].Cr); m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Auyv(argb); } } else { XY_LOG_ERROR("Not supported"); ASSERT(0); return; } break; case MSP_RGBA: if (FULL_TYPE(cur_type,cur_range)== FULL_TYPE(ColorConvTable::BT709, ColorConvTable::RANGE_TV)) { for (int i=0;i<paletteNumber;i++) { DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_TV_BT709(m_Palette[i].T, m_Palette[i].Y , m_Palette[i].Cb, m_Palette[i].Cr); m_Colors[m_Palette[i].entry_id] = argb; } } else if (FULL_TYPE(cur_type,cur_range)== FULL_TYPE(ColorConvTable::BT709, ColorConvTable::RANGE_PC)) { for (int i=0;i<paletteNumber;i++) { DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_PC_BT709(m_Palette[i].T, m_Palette[i].Y , m_Palette[i].Cb, m_Palette[i].Cr); m_Colors[m_Palette[i].entry_id] = argb; } } else if (FULL_TYPE(cur_type,cur_range)== FULL_TYPE(ColorConvTable::BT601, ColorConvTable::RANGE_TV)) { for (int i=0;i<paletteNumber;i++) { DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_TV_BT601(m_Palette[i].T, m_Palette[i].Y , m_Palette[i].Cb, m_Palette[i].Cr); m_Colors[m_Palette[i].entry_id] = argb; } } else if (FULL_TYPE(cur_type,cur_range)== FULL_TYPE(ColorConvTable::BT601, ColorConvTable::RANGE_PC)) { for (int i=0;i<paletteNumber;i++) { DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_PC_BT601(m_Palette[i].T, m_Palette[i].Y , m_Palette[i].Cb, m_Palette[i].Cr); m_Colors[m_Palette[i].entry_id] = argb; } } else { XY_LOG_ERROR("Not supported"); ASSERT(0); return; } break; default: XY_LOG_ERROR("Not supported"); ASSERT(0); return; } } }
STDMETHODIMP XySubRenderProviderWrapper::RequestFrame( IXySubRenderFrame**subRenderFrame, REFERENCE_TIME now ) { ASSERT(m_consumer); double fps; CheckPointer(subRenderFrame, E_POINTER); *subRenderFrame = NULL; HRESULT hr = m_consumer->XyGetDouble(DirectVobSubXyOptions::DOUBLE_FPS, &fps); if (FAILED(hr)) { XY_LOG_ERROR("Failed to get fps. "<<XY_LOG_VAR_2_STR(hr)); return hr; } CRect output_rect, subtitle_target_rect; CSize original_video_size; bool use_dst_alpha = false; ASSERT(m_consumer); hr = m_consumer->XyGetSize(DirectVobSubXyOptions::SIZE_ORIGINAL_VIDEO, &original_video_size); ASSERT(SUCCEEDED(hr)); hr = m_consumer->XyGetBool(DirectVobSubXyOptions::BOOL_SUB_FRAME_USE_DST_ALPHA, &use_dst_alpha); if (m_original_video_size!=original_video_size || m_use_dst_alpha!=use_dst_alpha) { if (m_use_dst_alpha==use_dst_alpha) { XY_LOG_WARN("Original video size changed from "<<m_original_video_size<<" to "<<original_video_size); } else { XY_LOG_INFO("'Use dst alpha' option changed from "<<m_use_dst_alpha<<" to "<<use_dst_alpha); } Invalidate(); m_original_video_size = original_video_size; m_use_dst_alpha = use_dst_alpha; } if(!m_pSubPic) { if (!m_allocator) { ResetAllocator(); } } POSITION pos = m_provider->GetStartPosition(now, fps); if (!pos) { return S_FALSE; } REFERENCE_TIME start = m_provider->GetStart(pos, fps); REFERENCE_TIME stop = m_provider->GetStop(pos, fps); //fixme: have to get start stop twice if (!(start <= now && now < stop)) { return S_FALSE; } hr = Render( now, pos, fps ); if (FAILED(hr)) { return hr; } if (m_xy_sub_render_frame) { *subRenderFrame = m_xy_sub_render_frame; (*subRenderFrame)->AddRef(); } return hr; }
HRESULT XySubRenderProviderWrapper2::CombineBitmap(REFERENCE_TIME now) { static int s_combined_bitmap_id = 0x10000000;//fixme: important! Uncombined bitmap id MUST < 0x10000000. XY_LOG_TRACE(now); HRESULT hr = NOERROR; if (m_xy_sub_render_frame) { m_subpic = NULL; hr = m_allocator->AllocDynamicEx(&m_subpic); if(FAILED(hr) || !m_subpic) { XY_LOG_FATAL("Failed to allocate subpic. "<<XY_LOG_VAR_2_STR(hr)); return hr; } int count = 0; hr = m_xy_sub_render_frame->GetBitmapCount(&count); ASSERT(SUCCEEDED(hr)); if (count==1) { return S_OK; } SubPicDesc spd; hr = m_subpic->Lock(spd); if (FAILED(hr)) { XY_LOG_ERROR("Failed to lock spd. "<<XY_LOG_VAR_2_STR(hr)); return hr; } DWORD color = 0x00000000; hr = m_subpic->ClearDirtyRect(color); if(FAILED(hr)) { XY_LOG_ERROR("Failed to clear dirty rect. "<<XY_LOG_VAR_2_STR(hr)); return hr; } CRect dirty_rect; for (int i=0;i<count;i++) { POINT pos; SIZE size; LPCVOID pixels; int pitch; hr = m_xy_sub_render_frame->GetBitmap(i, NULL, &pos, &size, &pixels, &pitch ); if (FAILED(hr)) { XY_LOG_ERROR("Failed to get bitmap. "<<XY_LOG_VAR_2_STR(hr)); return hr; } ASSERT(SUCCEEDED(hr)); dirty_rect |= CRect(pos, size); XyBitmap::BltPack(spd, pos, size, pixels, pitch); } dirty_rect &= m_subtitle_target_rect; hr = m_subpic->Unlock(&dirty_rect); if (FAILED(hr)) { XY_LOG_ERROR("Failed to unlock. "<<XY_LOG_VAR_2_STR(dirty_rect)<<XY_LOG_VAR_2_STR(hr)); return hr; } hr = m_subpic->GetDirtyRect(&dirty_rect); ASSERT(SUCCEEDED(hr)); CMemSubPic * mem_subpic = dynamic_cast<CMemSubPic*>((ISubPicEx *)m_subpic); ASSERT(mem_subpic); m_xy_sub_render_frame = DEBUG_NEW XySubRenderFrameWrapper(mem_subpic, m_output_rect, m_subtitle_target_rect , s_combined_bitmap_id++, &hr); return hr; } return hr; }
STDMETHODIMP XySubRenderProviderWrapper2::RequestFrame( IXySubRenderFrame**subRenderFrame, REFERENCE_TIME now ) { ASSERT(m_consumer); double fps; CheckPointer(subRenderFrame, E_POINTER); *subRenderFrame = NULL; HRESULT hr = m_consumer->XyGetDouble(DirectVobSubXyOptions::DOUBLE_FPS, &fps); if (FAILED(hr)) { XY_LOG_ERROR("Failed to get fps. "<<XY_LOG_VAR_2_STR(hr)); return hr; } m_fps = fps;//fix me: invalidate CRect output_rect, subtitle_target_rect; CSize original_video_size; bool use_dst_alpha = false; bool combine_bitmap = false; bool render_to_original_video_size = false; ASSERT(m_consumer); hr = m_consumer->XyGetRect(DirectVobSubXyOptions::RECT_VIDEO_OUTPUT, &output_rect); ASSERT(SUCCEEDED(hr)); hr = m_consumer->XyGetRect(DirectVobSubXyOptions::RECT_SUBTITLE_TARGET, &subtitle_target_rect); ASSERT(SUCCEEDED(hr)); ASSERT(output_rect.Width()<=subtitle_target_rect.Width() && output_rect.Height()<=subtitle_target_rect.Height()); hr = m_consumer->XyGetSize(DirectVobSubXyOptions::SIZE_LAYOUT_WITH, &original_video_size); ASSERT(SUCCEEDED(hr)); hr = m_consumer->XyGetInt(DirectVobSubXyOptions::INT_MAX_BITMAP_COUNT2, &m_max_bitmap_count2); ASSERT(SUCCEEDED(hr)); hr = m_consumer->XyGetBool(DirectVobSubXyOptions::BOOL_SUB_FRAME_USE_DST_ALPHA, &use_dst_alpha); hr = m_consumer->XyGetBool(DirectVobSubXyOptions::BOOL_RENDER_TO_ORIGINAL_VIDEO_SIZE, &render_to_original_video_size); if (render_to_original_video_size) { output_rect = CRect(CPoint(), original_video_size); subtitle_target_rect = output_rect; } m_render_to_original_video_size = render_to_original_video_size; bool should_invalidate = false; bool should_invalidate_allocator = false; if (m_original_video_size!=original_video_size || m_use_dst_alpha!=use_dst_alpha || m_output_rect!=output_rect || m_subtitle_target_rect!=subtitle_target_rect) { should_invalidate = true; should_invalidate_allocator = (m_subtitle_target_rect!=subtitle_target_rect)==TRUE; m_original_video_size = original_video_size; m_use_dst_alpha = use_dst_alpha; m_output_rect = output_rect; m_subtitle_target_rect = subtitle_target_rect; } if (m_xy_sub_render_frame) { int count = 0; hr = m_xy_sub_render_frame->GetBitmapCount(&count); should_invalidate = (count>m_max_bitmap_count2); } if (should_invalidate) { XY_LOG_INFO("Output rects or max_bitmap_count or alpha type changed."); Invalidate(); } if (should_invalidate_allocator) { CSize max_size(m_subtitle_target_rect.right, m_subtitle_target_rect.bottom); m_allocator = DEBUG_NEW CPooledSubPicAllocator(MSP_RGB32, max_size,2); ASSERT(m_allocator); m_allocator->SetCurSize(max_size); m_allocator->SetCurVidRect(CRect(CPoint(0,0),max_size)); } POSITION pos = m_provider->GetStartPosition(now, fps); if (!pos) { XY_LOG_TRACE("No subtitles at "<<XY_LOG_VAR_2_STR(now)); return S_FALSE; } REFERENCE_TIME start = m_provider->GetStart(pos, fps); REFERENCE_TIME stop = m_provider->GetStop(pos, fps); //fixme: have to get start stop twice if (!(start <= now && now < stop)) { XY_LOG_TRACE("No subtitles at "<<XY_LOG_VAR_2_STR(now)); return S_FALSE; } hr = Render( now, pos ); if (FAILED(hr)) { return hr; } if (m_xy_sub_render_frame) { *subRenderFrame = m_xy_sub_render_frame; (*subRenderFrame)->AddRef(); } return hr; }
HRESULT XySubRenderProviderWrapper::Render( REFERENCE_TIME now, POSITION pos, double fps ) { if(m_pSubPic && m_pSubPic->GetStart() <= now && now < m_pSubPic->GetStop()) { return S_OK; } HRESULT hr = E_FAIL; //should always re-alloc one for the old be in used by the consumer m_pSubPic = NULL; ASSERT(m_allocator); if(FAILED(m_allocator->AllocDynamicEx(&m_pSubPic))) { XY_LOG_ERROR("Failed to allocate subpic"); return E_FAIL; } ASSERT(m_pSubPic); if(FAILED(m_provider->Lock())) { return hr; } CMemSubPic * mem_subpic = dynamic_cast<CMemSubPic*>((ISubPicEx *)m_pSubPic); ASSERT(mem_subpic); SubPicDesc spd; if(SUCCEEDED(m_pSubPic->Lock(spd))) { CAtlList<CRect> rectList; DWORD color = 0xFF000000; if(SUCCEEDED(m_pSubPic->ClearDirtyRect(color))) { hr = m_provider->RenderEx(spd, now, fps, rectList); if (!m_provider->IsAnimated(pos)) { REFERENCE_TIME start = m_provider->GetStart(pos, fps); REFERENCE_TIME stop = m_provider->GetStop(pos, fps); XY_LOG_TRACE(XY_LOG_VAR_2_STR(start)<<XY_LOG_VAR_2_STR(stop)); m_pSubPic->SetStart(start); m_pSubPic->SetStop(stop); } else { m_pSubPic->SetStart(now); m_pSubPic->SetStop(now+1); } } else { rectList.AddHead(CRect(CPoint(0,0),m_original_video_size)); XY_LOG_ERROR("Failed to clear subpic!"); } hr = m_pSubPic->UnlockEx(&rectList); ASSERT(SUCCEEDED(hr)); if (FAILED(hr)) { XY_LOG_ERROR("Failed to unlock subpic. "<<XY_LOG_VAR_2_STR(hr)); } CRect dirty_rect; hr = m_pSubPic->GetDirtyRect(&dirty_rect); ASSERT(SUCCEEDED(hr)); if (!dirty_rect.IsRectEmpty()) { if (!m_use_dst_alpha) { hr = mem_subpic->FlipAlphaValue(dirty_rect);//fixme: mem_subpic.type is now MSP_RGBA_F, not MSP_RGBA ASSERT(SUCCEEDED(hr)); if (FAILED(hr)) { XY_LOG_ERROR("Failed. "<<XY_LOG_VAR_2_STR(hr)); return hr; } } } else { hr = S_FALSE; } } m_provider->Unlock(); if (hr == S_OK) { CRect video_rect(CPoint(0,0), m_original_video_size); m_xy_sub_render_frame = DEBUG_NEW XySubRenderFrameWrapper(mem_subpic, video_rect, video_rect, now, &hr); } else { m_xy_sub_render_frame = NULL; } return hr; }
STDMETHODIMP HdmvSubtitleProviderImpl::RequestFrame( IXySubRenderFrame**subRenderFrame, REFERENCE_TIME now ) { CheckPointer(subRenderFrame, E_POINTER); *subRenderFrame = NULL; HRESULT hr = NOERROR; POSITION pos; CSize MaxTextureSize, VideoSize; CPoint VideoTopLeft; pos = m_pSub->GetStartPosition(now); if (!pos) { return S_FALSE; } bool use_dst_alpha = false; hr = m_consumer->XyGetBool(DirectVobSubXyOptions::BOOL_SUB_FRAME_USE_DST_ALPHA, &use_dst_alpha); if (m_use_dst_alpha!=use_dst_alpha) { XY_LOG_INFO("Alpha type changed from "<<m_use_dst_alpha<<" to "<<use_dst_alpha); Invalidate(-1); m_use_dst_alpha = use_dst_alpha; } hr = m_pSub->GetTextureSize(pos, MaxTextureSize, VideoSize, VideoTopLeft); if (SUCCEEDED(hr)) { ASSERT(MaxTextureSize==VideoSize && VideoTopLeft==CPoint(0,0)); if (!(MaxTextureSize==VideoSize && VideoTopLeft==CPoint(0,0))) { XY_LOG_ERROR("We don't know how to deal with this sizes." <<XY_LOG_VAR_2_STR(MaxTextureSize)<<XY_LOG_VAR_2_STR(VideoSize) <<XY_LOG_VAR_2_STR(VideoTopLeft)); return E_FAIL; } } else { XY_LOG_ERROR("Failed to get sizes info"); return hr; } if (!m_allocator || m_cur_output_size!=MaxTextureSize) { m_cur_output_size = MaxTextureSize; if (m_cur_output_size.cx!=0 && m_cur_output_size.cy!=0) { hr = ResetAllocator(); ASSERT(SUCCEEDED(hr)); } else { XY_LOG_WARN("Invalid output size "<<m_cur_output_size); return S_FALSE; } } hr = Render( now, pos ); if (SUCCEEDED(hr) && m_xy_sub_render_frame) { *subRenderFrame = m_xy_sub_render_frame; (*subRenderFrame)->AddRef(); } return hr; }
HRESULT HdmvSubtitleProviderImpl::Render( REFERENCE_TIME now, POSITION pos ) { REFERENCE_TIME start = m_pSub->GetStart(pos); REFERENCE_TIME stop = m_pSub->GetStop(pos); if (!(start <= now && now < stop)) { return S_FALSE; } if(m_pSubPic && m_pSubPic->GetStart() <= now && now < m_pSubPic->GetStop()) { return S_OK; } //should always re-alloc one for the old be in used by the consumer m_pSubPic = NULL; ASSERT(m_allocator); if(FAILED(m_allocator->AllocDynamicEx(&m_pSubPic))) { XY_LOG_ERROR("Failed to allocate subpic"); return E_FAIL; } ASSERT(m_pSubPic); HRESULT hr = E_FAIL; CMemSubPic * mem_subpic = dynamic_cast<CMemSubPic*>((ISubPicEx *)m_pSubPic); ASSERT(mem_subpic); SubPicDesc spd; if(SUCCEEDED(m_pSubPic->Lock(spd))) { CRect dirty_rect; DWORD color = 0xFF000000; if(SUCCEEDED(m_pSubPic->ClearDirtyRect(color))) { m_pSub->Render(spd, now, dirty_rect); TRACE_SUB_PROVIDER(XY_LOG_VAR_2_STR(start)<<XY_LOG_VAR_2_STR(stop)); m_pSubPic->SetStart(start); m_pSubPic->SetStop(stop); } hr = m_pSubPic->Unlock(&dirty_rect); ASSERT(SUCCEEDED(hr)); if (FAILED(hr)) { XY_LOG_ERROR("Failed to unlock subtitle." <<XY_LOG_VAR_2_STR(hr)<<XY_LOG_VAR_2_STR(dirty_rect)); } if (!dirty_rect.IsRectEmpty()) { hr = m_pSubPic->GetDirtyRect(&dirty_rect); ASSERT(SUCCEEDED(hr)); if (!m_use_dst_alpha) { hr = mem_subpic->FlipAlphaValue(dirty_rect);//fixme: mem_subpic.type is now MSP_RGBA_F, not MSP_RGBA ASSERT(SUCCEEDED(hr)); if (FAILED(hr)) { XY_LOG_ERROR("Failed. "<<XY_LOG_VAR_2_STR(hr)); return hr; } } hr = S_OK; } else { hr = S_FALSE; } } if (hr == S_OK) { CRect video_rect(CPoint(0,0), m_cur_output_size); m_xy_sub_render_frame = DEBUG_NEW XySubRenderFrameWrapper(mem_subpic, video_rect, video_rect, now, &hr); } else { m_xy_sub_render_frame = NULL; } return hr; }