windows media format sdk中使用precompressed stream的问题,高手请进

captainwh 2003-11-04 11:24:39
我要在windows media format sdk中使用一个自己开发的video for windows codec作编码,文档中称这种使用第三方codec为precompressed stream, 应用开发者必须自己完成数据的压缩,并将压缩后的数据传递给writer object。

writer object必须使用一个自定义的profile来说明这个precompressed stream, 下面是我按照文档中的说法完成的代码:

// 媒体类型的GUID
// {31444956-EB3F-4D0D-90FA-E807FCBAA116}
DEFINE_GUID(TTLH264_Video,
0x31444956, 0xeb3f, 0x4d0d, 0x90, 0xfa, 0xe8, 0x7, 0xfc, 0xba, 0xa1, 0x16);

// 媒体类型的压缩类型
const DWORD FOURCC_VID1 = MAKEFOURCC('V','I','D','1');
// 826558806 // 0x31444956

// 文档中讲媒体类型的GUID必须和压缩类型匹配, 象这样
// DWORD FOURCC_VID1 = MAKEFOURCC('V','I','D','1') = 0x31444956
// 则GUID必须以0x31444956, 开头
// 问题是我们怎么去控制GUID的生成值呢,目前我是生成后直接将其修改成符合标
// 准的形式,不知可不可以

const WORD VIDEO_STREAM_NUMBER = 1;
WCHAR *VIDEO_STREAM_NAME = L"TTL H.264 Video Stream";
WCHAR *VIDEO_STREAM_CONNECTION_NAME = L"TTL Video Connection";

// 初始化代码
// Image Info (Vid1 format)
ZeroMemory(&m_bmpInfoHdr, sizeof(BITMAPINFOHEADER));
m_bmpInfoHdr.biSize = sizeof(BITMAPINFOHEADER);
m_bmpInfoHdr.biWidth = m_nWidth;
m_bmpInfoHdr.biHeight = m_nHeight;
m_bmpInfoHdr.biPlanes = 1;
m_bmpInfoHdr.biBitCount = 24;
m_bmpInfoHdr.biCompression = FOURCC_VID1; // 自定义的
// Compression type

// Video Format Struct
RECT rect;
SetRect(&rect, 0, 0, m_nWidth, m_nHeight);
ZeroMemory(&m_VideoInfoHdr, sizeof(WMVIDEOINFOHEADER));
m_VideoInfoHdr.rcSource = rect;
m_VideoInfoHdr.rcTarget = rect;
m_VideoInfoHdr.dwBitRate = 190773; // 码率
m_VideoInfoHdr.dwBitErrorRate = 0; // 这个好像是错
// 误的码
// 率,不止怎么填
m_VideoInfoHdr.AvgTimePerFrame = 40 * 10000; // 每祯图象显示时
// 间
// (100ns 为单位)
m_VideoInfoHdr.bmiHeader = m_bmpInfoHdr;

// Video Media Type
ZeroMemory(&m_MediaSubType, sizeof(WM_MEDIA_TYPE));
m_MediaSubType.majortype = WMMEDIATYPE_Video;
m_MediaSubType.subtype = TTLH264_Video; // 自定义
// Compress type
// 的GUID
m_MediaSubType.bFixedSizeSamples = FALSE; // 每祯图象是否大
// 小相同
m_MediaSubType.bTemporalCompression = TRUE; // 图象是否已经
// 压缩过
m_MediaSubType.lSampleSize = 0;
m_MediaSubType.formattype = WMFORMAT_VideoInfo;
m_MediaSubType.pUnk = NULL;
m_MediaSubType.cbFormat = sizeof(WMVIDEOINFOHEADER);
m_MediaSubType.pbFormat = (BYTE*)&m_VideoInfoHdr;

// Init Com Library
CoInitialize(NULL);

// Create an Empty Profile
HRESULT hr = WMCreateProfileManager(&m_pProfileMgr);
hr = m_pProfileMgr->CreateEmptyProfile(WMT_VER_9_0,
&m_pProfile);

// create a new stream, config the stream
hr = m_pProfile->CreateNewStream(WMMEDIATYPE_Video,
&m_pStreamCfg);
hr = m_pStreamCfg->SetStreamNumber(1);
hr = m_pStreamCfg->SetStreamName(L"TTL Video Stream");
hr = m_pStreamCfg->SetConnectionName(L"Video");
hr = m_pStreamCfg->SetBufferWindow(3000); // 缓冲时间
hr = m_pStreamCfg->SetBitrate(190773); // 码率
hr = m_pStreamCfg->QueryInterface(IID_IWMMediaProps, (void**)
&m_pMediaProp);
hr = m_pMediaProp->SetMediaType(&m_MediaSubType); // 设置sub
// type
if (FAILED(hr))
{
// 在这里失败, 返回值表示m_MediaSubType的设置不正确
if (hr == NS_E_INVALID_STREAM)
int y = 100;
}

