Как одновременно читать и записывать в поток для воспроизведения мультимедийного файла в Silverlight 4 MediaStreamSource? - PullRequest
2 голосов
/ 07 марта 2011

ФОН

У меня есть мультимедийный файл, который я постепенно загружаю в свое приложение Silverlight 4, используя WebClient.OpenReadAsync / OpenReadCompleted и Stream.BeginRead / AsyncCallback. Цель состоит в том, чтобы воспроизвести файл в MediaElement, вызвав метод SetSource, передав экземпляр нашего пользовательского MediaStreamSource, чтобы файл мог начать воспроизведение до того, как будет загружено все содержимое файла. Медиа-файл использует пользовательскую кодировку / декодирование, поэтому мы используем пользовательский MediaStreamSource. Наш MediaStreamSource создан для приема потока и начала анализа информации о треках и воспроизведения в MediaElement. Я подтвердил, что постепенно загружаю содержимое файла. Вот краткое изложение кода загрузки:

public void SetSource(string sourceUrl)
{
    var uriBuilder = new UriBuilder(sourceUrl);
    WebClient webClient = new WebClient();

    // AllowReadStreamBuffering = false allows us to get the stream
    // before it's finished writing to it.
    webClient.AllowReadStreamBuffering = false;
    webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted);
    webClient.OpenReadAsync(uriBuilder.Uri);
}

void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
    _inboundVideoStream = e.Result;
    BeginReadingFromStream();
}

private void BeginReadingFromStream()
{
    if (_inboundVideoStream.CanRead)
    {
        _chunk = new byte[_chunkSize];
        _inboundVideoStream.BeginRead(_chunk, 0, _chunk.Length, new AsyncCallback(BeginReadCallback), _inboundVideoStream);
    }
}

private void BeginReadCallback(IAsyncResult asyncResult)
{
    Stream stream = asyncResult.AsyncState as Stream;
    int bytesRead = stream.EndRead(asyncResult);
    _totalBytesRead += bytesRead;

    if (_playableStream == null)
        _playableStream = new MemoryStream();

    _playableStream.Write(_chunk, 0, _chunk.Length);

    if (!_initializedMediaStream && _playableStream.Length >= _minimumToStartPlayback)
    {
        _initializedMediaStream = true;

        // Problem: we can't hand the stream source a stream that's still being written to
        // It's Position is at the end.  Can I read and write from the same stream or is there another way
        MP4MediaStreamSource streamSource = new MP4MediaStreamSource(_playableStream);

        this.Dispatcher.BeginInvoke(() =>
        {
            mediaElement1.SetSource(streamSource);
        });
    }

    if (_totalBytesRead < _fileSize)
    {
        ReadFromDownloadStream();
    }
    else
    {
        // Finished downloading
    }
}

Я пытался одновременно записывать / читать в MemoryStream, как указано выше, а также записывать в IsolatedStorageFile и читать из этого файла, когда я пишу в него. Пока я не могу найти способ заставить любой подход работать.

ВОПРОС:

Есть ли способ чтения и записи в один и тот же поток? Или есть стандартный способ реализовать это с помощью потока и MediaStreamSource?

Спасибо

1 Ответ

1 голос
/ 22 декабря 2011

Способ, которым я сделал это в моей реализации MediaStreamSource, состоит в том, чтобы в нем было 2 потока: один для чтения и один для записи.

Я располагаю и воссоздаю поток чтения, используя буфер потока записи каждый раз, когда вызывается GetSampleAsync ().Другой способ сделать это, я думаю, это использовать отрицательное смещение при создании MediaStreamSample для передачи в ReportGetSampleCompleted (), поскольку позиция потока всегда будет в конце, но в противном случае вы должны убедиться, что позиция в концеэто не будет работать, для простоты я просто использовал 2 потока

...