Skip to content

Commit

Permalink
SubRenderIntf: Use libass to render ASS subtitles
Browse files Browse the repository at this point in the history
  • Loading branch information
jesec committed Feb 11, 2019
1 parent cf8f5b2 commit 076f895
Show file tree
Hide file tree
Showing 15 changed files with 376 additions and 3 deletions.
17 changes: 17 additions & 0 deletions include/ass.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once
#include "ass.h"

struct ASS_LibraryDeleter
{
void operator()(ASS_Library* p) { if (p) ass_library_done(p); }
};

struct ASS_RendererDeleter
{
void operator()(ASS_Renderer* p) { if (p) ass_renderer_done(p); }
};

struct ASS_TrackDeleter
{
void operator()(ASS_Track* p) { if (p) ass_free_track(p); }
};
11 changes: 11 additions & 0 deletions src/filters/transform/vsfilter/DirectVobSubPropPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1901,6 +1901,8 @@ CXySubFilterMorePPage::CXySubFilterMorePPage(LPUNKNOWN pUnk, HRESULT* phr)
BindControl(IDC_AUTORELOAD, m_autoreload);
BindControl(IDC_INSTANTUPDATE, m_instupd);

BindControl(IDC_CHECKBOX_VS_ASS_RENDERING, m_vsassrendering);

BindControl(IDC_COMBO_COLOR_SPACE, m_combo_yuv_matrix);
BindControl(IDC_COMBO_YUV_RANGE, m_combo_yuv_range);
BindControl(IDC_COMBO_RGB_LEVEL, m_combo_rgb_level);
Expand Down Expand Up @@ -2037,6 +2039,9 @@ void CXySubFilterMorePPage::UpdateObjectData(bool fSave)
hr = m_pDirectVobSub->put_SubtitleReloader(m_fReloaderDisabled);
CHECK_N_LOG(hr, "Failed to set option");

hr = m_pDirectVobSubXy->XySetBool(DirectVobSubXyOptions::BOOL_VS_ASS_RENDERING, m_fVSAssRendering);
CHECK_N_LOG(hr, "Failed to set option");

hr = m_pDirectVobSubXy->XySetInt(DirectVobSubXyOptions::INT_YUV_RANGE, m_yuv_range);
CHECK_N_LOG(hr, "Failed to set option");
hr = m_pDirectVobSubXy->XySetInt(DirectVobSubXyOptions::INT_COLOR_SPACE, m_yuv_matrix);
Expand Down Expand Up @@ -2074,6 +2079,9 @@ void CXySubFilterMorePPage::UpdateObjectData(bool fSave)
hr = m_pDirectVobSub->get_SubtitleReloader(&m_fReloaderDisabled);
CHECK_N_LOG(hr, "Failed to get option");

hr = m_pDirectVobSubXy->XyGetBool(DirectVobSubXyOptions::BOOL_VS_ASS_RENDERING, &m_fVSAssRendering);
CHECK_N_LOG(hr, "Failed to get option");

hr = m_pDirectVobSubXy->XyGetInt(DirectVobSubXyOptions::INT_YUV_RANGE, &m_yuv_range);
CHECK_N_LOG(hr, "Failed to get option");
hr = m_pDirectVobSubXy->XyGetInt(DirectVobSubXyOptions::INT_COLOR_SPACE, &m_yuv_matrix);
Expand Down Expand Up @@ -2129,6 +2137,7 @@ void CXySubFilterMorePPage::UpdateControlData(bool fSave)
m_fAllowMoving = !!m_allowmoving.GetCheck();
m_fReloaderDisabled = !m_autoreload.GetCheck();

m_fVSAssRendering = !!m_vsassrendering.GetCheck();

if (m_combo_yuv_range.GetCurSel() != CB_ERR)
{
Expand Down Expand Up @@ -2228,6 +2237,8 @@ void CXySubFilterMorePPage::UpdateControlData(bool fSave)
m_autoreload.SetCheck(!m_fReloaderDisabled);
m_instupd.SetCheck(!!theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_INSTANTUPDATE), 1));

m_vsassrendering.SetCheck(m_fVSAssRendering);

if( m_yuv_range != CDirectVobSub::YuvRange_Auto &&
m_yuv_range != CDirectVobSub::YuvRange_PC &&
m_yuv_range != CDirectVobSub::YuvRange_TV )
Expand Down
4 changes: 3 additions & 1 deletion src/filters/transform/vsfilter/DirectVobSubPropPage.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,13 +291,15 @@ class CXySubFilterMorePPage : public CDVSBasePPage
int m_yuv_matrix, m_yuv_range, m_rgb_level;
SIZE m_layout_size;

bool m_fHideSubtitles, m_fAllowMoving, m_fReloaderDisabled;
bool m_fHideSubtitles, m_fAllowMoving, m_fReloaderDisabled, m_fVSAssRendering;
bool m_render_to_original_video_size;