// add the stream to the profile
hr = m_pProfile->AddStream(m_pStreamCfg);
if (FAILED(hr))
{
if (hr == NS_E_INVALID_STREAM)
int x = 100;
}

// Create WM Writer Object, Set the Profile
hr = WMCreateWriter(NULL, &m_pWriter);
hr = m_pWriter->SetProfile(m_pProfile);

// Config all Input
DWORD dwInputCount = 0;
hr = m_pWriter->GetInputCount(&dwInputCount);
for (int i = 0; i < dwInputCount; i++)
hr = m_pWriter->SetInputProps(i, NULL);

// Init Writer
hr = WMCreateWriterFileSink(&m_pFileSink);
hr = m_pFileSink->QueryInterface(IID_IWMWriterFileSink3,
(void**)&m_pFileSink3);
hr = m_pWriter->QueryInterface(IID_IWMWriterAdvanced, (void**)
m_pWriterAdvanced);
hr = m_pWriterAdvanced->AddSink(m_pFileSink3);

// 启动写入线程
unsigned ThreadID;
m_hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, this,
0, &ThreadID);
// 初始化结束


// 这里是写入数据的线程代码
int CTTLASFWriter::Run()
{
m_bRunning = true;

// 打开输出文件, 开始写入
HRESULT hr = m_pFileSink3->Open(L"d:\\test.asf");
hr = m_pWriter->BeginWriting();

QWORD qwSampleTime = 0; // sample time
while (true)
{
if (m_bExit)
break;

// 获取数据
int res = m_pSource->ReadVideo(&m_pInBuffer,
&m_InSize);
if (m_InSize <= 0 || res == -1)
break;

INSSBuffer *pNSSBuffer;
hr = m_pWriter->AllocateSample(m_InSize, &pNSSBuffer);
BYTE *pOutBuf = NULL;
hr = pNSSBuffer->GetBuffer(&pOutBuf);
memcpy(pOutBuf, m_pInBuffer, m_InSize);
hr = pNSSBuffer->SetLength(m_InSize);
qwSampleTime = timeGetTime() * 10000; // 单位100ns
m_pWriterAdvanced->WriteStreamSample
(VIDEO_STREAM_NUMBER, qwSampleTime, 0, 0, 0,
pNSSBuffer);
pNSSBuffer->Release();

m_pInBuffer = NULL;
m_InSize = 0;
}

hr = m_pFileSink3->Close();
hr = m_pWriter->EndWriting();

m_bRunning = false;
return 0;
}

请教为什么我设置sub media type会失败, 另外在写入sample时,每个sample都需要有一个sample time, 文档中也没有介绍这个冬冬怎么写, 它是相对第一祯的时间还是绝对的时间值呢? 请高手帮忙。
...全文
179 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
captainwh 2003-11-10
  • 打赏
  • 举报
回复
我试过去掉写sample的代码,象下面这样:
HRESULT hr = m_pFileSink3->Open(L"d:\\test1.asf");
hr = m_pWriter->BeginWriting();
hr = m_pFileSink3->Close();
hr = m_pWriter->EndWriting();

和有写sample的情况,象下面这样:

QWORD qwSampleTime = 0;
while (true)
{
if (m_bExit)
break;

int res = m_pSource->ReadVideo(&m_pInBuffer, &m_InSize);
if (m_InSize <= 0 || res == -1)
break;

INSSBuffer *pNSSBuffer;
hr = m_pWriter->AllocateSample(m_InSize, &pNSSBuffer);
BYTE *pOutBuf = NULL;
hr = pNSSBuffer->GetBuffer(&pOutBuf);
memcpy(pOutBuf, m_pInBuffer, m_InSize);
hr = pNSSBuffer->SetLength(m_InSize);

if (m_ImageCount == 0)
{
m_StartTime = timeGetTime();
qwSampleTime = m_StartTime * 10000;
}
else
{
qwSampleTime = (timeGetTime() - m_StartTime) * 10000;
}

DWORD dwFlags;
if (m_InSize > 10 * 1024)
dwFlags = WM_SF_CLEANPOINT;
else
dwFlags = 0;

hr = m_pWriterAdvanced->WriteStreamSample(VIDEO_STREAM_NUMBER,
qwSampleTime, 0, 0, dwFlags, pNSSBuffer);
//hr = m_pWriter->WriteSample(0, qwSampleTime, 0, pNSSBuffer);
if (hr != S_OK)
{
break;
}
pNSSBuffer->Release();

m_ImageCount++;
printf("%d %d\n", m_ImageCount, m_InSize);

m_pInBuffer = NULL;
m_InSize = 0;
}

