Site feedback

nthamy-1095 avatar image
1 Vote"
nthamy-1095 suggested nthamy-1095 edited

Error writing file with Media Foundation while file is being opened

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;
 }

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

  2. 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());
  }
 }

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

  2. 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-api-graphics-media
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

No Solutions

Your Opinion Counts

Share your feedback, or help out by voting for other people's feedback.