int m_cache_size, m_auto_cache_size;

CButton m_hidesub, m_allowmoving, m_autoreload, m_instupd;

CButton m_vsassrendering;

CSpinButtonCtrl m_path_cache, m_scanline_cache, m_overlay_no_blur_cache, m_overlay_cache;

CSpinButtonCtrl m_layout_size_x, m_layout_size_y;
Expand Down
6 changes: 6 additions & 0 deletions src/filters/transform/vsfilter/IDirectVobSubXy.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ namespace DirectVobSubXyOptions

BOOL_ALLOW_MOVING,

BOOL_VS_ASS_RENDERING,

OPTION_COUNT
};
struct ColorSpaceOpt
Expand Down Expand Up @@ -246,6 +248,8 @@ namespace DirectVobSubXyOptions
{XyOptionsImpl::OPTION_TYPE_BOOL , XyOptionsImpl::OPTION_MODE_RW, BOOL_HIDE_SUBTITLES},
{XyOptionsImpl::OPTION_TYPE_BOOL , XyOptionsImpl::OPTION_MODE_RW, BOOL_ALLOW_MOVING},

{XyOptionsImpl::OPTION_TYPE_BOOL , XyOptionsImpl::OPTION_MODE_RW, BOOL_VS_ASS_RENDERING},

{XyOptionsImpl::OPTION_TYPE_SIZE , XyOptionsImpl::OPTION_MODE_READ, SIZE_ORIGINAL_VIDEO},
{XyOptionsImpl::OPTION_TYPE_SIZE , XyOptionsImpl::OPTION_MODE_READ, SIZE_ASS_PLAY_RESOLUTION},
{XyOptionsImpl::OPTION_TYPE_SIZE , XyOptionsImpl::OPTION_MODE_RW, SIZE_USER_SPECIFIED_LAYOUT_SIZE},
Expand Down Expand Up @@ -336,6 +340,8 @@ namespace DirectVobSubXyOptions
{XyOptionsImpl::OPTION_TYPE_BOOL , XyOptionsImpl::OPTION_MODE_RW, BOOL_HIDE_SUBTITLES},
{XyOptionsImpl::OPTION_TYPE_BOOL , XyOptionsImpl::OPTION_MODE_RW, BOOL_ALLOW_MOVING},

{XyOptionsImpl::OPTION_TYPE_BOOL , XyOptionsImpl::OPTION_MODE_RW, BOOL_VS_ASS_RENDERING},

{XyOptionsImpl::OPTION_TYPE_INT , XyOptionsImpl::OPTION_MODE_RW, INT_MAX_BITMAP_COUNT},
{XyOptionsImpl::OPTION_TYPE_BOOL , XyOptionsImpl::OPTION_MODE_RW, BOOL_COMBINE_BITMAPS},
{XyOptionsImpl::OPTION_TYPE_INT , XyOptionsImpl::OPTION_MODE_RW, INT_MAX_BITMAP_COUNT2},
Expand Down
141 changes: 141 additions & 0 deletions src/filters/transform/vsfilter/SubFrame.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
* Copyright(C) 2016-2017 Blitzker
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.If not, see <http://www.gnu.org/licenses/>.
*/

#include "stdafx.h"
#include "SubFrame.h"
#include <ppl.h>

namespace
{
inline POINT GetRectPos(RECT rect)
{
return {rect.left, rect.top};
}

inline SIZE GetRectSize(RECT rect)
{
return {rect.right - rect.left, rect.bottom - rect.top};
}
}

SubFrame::SubFrame(RECT rect, ULONGLONG id, ASS_Image* image)
: CUnknown("", nullptr)
, m_rect(rect)
, m_id(id)
, m_pixelsRect{}
{
Flatten(image);
}

STDMETHODIMP SubFrame::NonDelegatingQueryInterface(REFIID riid, void** ppv)
{
if (riid == __uuidof(ISubRenderFrame))
return GetInterface(static_cast<ISubRenderFrame*>(this), ppv);

return __super::NonDelegatingQueryInterface(riid, ppv);
}

STDMETHODIMP SubFrame::GetOutputRect(RECT* outputRect)
{
CheckPointer(outputRect, E_POINTER);
*outputRect = m_rect;
return S_OK;
}

STDMETHODIMP SubFrame::GetClipRect(RECT* clipRect)
{
CheckPointer(clipRect, E_POINTER);
*clipRect = m_rect;
return S_OK;
}

STDMETHODIMP SubFrame::GetBitmapCount(int* count)
{
CheckPointer(count, E_POINTER);
*count = (m_pixels ? 1 : 0);
return S_OK;
}

