2012-04-06 2 views
3

Клиент, указанный ниже, предназначен для запуска приложения oflaDemo, работающего на red5 на localhost. Он содержит промо-ролика с фильмом.Red5 Воспроизведение RTMPClient начинает отбрасывать сообщения, если проигрывается полный поток

Проблема в том, что клиент читает 15 секунд фильма и зависает. Зачем?

Чтобы скомпилировать программу ниже, просто скачайте red5 отсюда http://wiki.red5.org/wiki/1_0_RC1, установите его и запустите. Откройте корневую страницу http://localhost:5080 и перейдите на страницу установки демонстрационных версий. Установите образец oflaDemo. Затем перейдите на страницу tolaDemo и проверьте, работает ли она.

Затем создайте новый проект Java со всеми баночками из red5 в качестве библиотеки. Запустите его с запуском red5.

Клиент связывается с сервером через порт 1935.

Структура приложения следующим образом:

1) connect() метод подключается к приложению

connectCallback 2) от результата предыдущей операции создается новый поток; Библиотечная функция не используется для введения пользовательского потока класса

3) createStreamCallback это инъекционное на результате создания потока

4) пользовательский поток MyClientStream; он просто печатает то, что было отправлено

На моей машине я работаю до отметки времени 15203 и висит.

public class SSCCE_RTMPPlayer extends RTMPClient{ 

private String server = "localhost"; 
private int port = 1935; 
private String application = "oflaDemo"; 
private String filename = "avatar.flv"; 

private static boolean finished = false; 

public static void main(String[] args) throws InterruptedException { 

    final SSCCE_RTMPPlayer player = new SSCCE_RTMPPlayer(); 
    player.connect(); 

    synchronized(SSCCE_RTMPPlayer.class) { 
     if(!finished) SSCCE_RTMPPlayer.class.wait(); 
    } 

    System.out.println("Ended"); 
} 

public void connect() { 
    connect(server, port, application, connectCallback); 

    setExceptionHandler(new ClientExceptionHandler() { 

     @Override 
     public void handleException(Throwable throwable) { 
      throwable.printStackTrace(); 
     } 
    }); 
} 

private IPendingServiceCallback connectCallback = new IPendingServiceCallback() { 
    @Override 
    public void resultReceived(IPendingServiceCall call) { 
     System.out.println("connectCallback"); 
     invoke("createStream", null, createStreamCallback); 
    } 
}; 

private IPendingServiceCallback createStreamCallback = new IPendingServiceCallback() { 
    @Override 
    public void resultReceived(IPendingServiceCall call) { 
     Integer streamIdInteger = (Integer) call.getResult(); 
     MyClientStream myClientStream = new MyClientStream(); 
     myClientStream.setStreamId(streamIdInteger.intValue()); 
     myClientStream.setConnection(conn); 
     conn.addClientStream(myClientStream); 


     play(streamIdInteger.intValue(), filename, 0, -2); 
    } 
}; 

protected void onInvoke(RTMPConnection conn, Channel channel, Header header, Notify notify, RTMP rtmp) { 
    super.onInvoke(conn, channel, header, notify, rtmp); 
    System.out.println("onInvoke, header = " + header.toString()); 
    System.out.println("onInvoke, notify = " + notify.toString()); 
    System.out.println("onInvoke, rtmp = " + rtmp.toString()); 

}; 

public static class MyClientStream extends AbstractClientStream implements IEventDispatcher { 

