iMediAdet :: GetBitmapbits는 Zeroes를 반환합니다 - MKV 비디오 파일에서 검은 색 이미지
-
21-12-2019 - |
문제
외부 lib : "Nofollow"> http://sourceforge.net/projects/directshownet/ AVI, WMV, MP4, FLV, WEBM 파일이 코드는 OK이지만 MKV는 검은 색 이미지 만 반환합니다 (X264 비디오 스트림 및 XVID 비디오 스트림으로 테스트 됨).
그래서 ... 내 질문은 : MKV 파일에서 프레임을 가져 오는 방법에 대한 아이디어가 있습니까?(현재 나는 할리 미디어 스플리터를 사용하고 있음)
public string FileName
{
get
{
return fileName;
}
set
{
mediaDet = null;
fileName = value;
if (File.Exists(fileName))
{
AMMediaType mediaType = null;
try
{
mediaDet = (IMediaDet)new MediaDet();
DsError.ThrowExceptionForHR(mediaDet.put_Filename(fileName));
// find the video stream in the file
int index = 0;
Guid type = Guid.Empty;
while (type != MediaType.Video)
{
mediaDet.put_CurrentStream(index++);
mediaDet.get_StreamType(out type);
}
// retrieve some measurements from the video
mediaDet.get_FrameRate(out frameRate);
mediaType = new AMMediaType();
mediaDet.get_StreamMediaType(mediaType);
videoInfo = (VideoInfoHeader)Marshal.PtrToStructure(mediaType.formatPtr, typeof(VideoInfoHeader));
DsUtils.FreeAMMediaType(mediaType);
mediaType = null;
width = videoInfo.BmiHeader.Width;
height = videoInfo.BmiHeader.Height;
mediaDet.get_StreamLength(out mediaLength);
frameCount = (int)(frameRate * mediaLength);
}
catch (Exception e)
{
if (mediaType != null)
{
DsUtils.FreeAMMediaType(mediaType);
}
fileName = "";
throw new ArgumentException(String.Format("unable to open the file \"{0}\", DirectShow reported the following error: {1}", value, e.Message));
}
}
}
}
public Bitmap GetImageAtTime(double seconds)
{
if (seconds <= mediaLength)
{
if (mediaDet != null)
{
IntPtr bufferPtr = IntPtr.Zero;
Bitmap returnValue = null;
try
{
// create a buffer to hold the image data from the MediaDet
int bufferSize;
mediaDet.GetBitmapBits(seconds, out bufferSize, IntPtr.Zero, width, height);
bufferPtr = Marshal.AllocHGlobal(bufferSize);
mediaDet.GetBitmapBits(seconds, out bufferSize, bufferPtr, width, height);
// compose a bitmap from the data in the managed buffer
unsafe
{
returnValue = new Bitmap(width, height, this.PixelFormat);
BitmapData imageData = returnValue.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, this.PixelFormat);
int* imagePtr = (int*)imageData.Scan0;
int bitmapHeaderSize = Marshal.SizeOf(videoInfo.BmiHeader);
int* sourcePtr = (int*)((byte*)bufferPtr.ToPointer() + bitmapHeaderSize);
for (int i = 0; i < (bufferSize - bitmapHeaderSize) / 4; i++)
{
*imagePtr = *sourcePtr;
imagePtr++;
sourcePtr++;
}
returnValue.UnlockBits(imageData);
returnValue.RotateFlip(RotateFlipType.Rotate180FlipX); // DirectShow stores pixels in a different order than Bitmaps do
}
Marshal.FreeHGlobal(bufferPtr);
return returnValue;
}
catch
{
if (bufferPtr != IntPtr.Zero)
{
Marshal.FreeHGlobal(bufferPtr);
}
if (returnValue != null)
{
returnValue.Dispose();
}
throw;
}
}
else
{
throw new InvalidOperationException("cannot retrieve the frame because the FileName property has not been set yet");
}
}
else
{
throw new ArgumentException(String.Format("seconds must be between 0 and {0} inclusive, value was \"{1}\"", mediaLength, seconds));
}
}
. 해결책
트랜스 닙 플레이스 필터를 기반으로 자신의 샘플 그래버 필터를 사용하는 것이 더 낫습니다.문제 왜 이유 - 표준 샘플 그래버 필터 (iMediAdet에서 사용)가 지원하지 않는 VideoInfoHeader2 사용법.VideoInfoHeader / VideoInfoHeader2 지원으로 자신의 필터를 만들어야합니다.그것은 간단합니다.CEZRGB24 또는 그레이 스케일러 필터를 샘플로 사용하십시오.
제휴하지 않습니다 StackOverflow