Avi file not played correctly by Windows Media Player on Windows 8.1

Jun 10, 2015 at 4:35 PM
Hi,
first of all thanks for your great work on this lib.
I tried to use your sample application to generate an avi file with MJPEG video and uncompressed (or even mp3) audio and I found that I cannot seek (set a position on the position bar) with windows media player or with software developed using Windows Media Foundation.
Do you know if it is possible to work around this issue?
Thanks in advance.
Stefano
Coordinator
Jun 15, 2015 at 2:37 PM
Hi,
Sorry for a late response. I was not able to answer at that moment.

Had never noticed that before. I use Media Player Classic, which does not have such issues.

After digging into the issue in more detail I see that looks like WMP does seek, but does not update the picture. If you seek while playing, or resume after seeking - all goes as expected, it plays from the position you've set on the bar.
I've checked several AVI files on my PC that were not produced with SharpAVI and WMP behave exactly the same with them. So it does not appear to be a problem specific to SharpAVI.

I cannot suggest you any workaround besides using other software for playing AVI files.
Jun 16, 2015 at 3:31 PM
Hi,
I checked and I found a couple of problems in the audio list. I fixed them and now it seems to work.

In WriteStreamHeader(AviAudioStream audioStream) I divided the TotalDataSize by the Granularity because, according to the specs, that value should be
normalized on the scale
fileWriter.Write((uint)(streamsInfo[audioStream.Index].TotalDataSize / audioStream.Granularity)); // length

In WriteStreamSuperIndex, just for AviAudioStreams, the duration should be multiplied by the number of samples per chunk
I computed it as (stream.SamplesPerSecond * (entry.ChunkSize/stream.BytesPerSecond)).

Then I removed the MainHeaderFlags.TrustChunkType but I don't know if that affects the result.
Now it works also with WMP and with other player like SMPlayer that were having problems before.

Ciao.
Stefano
Coordinator
Jun 18, 2015 at 7:48 AM
Hi
Thanks for your input. I'll check these modifications.
Coordinator
Jun 25, 2015 at 9:28 PM
Edited Jun 25, 2015 at 9:28 PM
I have tried what you've suggested. However, WMP refused to play a video at all until I have reverted your first modification in WriteStreamHeader. MPC plays nicely regardless of the changes.
Could you make a pull request on GitHub or just attach a patch with your changes? I guess you may have forgotten to mention something or I simply don't get you right.
Jul 14, 2015 at 10:15 AM
Edited Jul 14, 2015 at 10:24 AM
Hi baSSiLL,
sorry for the delay.
Here is the patched code WriteStreamHeader:
    void IAviStreamWriteHandler.WriteStreamHeader(AviAudioStream audioStream)
    {
        // See AVISTREAMHEADER structure
        fileWriter.Write((uint)audioStream.StreamType);
        fileWriter.Write(0U); // no codec
        fileWriter.Write(0U); // StreamHeaderFlags
        fileWriter.Write((ushort)0); // priority
        fileWriter.Write((ushort)0); // language
        fileWriter.Write(0U); // initial frames
        fileWriter.Write((uint)audioStream.Granularity); // scale (sample rate denominator)
        fileWriter.Write((uint)audioStream.BytesPerSecond); // rate (sample rate numerator)
        fileWriter.Write(0U); // start
        fileWriter.Write((uint)(streamsInfo[audioStream.Index].TotalDataSize / audioStream.Granularity)); // length
        fileWriter.Write((uint)(audioStream.BytesPerSecond / 2)); // suggested buffer size (half-second)
        fileWriter.Write(-1); // quality
        fileWriter.Write(audioStream.Granularity); // sample size
        fileWriter.SkipBytes(sizeof(short) * 4);
    }
and here is the WriteSuperIndex:
    private void WriteStreamSuperIndex(IAviStream stream)
    {
        var superIndex = streamsInfo[stream.Index].SuperIndex;
        // See AVISUPERINDEX structure
        var chunk = fileWriter.OpenChunk(KnownFourCCs.Chunks.StreamIndex);
        fileWriter.Write((ushort)4); // DWORDs per entry
        fileWriter.Write((byte)0); // index sub-type
        fileWriter.Write((byte)IndexType.Indexes); // index type
        fileWriter.Write((uint)superIndex.Count); // entries count
        fileWriter.Write((uint)((IAviStreamInternal)stream).ChunkId); // chunk ID of the stream
        fileWriter.SkipBytes(3 * sizeof(uint)); // reserved

        // entries
        foreach (var entry in superIndex)
        {
            fileWriter.Write((ulong)entry.ChunkOffset); // offset of sub-index chunk
            fileWriter.Write((uint)entry.ChunkSize); // size of sub-index chunk
            IAviAudioStream audio_stream = stream as IAviAudioStream ;
            if (audio_stream != null)
            {
                uint duration = (uint)(entry.Duration * audio_stream.SamplesPerSecond * frameRateDenominator / frameRateNumerator);
                fileWriter.Write(duration); // duration of sub-index data (number of frames it refers to)
            }
            else
            {
                fileWriter.Write((uint)entry.Duration); // duration of sub-index data (number of frames it refers to)
            }
        }

        fileWriter.CloseItem(chunk);
    }
This works if the duration of audio blocks is 1/fps because I use the fps to compute the number of samples per block.
Using MJPEG for video and PCM for audio, this works fine at my side.
Hope it helps.
Ciao,
Stefano

p.s.
I have also added two overloads of WriteStreamSuperIndex
    private void WriteStreamSuperIndex(AviVideoStream stream)
and
    private void WriteStreamSuperIndex(AviAudioStream stream)
to separate audio and video but the check (audio_stream != null) in WriteStreamSuperIndex(IAviStream stream) should be enough