자막처리 신호를 어디서 얻어야 할지..

senah의 이미지

안녕하세요. 자막처리 부분을 만들다가 골치를 썩이는 부분이 있어서 질문 올립니다.

DirectShow를 사용해서 동영상 플레이어를 제작하고 있는데, 자막이야 SAMI 형식의 자막데이터는 널 렌더링으로 처리해도 그럭저럭 화면에 오버레이가 되지만, 지금 구현하려는 것은 SAMI 형식의 자막 데이터가 아니라, 다른 XML 형식의 파일에서 데이터를 읽어들여 오버레이 할 필요없이 아무 윈도우에나 출력하면 됩니다. 그러니까, 자막을 출력할 정확한 시점을 얻는 것이 문제인데..

여기가 문제입니다. 일단 처음 생각한 것은 타이머를 걸어서 일정한 시간마다 IMediaSeeking 인터페이스를 사용해서 GetCurrentPosition() 메서드를 호출하고, 자막 데이터가 가진 적절한 위치와 비교해서 해당 윈도우에 출력하게 하면 되지 않을까 했었는데.. 타이머에서 GetCurrentPosition()으로 가져오는 값을 살펴보니, 실행할 때 항상 동일한 값을 가져오는 것은 아니더군요. 그러니까, 1초에서 가져오는 값, 2초에서 가져오는 값이 실행할 때 매번 같지는 않다는 겁니다.

그래도, 값만 일단 비슷한 곳에 있다고 한다면 일정 범위를 정해줘서 해당 범위 내에 자막이 떠야할 시점을 잡을 수 있겠는데.. 이것도 문제가 됩니다.

IMediaSeeking에서 GetCurrentPosition()을 호출하기 전에, 적절한 타임 포맷이 미디어 파일에서 지원되는지 알아보고, 시험삼아 돌려본 파일에서는 TIME_FORMAT_FRAME 형식을 지원하길래, 이것으로 한번 테스트해보았습니다. 임의의 자막이 떠야할 시점을 200000 프레임의 위치에 설정하고, 값의 +50000 ~ -50000? 정도의 범위에서 지정했는데.. 타이머의 주기를 아무리 낮추어봐도 정확하게 처리가 안 됩니다.

자막의 싱크를 맞추는데 필요한 동기 신호를 정확하게 얻으려면 어떻게 해야 하는지.. 쩝..

MSDN 뒤져보고, IMediaPosition 인터페이스의 get_Position()을 사용하면 초 단위의 그럭저럭한 값은 얻어낼 수 있지만.. 뭔가 좀 이상한 것 같은 느낌이 드네요. 다른 일반적인 방법이 있을 듯 한데..

kkb110의 이미지

제가 정확히 이해를 한 것인지는 모르겠는데요.

지금 구현하시는 방법은 계속 GetCurrentPosition()을 호출을 해서..
만약 지금이 2.1초라고 찍혔으면 대략 2.0~2.2초정도에 바뀌는 자막이 있는지 검사한 뒤 있으면 바꾸는.. 그런건가요?

만약 그렇다면, 타이머 주기를 낮추어도 정확하게 처리가 안된다고 하시는 것은
자막이 표시될 시점을 건너 뛰는 현상이 발생한다는 것인지 아니면 예상보다 살짝 빨리나 늦게 표시된다는 것인지요?

senah의 이미지

프레임 타임 포맷 형식으로 된 것에서는, 예를 든 시간 대에서 가져오는 프레임 시간대가 항상 같은 결과를 보인다는 것이 힘들 정도로 들쭉날쭉합니다. 아마도, 윈도우의 WM_TIMER 메세지가 대체로 항상 그 주기마다 보내지기는 하지만, WM_TIMER 메세지는 윈도우가 경우에 따라서는 무시해버릴 수도 있는 메세지라는 점도 작용한 것 같습니다.

그래서, IMediaPosition 인터페이스를 사용해서 초 단위로 값을 받는다고 했을때, 동일한 타이머를 작동시켜 GetCurrentPosition()을 받아봐도 소수점 첫번째 자리부터 실행시마다 같은 값을 가지지 않습니다.

그래서, 자막을 처리하는데 기준이 되는 시그널을 어떻게 얻어야 할지 지금 난감합니다.

kkb110의 이미지

정확한 현재 플레이 시간을 알 수 있는 함수가GetCurrentPosition()밖에 없다고 했을 때
약간은 비효율적이지만 정확한 방법은..

스레드를 하나 만들어서 루프를 돌려서 검사해서 바꾸는것이겠지요

while(1)
{
if (GetCurrentTime() > sometime)
{
//자막바꿈
}
sleep(1); // 불필요한 점유율을 낮추기위해. 스레드 전환 강제 발생
}

sleep이 들어갔기 때문에 오버해드가 생각만큼 클 것 같지는 않지만 여기서 불필요한 점유율을 낮추고싶으면
타이머를 사용해서 자막이 바뀌는 근처시간 (가령 0.2초 전이라던지)에 스레드를 살리고.
자막이 바뀌는순간 스레드를 정지시키고 다시 타이머로 다음 자막 근처시간에 스레드를 작동시키고.. 하면 될 것 같습니다.

약간은 무식하다면 무식한 방법인데 현재 할 수 있는 방법 중에는 가장 정확한 방법일 것 같군요.

Prentice의 이미지

일단 저는 자막이나 비디오처리에 대해서는 거의 아무것도 모르지만... 오디오 부분의 샘플링레이트가 44100 Hz나 48000 Hz라고 가정하면 (이상적인 경우) 1초에 4만번 이상 분기점을 찾을 수 있습니다. 이걸 이용해보시면 어떨까요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.