2013-05-31 3 views
0

비디오 실시간 스트림을 다운로드하는 알고리즘을 작성하려고합니다. 특히 내가 가져 오려고하는 각 스트림은 동적으로 .m3u8 재생 목록 파일을 기반으로하며,이 파일은 새 비디오 파일의 URI를 주기적으로 제공합니다. 주요 목표는 개별 미디어 파일을 하나의 일관된 InputStream으로 결합하는 것입니다.
실제로 작동시키기에 성공했습니다. 정기적으로 재생 목록에 나타나는 새 미디어 파일을 확인하고 HTTP 스트림을 사용자 지정 InputStream 구현 즉, InputStreamChain으로 전달합니다. 라이브 스트림이기 때문에 최소한 무한한이라고 가정합니다. Ergo, 내 InputStreamChainread()이 -1을 보내지 않기를 바랬다. 불행하게도, 그것은했다. 대기열에있는 모든 미디어 스트림이 소비 될 때마다 InputStreamChain이 종료되었습니다. 대신 새로운 미디어 파일이 도착할 때까지 I/O를 차단하고 싶었습니다. 그래서 저는 작업 솔루션을 생각해 냈습니다. read() 메서드를 사용하여 새로운 스트림이있을 때까지 루프를 조정했습니다 (TimerTask은 새 파일을 제공함). 내가이에되어있어 어떻게 그 일을 아니에요 나는 느낌이, 작동하는 것 같다 있지만InputStream의 read() 블록 입출력

public int read() throws IOException { 
    int bit = current.read(); 
    if (bit == -1 && streams.size() > 0) { 
     // left out due to lacking relevance 
    } else if(bit == -1 && streams.size() == 0) { 
     while(streams.size() == 0) { 
      Thread.currentThread().sleep(50); 
     } 
     return read(); 
    } 
    return bit; 
} 

: 루프에서 필자는 CPU의 부하를 줄이기 위해, Thread.sleep() 내장되어 있습니다. 또한 LockCondition.await()과 함께 사용해 보았습니다. 그러나 TimerTaskCondition.signal()을 트리거하려고 시도했을 때, 단지 IllegalMonitorStateException을 던졌습니다.

나는 특히 내 시나리오에서의 InputStream의 read() 방법을 차단/연기해야하는지 방법으로 왜 나는 질문 부탁 해요 것
?

편집

: 완성도를 위해서

는, 나도 내 실패 Lock 접근 방식을 제공하겠습니다 :

private ReentrantLock ioLock; 
private Condition ioCond; 
private boolean waitingForStream = false; 

public InputStreamChain() { 
    ioLock = new ReentrantLock(); 
    ioCond = ioLock.newCondition(); 
} 

public synchronized InputStreamChain addInputStream(final InputStream stream) { 
    streams.addLast(stream); 
    if (current == null) { 
     current = streams.removeFirst(); 
    } 
    if(waitingForStream) { 
     ioCond.signal(); 
    } 
    return this; 
} 

public int read() throws IOException { 
    int bit = current.read(); 
    if (bit == -1 && streams.size() > 0) { 
     // do stuff 
    } else if(bit == -1) { 
     waitingForStream = true; 
     ioLock.lock(); 
     try { 
      ioCond.await(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } finally { 
      waitingForStream = false; 
      ioLock.unlock(); 
     } 
     return read(); 
    } 
    return bit; 
} 
+0

상태 신호를 보내고 상태를 기다리는 데는 잠금 장치가 있어야합니다. – Flavio

+0

@Flavio 나는 내 머리 꼭대기에서 나의 '잠금'접근법을 적어 봤다. 나는 어디로 잘못 갔는가? – MCL

+0

'cond.signal()','lock.unlock()'전에 lock.lock()을 호출해야합니다. – Flavio

답변

1

아마 당신은 동기화 된 블록을 사용하고 있지 않습니다. 예를 들면 다음과 같습니다.

class MyReader 
{ 
    public int read() throws IOException { 
     int bit = current.read(); 
     if (bit == -1 && streams.size() > 0) { 
      // left out due to lacking relevance 
     } else if(bit == -1 && streams.size() == 0) { 
      waitForNextStream(); 
      return read(); 
     } 
     return bit; 
    } 

    private synchronized void waitForNextStream() 
    { 
     // TODO add close handling, set current here 
     while (streams.isEmpty()) 
     { 
      wait(); 
     } 
    } 


    public synchronized void addNextStream(InputStream is) 
    { 
     streams.add(is); 
     notify(); 
    } 
} 
+0

감사합니다 발레리! 꽤 좋아 보인다. 내 경우에는'addInputStream()'메쏘드 안에'notify()'를 넣어야 할 것으로 생각한다. +1 지금 ... 최대한 빨리 테스트하겠습니다. – MCL

+1

@MCL'synchronized '블록을 잊지 마라. 그것들 없이는 작동하지 않을 것입니다. –

+0

좋습니다, 제안대로 구현했지만 완벽하게 작동합니다. 아무튼, 나는 몇 가지 질문이있다 : 1. 왜 당신은 'wait()'를 하나의 루프로 묶고 있는가? 문서들에 따르면'wait()'는 다음'notify()'를 기다릴 것입니다. 나는 그것을 시도하고, 또한 루프없이 작동합니다. 2. InputStreams에 관해서는 IO 블로킹의 특별한 방법이 있지만, 그 의미가 무엇인지 알 수는 없다.이것은 말한 방식입니까 아니면 다른 가능성이 있습니까? – MCL

관련 문제