1 // Copyright 2003-2006 Gabest
2 // http://www.gabest.org
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
17 // http://www.gnu.org/copyleft/gpl.html
21 #include "DirectVobSubFilter.h"
22 #include "..\..\..\DSUtil\DSUtil.h"
23 #include "..\..\..\DSUtil\MediaTypes.h"
26 #include "../../../../include/moreuuids.h"
27 #include "../../subpic/color_conv_table.h"
29 #include "xy_logger.h"
31 using namespace DirectVobSubXyIntOptions
;
33 static void LogSubPicStartStop( const REFERENCE_TIME
& rtStart
, const REFERENCE_TIME
& rtStop
, const CString
& msg
)
36 static REFERENCE_TIME s_rtStart
= -1, s_rtStop
= -1;
37 if(s_rtStart
!=rtStart
|| s_rtStop
!=rtStop
)
39 XY_LOG_INFO(msg
.GetString());
46 void BltLineRGB32(DWORD
* d
, BYTE
* sub
, int w
, const GUID
& subtype
)
48 if(subtype
== MEDIASUBTYPE_YV12
|| subtype
== MEDIASUBTYPE_I420
|| subtype
== MEDIASUBTYPE_IYUV
49 || subtype
== MEDIASUBTYPE_NV12
|| subtype
== MEDIASUBTYPE_NV21
)
53 BYTE
* dbtend
= db
+ w
;
55 for(; db
< dbtend
; sub
+=4, db
++)
59 int y
= ColorConvTable::Rgb2Y(sub
[2], sub
[1], sub
[0]);
60 *db
= y
; // w/o colors
64 else if(subtype
== MEDIASUBTYPE_P010
|| subtype
== MEDIASUBTYPE_P016
)
67 WORD
* db
= reinterpret_cast<WORD
*>(d
);
68 WORD
* dbtend
= db
+ w
;
70 for(; db
< dbtend
; sub
+=4, db
++)
74 int y
= ColorConvTable::Rgb2Y(sub
[2], sub
[1], sub
[0])<<2;
75 *db
= y
<<8; // w/o colors
79 else if(subtype
== MEDIASUBTYPE_YUY2
)
82 WORD
* dstend
= ds
+ w
;
84 for(; ds
< dstend
; sub
+=4, ds
++)
88 int y
= ColorConvTable::Rgb2Y(sub
[2], sub
[1], sub
[0]);
89 *ds
= 0x8000|y
; // w/o colors
93 else if(subtype
== MEDIASUBTYPE_RGB555
)
96 WORD
* dstend
= ds
+ w
;
98 for(; ds
< dstend
; sub
+=4, ds
++)
102 *ds
= ((*((DWORD
*)sub
)>>9)&0x7c00)|((*((DWORD
*)sub
)>>6)&0x03e0)|((*((DWORD
*)sub
)>>3)&0x001f);
106 else if(subtype
== MEDIASUBTYPE_RGB565
)
109 WORD
* dstend
= ds
+ w
;
111 for(; ds
< dstend
; sub
+=4, ds
++)
115 *ds
= ((*((DWORD
*)sub
)>>8)&0xf800)|((*((DWORD
*)sub
)>>5)&0x07e0)|((*((DWORD
*)sub
)>>3)&0x001f);
119 else if(subtype
== MEDIASUBTYPE_RGB24
)
122 BYTE
* dstend
= dt
+ w
*3;
124 for(; dt
< dstend
; sub
+=4, dt
+=3)
134 else if(subtype
== MEDIASUBTYPE_RGB32
|| subtype
== MEDIASUBTYPE_ARGB32
)
136 DWORD
* dstend
= d
+ w
;
138 for(; d
< dstend
; sub
+=4, d
++)
140 if(sub
[3] < 0xff) *d
= *((DWORD
*)sub
)&0xffffff;
146 void Scale2x(const GUID
& subtype
, BYTE
* d
, int dpitch
, BYTE
* s
, int spitch
, int w
, int h
)
148 if(subtype
== MEDIASUBTYPE_YV12
|| subtype
== MEDIASUBTYPE_I420
|| subtype
== MEDIASUBTYPE_IYUV
149 || subtype
== MEDIASUBTYPE_NV12
|| subtype
== MEDIASUBTYPE_NV21
)
155 for(s1
= s
, s2
= s
+ h
*spitch
, d1
= d
; s1
< s2
; d1
+= dpitch
) // TODO: replace this mess with mmx code
157 BYTE
* stmp
= s1
+ spitch
;
158 BYTE
* dtmp
= d1
+ dpitch
;
160 for(BYTE
* s3
= s1
+ (w
-1); s1
< s3
; s1
+= 1, d1
+= 2)
163 d1
[1] = (s1
[0]+s1
[1])>>1;
166 d1
[0] = d1
[1] = s1
[0];
175 AvgLines8(d
, h
*2, dpitch
);
177 else if(subtype
== MEDIASUBTYPE_P010
|| subtype
== MEDIASUBTYPE_P016
)
180 BYTE
* s1_end
= s
+ h
*spitch
;
183 for( ; s1
< s1_end
; s1
+= spitch
, d1
+= dpitch
)
185 WORD
* s2
= reinterpret_cast<WORD
*>(s1
);
186 WORD
* s2_end
= reinterpret_cast<WORD
*>(s1
) + (w
-1);
187 WORD
* d2
= reinterpret_cast<WORD
*>(d1
);
189 for( ; s2
< s2_end
; s2
++, d2
+= 2)
192 d2
[1] = (s2
[0]+s2
[1])>>1;
194 d2
[0] = d2
[1] = s1
[0];
197 AvgLines8(d
, h
*2, dpitch
);
199 else if(subtype
== MEDIASUBTYPE_YUY2
)
201 unsigned __int64 __0xffffffff00000000
= 0xffffffff00000000;
202 unsigned __int64 __0x00000000ffffffff
= 0x00000000ffffffff;
203 unsigned __int64 __0x00ff00ff00ff00ff
= 0x00ff00ff00ff00ff;
209 for(s1
= s
, s2
= s
+ h
*spitch
, d1
= d
; s1
< s2
; d1
+= dpitch
)
211 BYTE
* stmp
= s1
+ spitch
;
212 BYTE
* dtmp
= d1
+ dpitch
;
214 // row0, 4 pixels: y1|u1|y2|v1|y3|u2|y4|v2
216 // row0, 8 pixels: y1|u1|(y1+y2)/2|v1|y2|(u1+u2)/2|(y2+y3)/2|(v1+v2)/2
227 movq mm4
, __0x00ff00ff00ff00ff
228 movq mm5
, __0x00000000ffffffff
229 movq mm6
, __0xffffffff00000000
234 pand mm0
, mm4
// mm0 = 00y400y300y200y1
235 psrlw mm2
, 8 // mm2 = 00u200v200u100v1
240 pand mm0
, mm5
// mm0 = 0000000000y200y1
243 pand mm1
, mm6
// mm1 = 00y300y200000000
245 por mm1
, mm0
// mm1 = 00y300y200y200y1
247 punpcklwd mm0
, mm0
// mm0 = 00y200y200y100y1
250 psrlw mm0
, 1 // mm0 = (mm0 + mm1) / 2
254 punpckldq mm1
, mm1
// mm1 = 00u100v100u100v1
257 psrlw mm1
, 1 // mm1 = (mm1 + mm2) / 2
261 por mm0
, mm1
// mm0 = (v1+v2)/2|(y2+y3)/2|(u1+u2)/2|y2|v1|(y1+y2)/2|u1|y1
277 *d1
++ =(s1
[0]+s1
[2])>>1;
291 AvgLines8(d
, h
*2, dpitch
);
293 else if(subtype
== MEDIASUBTYPE_RGB555
)
299 for(s1
= s
, s2
= s
+ h
*spitch
, d1
= d
; s1
< s2
; d1
+= dpitch
) // TODO: replace this mess with mmx code
301 BYTE
* stmp
= s1
+ spitch
;
302 BYTE
* dtmp
= d1
+ dpitch
;
304 for(BYTE
* s3
= s1
+ (w
-1)*2; s1
< s3
; s1
+= 2, d1
+= 4)
306 *((WORD
*)d1
) = *((WORD
*)s1
);
308 ((((*((WORD
*)s1
)&0x7c00) + (*((WORD
*)s1
+1)&0x7c00)) >> 1)&0x7c00)|
309 ((((*((WORD
*)s1
)&0x03e0) + (*((WORD
*)s1
+1)&0x03e0)) >> 1)&0x03e0)|
310 ((((*((WORD
*)s1
)&0x001f) + (*((WORD
*)s1
+1)&0x001f)) >> 1)&0x001f);
313 *((WORD
*)d1
) = *((WORD
*)s1
);
314 *((WORD
*)d1
+1) = *((WORD
*)s1
);
323 AvgLines555(d
, h
*2, dpitch
);
325 else if(subtype
== MEDIASUBTYPE_RGB565
)
331 for(s1
= s
, s2
= s
+ h
*spitch
, d1
= d
; s1
< s2
; d1
+= dpitch
) // TODO: replace this mess with mmx code
333 BYTE
* stmp
= s1
+ spitch
;
334 BYTE
* dtmp
= d1
+ dpitch
;
336 for(BYTE
* s3
= s1
+ (w
-1)*2; s1
< s3
; s1
+= 2, d1
+= 4)
338 *((WORD
*)d1
) = *((WORD
*)s1
);
340 ((((*((WORD
*)s1
)&0xf800) + (*((WORD
*)s1
+1)&0xf800)) >> 1)&0xf800)|
341 ((((*((WORD
*)s1
)&0x07e0) + (*((WORD
*)s1
+1)&0x07e0)) >> 1)&0x07e0)|
342 ((((*((WORD
*)s1
)&0x001f) + (*((WORD
*)s1
+1)&0x001f)) >> 1)&0x001f);
345 *((WORD
*)d1
) = *((WORD
*)s1
);
346 *((WORD
*)d1
+1) = *((WORD
*)s1
);
355 AvgLines565(d
, h
*2, dpitch
);
357 else if(subtype
== MEDIASUBTYPE_RGB24
)
363 for(s1
= s
, s2
= s
+ h
*spitch
, d1
= d
; s1
< s2
; d1
+= dpitch
) // TODO: replace this mess with mmx code
365 BYTE
* stmp
= s1
+ spitch
;
366 BYTE
* dtmp
= d1
+ dpitch
;
368 for(BYTE
* s3
= s1
+ (w
-1)*3; s1
< s3
; s1
+= 3, d1
+= 6)
373 d1
[3] = (s1
[0]+s1
[3])>>1;
374 d1
[4] = (s1
[1]+s1
[4])>>1;
375 d1
[5] = (s1
[2]+s1
[5])>>1;
378 d1
[0] = d1
[3] = s1
[0];
379 d1
[1] = d1
[4] = s1
[1];
380 d1
[2] = d1
[5] = s1
[2];
389 AvgLines8(d
, h
*2, dpitch
);
391 else if(subtype
== MEDIASUBTYPE_RGB32
|| subtype
== MEDIASUBTYPE_ARGB32
)
397 for(s1
= s
, s2
= s
+ h
*spitch
, d1
= d
; s1
< s2
; d1
+= dpitch
)
399 BYTE
* stmp
= s1
+ spitch
;
400 BYTE
* dtmp
= d1
+ dpitch
;
415 punpcklbw mm1
, mm0
// mm1 = 00xx00r100g100b1
416 punpckhbw mm2
, mm0
// mm2 = 00xx00r200g200b2
419 psrlw mm2
, 1 // mm2 = (mm1 + mm2) / 2
435 *((DWORD
*)d1
) = *((DWORD
*)s1
);
436 *((DWORD
*)d1
+1) = *((DWORD
*)s1
);
445 AvgLines8(d
, h
*2, dpitch
);
451 HRESULT
Copy(BYTE
* pSub
, BYTE
* pIn
, CSize sub
, CSize in
, int bpp
, const GUID
& subtype
, DWORD black
)
453 int wIn
= in
.cx
, hIn
= in
.cy
, pitchIn
= wIn
*bpp
>>3;
454 int wSub
= sub
.cx
, hSub
= sub
.cy
, pitchSub
= wSub
*bpp
>>3;
455 bool fScale2x
= wIn
*2 <= wSub
;
457 if(fScale2x
) wIn
<<= 1, hIn
<<= 1;
459 int left
= ((wSub
- wIn
)>>1)&~1;
461 int right
= left
+ ((wSub
- wIn
)&1);
463 int dpLeft
= left
*bpp
>>3;
464 int dpMid
= mid
*bpp
>>3;
465 int dpRight
= right
*bpp
>>3;
472 j
+= (hSub
- hIn
) >> 1;
474 for(; i
< j
; i
++, pSub
+= pitchSub
)
476 memsetd(pSub
, black
, dpLeft
+dpMid
+dpRight
);
482 pIn
+= pitchIn
* ((hIn
- hSub
) >> (fScale2x
?2:1));
487 pSub
+ dpLeft
, pitchSub
, pIn
, pitchIn
,
488 in
.cx
, (min(j
, hSub
) - i
) >> 1);
490 for(int k
= min(j
, hSub
); i
< k
; i
++, pIn
+= pitchIn
, pSub
+= pitchSub
)
492 memsetd(pSub
, black
, dpLeft
);
493 memsetd(pSub
+ dpLeft
+dpMid
, black
, dpRight
);
498 for(int k
= min(j
, hSub
); i
< k
; i
++, pIn
+= pitchIn
, pSub
+= pitchSub
)
500 memsetd(pSub
, black
, dpLeft
);
501 memcpy(pSub
+ dpLeft
, pIn
, dpMid
);
502 memsetd(pSub
+ dpLeft
+dpMid
, black
, dpRight
);
508 for(; i
< j
; i
++, pSub
+= pitchSub
)
510 memsetd(pSub
, black
, dpLeft
+dpMid
+dpRight
);
517 HRESULT
CDirectVobSubFilter::Copy(BYTE
* pSub
, BYTE
* pIn
, CSize sub
, CSize in
, int bpp
, const GUID
& subtype
, DWORD black
)
519 return ::Copy(pSub
, pIn
, sub
, in
, bpp
, subtype
, black
);
522 void CDirectVobSubFilter::PrintMessages(BYTE
* pOut
)
527 const GUID
& subtype
= m_pOutput
->CurrentMediaType().subtype
;
529 BITMAPINFOHEADER bihOut
;
530 ExtractBIH(&m_pOutput
->CurrentMediaType(), &bihOut
);
536 tmp
.Format(_T("in: %dx%d %s\nout: %dx%d %s\n"),
538 Subtype2String(m_pInput
->CurrentMediaType().subtype
),
539 bihOut
.biWidth
, bihOut
.biHeight
,
540 Subtype2String(m_pOutput
->CurrentMediaType().subtype
));
543 tmp
.Format(_T("real fps: %.3f, current fps: %.3f\nmedia time: %d, subtitle time: %d [ms]\nframe number: %d (calculated)\nrate: %.4f\n"),
544 m_fps
, m_fMediaFPSEnabled
?m_MediaFPS
:fabs(m_fps
),
545 (int)m_tPrev
.Millisecs(), (int)(CalcCurrentTime()/10000),
546 (int)(m_tPrev
.m_time
* m_fps
/ 10000000),
547 m_pInput
->CurrentRate());
550 CAutoLock
cAutoLock(&m_csQueueLock
);
552 if(m_simple_provider
)
555 REFERENCE_TIME rtNow
= -1, rtStart
= -1, rtStop
= -1;
556 m_simple_provider
->GetStats(nSubPics
, rtNow
, rtStart
, rtStop
);
557 tmp
.Format(_T("queue stats: %I64d - %I64d [ms]\n"), rtStart
/10000, rtStop
/10000);
560 for(int i
= 0; i
< nSubPics
; i
++)
562 m_simple_provider
->GetStats(i
, rtStart
, rtStop
);
563 tmp
.Format(_T("%d: %I64d - %I64d [ms]\n"), i
, rtStart
/10000, rtStop
/10000);
566 LogSubPicStartStop(rtStart
, rtStop
, tmp
);
570 tmp
.Format( _T("Colorspace: %ls %ls (%ls)\n"),
571 ColorConvTable::GetDefaultRangeType()==ColorConvTable::RANGE_PC
? _T("PC"):_T("TV"),
572 ColorConvTable::GetDefaultYUVType()==ColorConvTable::BT601
? _T("BT.601"):_T("BT.709"),
573 m_xy_int_opt
[INT_COLOR_SPACE
]==CDirectVobSub::YuvMatrix_AUTO
? _T("Auto") :
574 m_xy_int_opt
[INT_COLOR_SPACE
]==CDirectVobSub::GUESS
? _T("Guessed") : _T("Forced") );
577 SIZE layout_size
, script_playres
;
578 XyGetSize(SIZE_LAYOUT_WITH
, &layout_size
);
579 XyGetSize(SIZE_ASS_PLAY_RESOLUTION
, &script_playres
);
580 tmp
.Format( _T("Layout with size %dx%d, script playres %dx%d\n"),
581 layout_size
.cx
, layout_size
.cy
, script_playres
.cx
, script_playres
.cy
);
585 CachesInfo
*caches_info
= NULL
;
586 XyFlyWeightInfo
*xy_fw_info
= NULL
;
588 XyGetBin(DirectVobSubXyIntOptions::BIN_CACHES_INFO
, reinterpret_cast<LPVOID
*>(&caches_info
), &tmp_size
);
589 XyGetBin(DirectVobSubXyIntOptions::BIN_XY_FLY_WEIGHT_INFO
, reinterpret_cast<LPVOID
*>(&xy_fw_info
), &tmp_size
);
593 _T("Cache :stored_num/hit_count/query_count\n")\
594 _T(" Parser cache 1:%ld/%ld/%ld\n")\
595 _T(" Parser cache 2:%ld/%ld/%ld\n")\
597 _T(" LV 4:%ld/%ld/%ld\t\t")\
598 _T(" LV 3:%ld/%ld/%ld\n")\
599 _T(" LV 2:%ld/%ld/%ld\t\t")\
600 _T(" LV 1:%ld/%ld/%ld\n")\
601 _T(" LV 0:%ld/%ld/%ld\n")\
603 _T(" bitmap :%ld/%ld/%ld\t\t")\
604 _T(" scan line:%ld/%ld/%ld\n")\
605 _T(" relay key:%ld/%ld/%ld\t\t")\
606 _T(" clipper :%ld/%ld/%ld\n")\
608 _T(" FW string pool :%ld/%ld/%ld\t\t")\
609 _T(" FW bitmap key pool:%ld/%ld/%ld\n")\
611 caches_info
->text_info_cache_cur_item_num
, caches_info
->text_info_cache_hit_count
, caches_info
->text_info_cache_query_count
,
612 caches_info
->word_info_cache_cur_item_num
, caches_info
->word_info_cache_hit_count
, caches_info
->word_info_cache_query_count
,
613 caches_info
->path_cache_cur_item_num
, caches_info
->path_cache_hit_count
, caches_info
->path_cache_query_count
,
614 caches_info
->scanline_cache2_cur_item_num
, caches_info
->scanline_cache2_hit_count
, caches_info
->scanline_cache2_query_count
,
615 caches_info
->non_blur_cache_cur_item_num
, caches_info
->non_blur_cache_hit_count
, caches_info
->non_blur_cache_query_count
,
616 caches_info
->overlay_cache_cur_item_num
, caches_info
->overlay_cache_hit_count
, caches_info
->overlay_cache_query_count
,
617 caches_info
->interpolate_cache_cur_item_num
, caches_info
->interpolate_cache_hit_count
, caches_info
->interpolate_cache_query_count
,
618 caches_info
->bitmap_cache_cur_item_num
, caches_info
->bitmap_cache_hit_count
, caches_info
->bitmap_cache_query_count
,
619 caches_info
->scanline_cache_cur_item_num
, caches_info
->scanline_cache_hit_count
, caches_info
->scanline_cache_query_count
,
620 caches_info
->overlay_key_cache_cur_item_num
, caches_info
->overlay_key_cache_hit_count
, caches_info
->overlay_key_cache_query_count
,
621 caches_info
->clipper_cache_cur_item_num
, caches_info
->clipper_cache_hit_count
, caches_info
->clipper_cache_query_count
,
623 xy_fw_info
->xy_fw_string_w
.cur_item_num
, xy_fw_info
->xy_fw_string_w
.hit_count
, xy_fw_info
->xy_fw_string_w
.query_count
,
624 xy_fw_info
->xy_fw_grouped_draw_items_hash_key
.cur_item_num
, xy_fw_info
->xy_fw_grouped_draw_items_hash_key
.hit_count
, xy_fw_info
->xy_fw_grouped_draw_items_hash_key
.query_count
627 delete []caches_info
;
630 if(msg
.IsEmpty()) return;
632 HANDLE hOldBitmap
= SelectObject(m_hdc
, m_hbm
);
633 HANDLE hOldFont
= SelectObject(m_hdc
, m_hfont
);
635 SetTextColor(m_hdc
, 0xffffff);
636 SetBkMode(m_hdc
, TRANSPARENT
);
637 SetMapMode(m_hdc
, MM_TEXT
);
640 GetObject(m_hbm
, sizeof(BITMAP
), &bm
);
642 CRect
r(0, 0, bm
.bmWidth
, bm
.bmHeight
);
643 DrawText(m_hdc
, msg
, _tcslen(msg
), &r
, DT_CALCRECT
|DT_EXTERNALLEADING
|DT_NOPREFIX
|DT_WORDBREAK
);
646 r
&= CRect(0, 0, bm
.bmWidth
, bm
.bmHeight
);
648 DrawText(m_hdc
, msg
, _tcslen(msg
), &r
, DT_LEFT
|DT_TOP
|DT_NOPREFIX
|DT_WORDBREAK
);
650 BYTE
* pIn
= (BYTE
*)bm
.bmBits
;
651 int pitchIn
= bm
.bmWidthBytes
;
652 int pitchOut
= bihOut
.biWidth
* bihOut
.biBitCount
>> 3;
654 if( subtype
== MEDIASUBTYPE_YV12
|| subtype
== MEDIASUBTYPE_I420
|| subtype
== MEDIASUBTYPE_IYUV
655 || subtype
== MEDIASUBTYPE_NV12
|| subtype
==MEDIASUBTYPE_NV21
)
656 pitchOut
= bihOut
.biWidth
;
657 else if (subtype
== MEDIASUBTYPE_P010
|| subtype
== MEDIASUBTYPE_P016
)
658 pitchOut
= bihOut
.biWidth
* 2;
660 pitchIn
= (pitchIn
+3)&~3;
661 pitchOut
= (pitchOut
+3)&~3;
663 if(bihOut
.biHeight
> 0 && bihOut
.biCompression
<= 3) // flip if the dst bitmap is flipped rgb (m_hbm is a top-down bitmap, not like the subpictures)
665 pOut
+= pitchOut
* (abs(bihOut
.biHeight
)-1);
666 pitchOut
= -pitchOut
;
669 pIn
+= pitchIn
* r
.top
;
670 pOut
+= pitchOut
* r
.top
;
672 for(int w
= min(r
.right
, m_w
), h
= r
.Height(); h
--; pIn
+= pitchIn
, pOut
+= pitchOut
)
674 BltLineRGB32((DWORD
*)pOut
, pIn
, w
, subtype
);
675 memsetd(pIn
, 0xff000000, r
.right
*4);
678 SelectObject(m_hdc
, hOldBitmap
);
679 SelectObject(m_hdc
, hOldFont
);