hr = m_pFileSink3->Close();
hr = m_pWriter->EndWriting();

程序运行结束后文件都是2.28k, 也就是说数据根本没有写入文件,请问这又是怎么回事呢
captainwh 2003-11-10
  • 打赏
  • 举报
回复
我每一祯图象数据都用WriteStreamSample写入成功了,为什么最后得到的asf文件只有2.5k呢?我写入的数据总量大概在2.5m左右。
captainwh 2003-11-10
  • 打赏
  • 举报
回复
太感谢了,问题解决了
蒋晟 2003-11-10
  • 打赏
  • 举报
回复
当不是实时录制的时候,sample time就是播放时的媒体时间
蒋晟 2003-11-09
  • 打赏
  • 举报
回复
Converting FOURCC Codes to Subtype GUIDs

A range of 2*32 GUIDs is reserved for representing FOURCCs. These GUIDs are all of the form XXXXXXXX-0000-0010-8000-00AA00389B71 where XXXXXXXX is the FOURCC code. Thus, the subtype GUID for YUY2 is 32595559-0000-0010-8000-00AA00389B71.

Many of these GUIDs are defined already in the header file Uuids.h. For example, the YUY2 subtype is defined as MEDIASUBTYPE_YUY2. The DirectShow base class library also provides a helper class, FOURCCMap, which can be used to convert FOURCC codes into GUID values. The FOURCCMap constructor takes a FOURCC code as an input parameter. You can then cast the FOURCCMap object to the corresponding GUID:

FOURCCMap fccMap(FCC('YUY2'));
GUID g1 = (GUID)fccMap;

// Equivalent:
GUID g2 = (GUID)FOURCCMap(FCC('YUY2'));



FOURCC Registration Page
FOURCC Registration. To register a new FOURCC, complete the attached document and mail it to Microsoft at mmreg@microsoft.com. This system is fine in principle but there is currently no way of getting that information back out of the folks at Microsoft once the format is registered. ...

http://www.microsoft.com/whdc/hwdev/archive/devdes/fourcc.mspx
蒋晟 2003-11-06
  • 打赏
  • 举报
回复
对了,你知道为什么用Windows Media Audio 9压缩声音会变调么?不压缩没有问题
蒋晟 2003-11-06
  • 打赏
  • 举报
回复
声音变得很低
似乎是CPU过忙,采样不足造成的
captainwh 2003-11-06
  • 打赏
  • 举报
回复
不知啊,变成什么了
captainwh 2003-11-05
  • 打赏
  • 举报
回复
由于是压缩数据,biSizeImage大小不是固定的,我试了给它一个最大值,没有效果
captainwh 2003-11-05
  • 打赏
  • 举报
回复
谢谢各位支持,大家再帮我顶啊
蒋晟 2003-11-05
  • 打赏
  • 举报
回复
Sample time还是有问题,应该减去开始的时间m_tStart=timeGetTime();

m_tCur =timeGetTime()-m_tStart;
QWORD cnsSampleTime=(QWORD)(m_tCur)*10000;
不推荐用时间戳,因为会增加带宽。如果确实要加,可以参考UncompAVIToWMV示例中的函数
HRESULT CUncompAVIToWMV::AddSMPTETimeCode( INSSBuffer * pSample,
QWORD qwPresTime )

hahu 2003-11-05
  • 打赏
  • 举报
回复
biCompression =BI_RGB
的时候可以不用biSizeImage
其他情况可以不写吗?

也没有看过biCompression 不用sdk提供的值
captainwh 2003-11-05
  • 打赏
  • 举报
回复
media sub type是支持的,做法应该就是这样,但我的参数哪里错误了呢,请有经验的帮我看看我设置的BITMAPINFOHEADER, WMVIDEOINFOHEADER, WM_MEDIA_TYPE这三个结构体中哪里数据是非法的呢?
蒋晟 2003-11-04
  • 打赏
  • 举报
回复
Sample Time是从写入开始计算的采样的绝对时间,单位是100纳秒(1/10000毫秒)
我是用timeGetTime然后乘10000的
某些类型的流的Sample Time不能是0,例如script流
自定义的子类型没用过,可能不被支持吧
captainwh 2003-11-04
  • 打赏
  • 举报
