Error writing file with Media Foundation while file is being opened

nthamy 6 Reputation points
2021-09-24T02:10:35.163+00:00

I use Media Foundation to write files. The program is as follows:

#include <windows.h>
 #include <windowsx.h>
 #include <comdef.h>
 #include <stdio.h>
 #include <mfapi.h>
 #include <mfidl.h>
 #include <mfreadwrite.h>
 #include <Mferror.h>
 #include <mfplay.h>
 #include <codecapi.h>
 #include <atlcomcli.h>
 #pragma comment(lib, "ole32")
 #pragma comment(lib, "mfplat")
 #pragma comment(lib, "mfreadwrite")
 #pragma comment(lib, "mfuuid")

 int main()
 {
  HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  hr = MFStartup(MF_VERSION);

  IMFMediaType *pMediaType;
  IMFMediaType *pMediaTypeOut;
  IMFSourceReader *pSourceReader;
  IMFAttributes *pAttributes;
  IMFSinkWriter *pSinkWriter;
  IMFMediaType *pCurrentMediaType;
  LONGLONG nDruration = 300000000;

  hr = MFCreateSourceReaderFromURL(L"./in.mp4", NULL, &pSourceReader);
  pSourceReader->SetStreamSelection(MF_SOURCE_READER_FIRST_VIDEO_STREAM, TRUE);

  IMFMediaType *pPartialType;
  MFCreateMediaType(&pPartialType);
  hr = pPartialType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
  hr = pPartialType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_NV12);
  hr = pSourceReader->SetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, nullptr, pPartialType);
  hr = pSourceReader->GetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, &pPartialType);
  hr = pSourceReader->SetStreamSelection(MF_SOURCE_READER_FIRST_VIDEO_STREAM, TRUE);

  hr = MFCreateMediaType(&pMediaTypeOut);
  hr = pMediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
  hr = pMediaTypeOut->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_HEVC);
  hr = pMediaTypeOut->SetUINT32(MF_MT_AVG_BITRATE, 512000);
  hr = pMediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
  hr = MFSetAttributeRatio(pMediaTypeOut, MF_MT_FRAME_RATE, 30, 1);
  hr = MFSetAttributeSize(pMediaTypeOut, MF_MT_FRAME_SIZE, 720, 480);
  hr = MFSetAttributeRatio(pMediaTypeOut, MF_MT_PIXEL_ASPECT_RATIO, 16, 9);

  DWORD nWriterStreamIndex = -1;
  hr = MFCreateSinkWriterFromURL(L"./out.mp4", NULL, NULL, &pSinkWriter);
  hr = pSinkWriter->AddStream(pMediaTypeOut, &nWriterStreamIndex);
  hr = pSinkWriter->SetInputMediaType(nWriterStreamIndex, pPartialType, NULL);

  LONGLONG SampleDuration = 0L;
  hr = pSinkWriter->BeginWriting();

  for (;;)
  {
  DWORD nStreamIndex, nStreamFlags;
  LONGLONG nTime;
  IMFSample *pSample;

  hr = pSourceReader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM,
  0,
  &nStreamIndex,
  &nStreamFlags,
  &nTime,
  &pSample);
  printf("FLAGS %d\n", nStreamFlags);
  printf("TIME %lld\n", nTime);

  if (nStreamFlags & MF_SOURCE_READERF_ENDOFSTREAM)
  {
  break;
  }

  //Update media type, when current media tye changed.
  if (nStreamFlags & MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED) {
  pSourceReader->GetNativeMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, MF_SOURCE_READER_CURRENT_TYPE_INDEX, &pCurrentMediaType);
  printf("MediaType changed\n");
  pSourceReader->SetStreamSelection(MF_SOURCE_READER_FIRST_VIDEO_STREAM, TRUE);
  hr = pSinkWriter->SetInputMediaType(nWriterStreamIndex, pCurrentMediaType, NULL);
  continue;
  }
  pSample->GetSampleDuration(&SampleDuration);

  if (nTime >= nDruration)
  {
  break;
  }
  // Calculate new timestamp of sample when this sample is written on output file
  if (nTime + SampleDuration >= nDruration)
  {
  SampleDuration = nDruration - nTime;
  pSample->SetSampleDuration(SampleDuration);
  }
  pSample->SetSampleTime(nTime);

  if (FAILED(hr)) {
  printf("ReadSample Error...\n");
  return hr;
  }

  //write sample
  if (pSample)
  {
  OutputDebugString(L"Write sample...\n");
  hr = pSinkWriter->WriteSample(
  nWriterStreamIndex,
  pSample
  );
  if (FAILED(hr)) {
  pSample->Release();
  printf("WriteSample Error...\n");
  return hr;
  }
  pSample->Release();
  pSample = NULL;
  }
  }
  hr = pSinkWriter->Finalize();
  return 0;
 }

After running the program, I get the file "out.mp4". I play it with WMP (Window Media Player) and don't close it.

Then I run the program again, it crashes when calling MFCreateSinkWriterFromURL.

hr = HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION): The process cannot access the file because it is being used by another process.

I think the cause is out.mp4 being locked by WMP.
3. However, if I add a code to delete the out.mp4 file before calling MFCreateSinkWriterFromURL, the program will always run successfully. At this point, WMP will sometimes report an error.

 if (PathFileExistsW("./out.mp4")) {
  if (!DeleteFileW("./out.mp4")) {
  LERROR("msg", "delete output file failed", "error", GetLastError());
  }
 }

I try to delete a video file using File Explorer while the same file is still played by WMP. Results similar to step 3.

I did all the above steps again and replaced WMP with Movie&TV (on Win10), the results were slightly different.

In step 2, the program does not give error while the file is still playing on Movie&TV

In step 3 and step 4, we can always delete the file and Movie&TV gives error

0x8007002 - The item is missing or we can't get to it

So I have questions here:

  • With WMP, why can't we overwrite files (using Media Foundation) but we can delete files?
  • With Movie&TV, why can't the program detect the file being played by Movie&TV? Also like WMP, why can't the file be deleted while it's being played with Movie&TV ?
Windows development | Windows API - Win32
{count} votes

1 answer

Sort by: Most helpful
  1. nthamy 6 Reputation points
    2021-10-12T10:09:59.133+00:00

    Hi @Xiaopo Yang - MSFT
    Thanks you for your support and sorry for the late response.

    I have tried running the MFCaptureToFile sample, however it doesn't solve the problem I have.
    Please notice my steps below:

    • Step 1: Run the program MFCaptureToFile.
    • Step 2: Start Capture.
    • Step 3: Open the output video file with WMP and let it opened when completed playing.
    • Step 4: Start Capture again to override the output file.
      => I get 0x80070020 error
    • Step 5: Close WMP window and override the file, I don't get the error.

    These phenomena are identical to the samle code I gave.
    I think the output file is locked by WMP so it won't be possible to overwrite the file without closing WMP or switching to another file.
    However I can delete the file even when WMP is playing the file. This is what I am most confused about. Please explain this problem.

    Also, if I use Movie&TV, I can not only delete the file, but also overwrite the date file while Movie&TV is playing the file.

    This is clearly the behavior of Window. Hopefully Microsoft has an update to fix this.


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.