    @Override 
    public void start() { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void stop() { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void close() { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void dispatchEvent(IEvent event) { 
     System.out.println("AudioListenerClientStream.dispachEvent()" + event.toString()); 
    } 

} 

} 

ОБНОВЛЕНИЕ 1

версия с обычными setStreamEventDispatcher() ведет себя таким же образом.

public class SSCCE_RTMPPlayer2 extends RTMPClient { 

private String server = "localhost"; 
private int port = 1935; 
private String application = "oflaDemo"; 
private String filename = "avatar.flv"; 

private static boolean finished = false; 

public static void main(String[] args) throws InterruptedException { 

    final SSCCE_RTMPPlayer2 player = new SSCCE_RTMPPlayer2(); 
    player.connect(); 

    synchronized(SSCCE_RTMPPlayer.class) { 
     if(!finished) SSCCE_RTMPPlayer.class.wait(); 
    } 

    System.out.println("Ended"); 
} 

public void connect() { 

    setExceptionHandler(new ClientExceptionHandler() { 

     @Override 
     public void handleException(Throwable throwable) { 
      throwable.printStackTrace(); 
     } 
    }); 

    setStreamEventDispatcher(streamEventDispatcher); 

    connect(server, port, application, connectCallback); 


} 

private IEventDispatcher streamEventDispatcher = new IEventDispatcher() { 

    @Override 
    public void dispatchEvent(IEvent event) { 
     System.out.println("AudioListenerClientStream.dispachEvent()" + event.toString()); 
    } 
}; 

private IPendingServiceCallback connectCallback = new IPendingServiceCallback() { 
    @Override 
    public void resultReceived(IPendingServiceCall call) { 
     System.out.println("connectCallback"); 
     createStream(createStreamCallback); 
    } 
}; 

private IPendingServiceCallback createStreamCallback = new IPendingServiceCallback() { 
    @Override 
    public void resultReceived(IPendingServiceCall call) { 
     Integer streamIdInteger = (Integer) call.getResult(); 
     play(streamIdInteger.intValue(), filename, 0, -2); 
    } 
}; 

protected void onInvoke(RTMPConnection conn, Channel channel, Header header, Notify notify, RTMP rtmp) { 
    super.onInvoke(conn, channel, header, notify, rtmp); 

    System.out.println("onInvoke, header = " + header.toString()); 
    System.out.println("onInvoke, notify = " + notify.toString()); 
    System.out.println("onInvoke, rtmp = " + rtmp.toString()); 

    /* 
    ObjectMap<String, String> map = (ObjectMap) notify.getCall().getArguments()[0]; 
    String code = map.get("code"); 
    if (StatusCodes.NS_PLAY_STOP.equals(code)) { 

     synchronized(SSCCE_RTMPPlayer.class) { 
      finished = true; 
      SSCCE_RTMPPlayer.class.notifyAll(); 
     } 

     disconnect(); 
     System.out.println("Disconnected"); 
    } 
    */ 
}; 

} 

UPDATE 2

Я обнаружил, что пакеты начинают падать после того, как происходит зависание. Метод падение RTMPProtocolEncoder#dropMessage()

UPDATE 3

Я вижу, что «tardiness` растет со скоростью в режиме реального времени. Когда оно превышает значение 8000, начинается сброс.

ОБНОВЛЕНИЕ 4

Более точно, на стороне сервера, процесс начинает отбрасывать пакеты, примерно через 8 секунд прошло. Это, вероятно, значение 8000, которое является временем допуска. В тот же момент время метки пакета достигает 15-16 секунд. Клиент играет до этого времени и останавливается только тогда.

Таким образом, изображение того, что сервер опережает клиента 2 раза, и когда он достигает определенного предела, он не ждет, но начинает отбрасывать пакеты.

Похоже, что правильное поведение будет ждать, пока клиент достигнет отметки времени и продолжит ...

UPDATE 5

Возможно класс клиента поток не предназначен для прослушивания потока от сервера и поэтому не содержит соответствующую логику синхронизации?

MAGIC SOLUTION

Наблюдая различия в журнале во время воспроизведения потока с oflaDemo клиента и моего приложения, я обнаружил, что стандартный клиент сообщает размер буфера 5000 мс, а мой клиент не делает. Я не понимаю, как это может играть, но когда я добавил RTMP-пинг в свое приложение, он начинает работать. Волшебная линия следует

conn.ping(new Ping(Ping.CLIENT_BUFFER, streamId, 5000)); 

Поскольку его роль просто переложить опоздание на этом значение, я полагаю, что в целом проблема связана с RED5 ошибкой, что делает его неспособным правильно рассчитать опоздания.

+0

Если у вас или у кого-нибудь есть идеи для улучшения расчетов, я бы хотел их услышать. –

ответ

0

Возникла проблема с потоковой передачей видео с некоторыми файлами, из-за которых воспроизведение остановилось. Но с тех пор я исправил его на сервере; используйте версию 4329 или более позднюю. Вопрос для вашей справки находится здесь: http://code.google.com/p/red5/issues/detail?id=200

 Смежные вопросы

  • Нет связанных вопросов^_^