回复
:( ,哪位知道啊
dzqsuper 2003-11-04
  • 打赏
  • 举报
回复
这么高的高手
你应该当版主来
Ah 2003-11-04
  • 打赏
  • 举报
回复
关注
VisioForge Video Capture SDK major features include: Preview Video capture to AVI (using audio/video codecs like MJPEG, DivX, XviD, x264) WMV (support of custom WMV profiles. You can configure streams to use variable bit rate encoding (VBR), uncompressed audio or video stream, video size, buffer size, frame rate, etc.) DV and MPEG from DV/HDV Camcorders and TV Tuners with internal MPEG Encoder (DirectCapture technology) DV (from any video capture device) MPEG-1/2/4 (including VCD/SVCD/DVD profiles) and FLV using FFMPEG wrapper WebM MP4 H264 / AAC custom output formats (using 3rd-party DirectShow filters) Audio capture to WAV (compressed or not) MP3 (using LAME) Frame capture to Bitmap class, BMP, JPEG and PNG files Video processing and effects graphic overlay text overlay video transparency brightness, contrast, saturation, hue, etc. deinterlace denoise pan / zoom resize to any resolution chroma-key 3-rd party DirectShow filters support Audio processing and effects volume booster equalizer 3D-bass system TV Tuning TV channels selecting video formats selecting input selection (TV-Tuner, FM-Tuner, S-Video, etc.) TV frequency overrides auto-tuning Video capture device control video input (crossbar interface) video format frame rate supports video cards with several inputs camera control (brightness, saturation, etc.) Network streaming in WMV format to other media servers and devices using virtual camera/audio source Motion detection Closed captions support Custom interfaces support OSD (On-Screen Display) PIP (Picture-In-Picture) Video encryption Screen capture Virtual Camera output Multiply output screens support Supported input devices: DV and HDV MPEG-2 camcorders USB web-cameras and other capture devices PCI capture cards TV Tuners (with and without internal MPEG Encoder) JPEG/MJPEG, MPEG-4 and H.264 HTTP / RTSP / RTMP IP cameras / servers, HD format supported Audio capture devices and sound cards Development platforms: Visual Studio 2005 and later: Visual C#, Visu
r40_tinav2.1_最终验证通过_使用CB-S来验证OV5640有横条纹fpscamera+SPI2.0成功_20171114_1443没有外层目录.7z 开发板:CB-S 1、(可选修改/调试技巧:) 除了ov5640.c之外,其它的驱动都不编译,节省编译时间! W:\ov5640_spi20_r40t\lichee\linux-3.10\drivers\media\platform\sunxi-vfe\device\Makefile obj-m += ov5640.o #obj-m += ov2640.o #obj-m += ov7736.o #obj-m += s5k4ec.o #obj-m += s5k4ec_mipi.o #obj-m += gc2035.o #obj-m += gt2005.o #obj-m += gc0307.o #obj-m += gc0308.o #obj-m += gc0328.o #obj-m += gc0328c.o #obj-m += gc2145.o #obj-m += gc0329.o #obj-m += gc0311.o #obj-m += hi253.o #obj-m += sp2518.o #obj-m += sp2519.o #obj-m += sp0718.o #obj-m += sp0838.o #obj-m += ov16825.o #obj-m += ov5650.o #obj-m += ov5647.o #obj-m += ov5647_mipi.o #obj-m += t8et5.o #obj-m += s5k4e1.o #obj-m += s5k4e1_mipi.o #obj-m += sp2518.o #obj-m += sp0718.o #obj-m += gc5004.o #obj-m += gc5004_mipi.o #obj-m += ov5648.o #obj-m += ar0330.o #obj-m += ov5648.o #obj-m += sp5408.o #obj-m += ov12830.o #obj-m += ov8825.o #obj-m += ov8850.o #obj-m += gc2155.o #obj-m += ov8858.o #obj-m += ov13850.o #obj-m += imx214.o #obj-m += ov8858_4lane.o #obj-m += sp5409.o #obj-m += s5k5e2yx.o #obj-m += ov2710_mipi.o #obj-m += ov2686.o (这里是看ov5640的驱动的probe执行是否正确?设备ID是否读取成功!) W:\ov5640_spi20_r40t\lichee\linux-3.10\drivers\media\platform\sunxi-vfe\device\ov5640.c static int sensor_detect(struct v4l2_subdev *sd) { data_type rdval; printk("****wyb %s:%d/%s()! \n", __FILE__, __LINE__, __func__); LOG_ERR_RET(sensor_read(sd, 0x300a, &rdval;)) printk("****wyb %s:%d/%s()! 0x300a rdval=0xx\n", __FILE__, __LINE__, __func__, rdval); if(rdval != 0x56) return -ENODEV; LOG_ERR_RET(sensor_read(sd, 0x300b, &rdval;)) printk("****wyb %s:%d/%s()! 0x300b rdval=0xx\n", __FILE__, __LINE__, __func__, rdval); if(rdval != 0x40) return -ENODEV; return 0; } (在全志R16平台改过这个文件,让摄像头不要休眠,但是全志R40平台的tina v2.1系统下不需要修改!) W:\ov5640_spi20_r40t\lichee\linux-3.10\drivers\media\platform\sunxi-vfe\vfe.c 2、(可

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