STDMETHODIMP SubFrame::GetBitmap(int index, ULONGLONG* id, POINT* position, SIZE* size, LPCVOID* pixels, int* pitch)
{
if (index != 0) return E_INVALIDARG;

if (!id && !position && !size && !pixels && !pitch)
return S_FALSE;

if (id)
*id = m_id;
if (position)
*position = GetRectPos(m_pixelsRect);
if (size)
*size = GetRectSize(m_pixelsRect);
if (pixels)
*pixels = m_pixels.get();
if (pitch)
*pitch = size->cx * 4;

return S_OK;
}

void SubFrame::Flatten(ASS_Image* image)
{
if (image)
{
for (auto i = image; i != nullptr; i = i->next)
{
RECT rect1 = m_pixelsRect;
RECT rect2 = {i->dst_x, i->dst_y, i->dst_x + i->w, i->dst_y + i->h};
UnionRect(&m_pixelsRect, &rect1, &rect2);
}

const POINT pixelsPoint = GetRectPos(m_pixelsRect);
const SIZE pixelsSize = GetRectSize(m_pixelsRect);
m_pixels = std::make_unique<uint32_t[]>(pixelsSize.cx * pixelsSize.cy);

for (auto i = image; i != nullptr; i = i->next)
{
concurrency::parallel_for(0, i->h, [&](int y)
{
for (int x = 0; x < i->w; ++x)
{
uint32_t& dest = m_pixels[(i->dst_y + y - pixelsPoint.y) * pixelsSize.cx +
(i->dst_x + x - pixelsPoint.x)];

uint32_t destA = (dest & 0xff000000) >> 24;

uint32_t srcA = i->bitmap[y * i->stride + x] * (0xff - (i->color & 0x000000ff));
srcA >>= 8;

uint32_t compA = 0xff - srcA;

uint32_t outA = srcA + ((destA * compA) >> 8);

uint32_t outR = ((i->color & 0xff000000) >> 8) * srcA + (dest & 0x00ff0000) * compA;
outR >>= 8;

uint32_t outG = ((i->color & 0x00ff0000) >> 8) * srcA + (dest & 0x0000ff00) * compA;
outG >>= 8;

uint32_t outB = ((i->color & 0x0000ff00) >> 8) * srcA + (dest & 0x000000ff) * compA;
outB >>= 8;

dest = (outA << 24) + (outR & 0x00ff0000) + (outG & 0x0000ff00) + (outB & 0x000000ff);
}
}, concurrency::static_partitioner());
}
}
}
50 changes: 50 additions & 0 deletions src/filters/transform/vsfilter/SubFrame.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright(C) 2016-2017 Blitzker
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include <ass.h>

class SubFrame final
: public CUnknown
, public ISubRenderFrame
{
public:

SubFrame(RECT rect, ULONGLONG id, ASS_Image* image);

DECLARE_IUNKNOWN;

// CUnknown
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv) override;

// ISubRenderFrame
STDMETHODIMP GetOutputRect(RECT* outputRect) override;
STDMETHODIMP GetClipRect(RECT* clipRect) override;
STDMETHODIMP GetBitmapCount(int* count) override;
STDMETHODIMP GetBitmap(int index, ULONGLONG* id, POINT* position, SIZE* size, LPCVOID* pixels, int* pitch) override;

private:

void Flatten(ASS_Image* image);

const RECT m_rect;
const ULONGLONG m_id;

std::unique_ptr<uint32_t[]> m_pixels;
RECT m_pixelsRect;
};
2 changes: 2 additions & 0 deletions src/filters/transform/vsfilter/VSFilter.rc
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,8 @@ BEGIN
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,127,132,10
EDITTEXT IDC_EDIT_CACHE_SIZE,22,72,40,14,ES_AUTOHSCROLL,WS_EX_RIGHT
RTEXT "Cache Size(MB)",IDC_LABLE_CACHE_SIZE,14,60,57,8
CONTROL "Use VSFilter (legacy) ASS implementation",IDC_CHECKBOX_VS_ASS_RENDERING,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,266,224,10
END


Expand Down
6 changes: 4 additions & 2 deletions src/filters/transform/vsfilter/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,14 +243,16 @@
#define IDC_COLORSHAD 1066
#define IDS_RG_ALLOWMOVING 1070
#define IDC_CHECKBOX_ALLOW_MOVING 1071
#define IDS_RG_VSASSRENDERING 1072
#define IDC_CHECKBOX_VS_ASS_RENDERING 1073

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 338
#define _APS_NEXT_RESOURCE_VALUE 339
#define _APS_NEXT_COMMAND_VALUE 32770
#define _APS_NEXT_CONTROL_VALUE 343
#define _APS_NEXT_CONTROL_VALUE 344
#define _APS_NEXT_SYMED_VALUE 210
#endif
#endif
Loading

0 comments on commit 076f895

Please sign in to comment.