5. DirectShow-MediaSample的生命周期管理

MediaSample的分配

另一个 COM 对象称为 分配器,负责创建和管理MediaSample。 分配器公开 IMemAllocator 接口。 每当filter需要具有空缓冲区的MediaSample时,它会调用 IMemAllocator::GetBuffer 方法,该方法返回指向MediaSample的指针。 每个pin连接共享一个分配器。 当两个pin连接时,它们决定哪个filter将提供分配器。 pin还会在分配器上设置属性,例如缓冲区数和每个缓冲区的大小。 (有关详细信息,请参阅 filter如何连接 和 协商分配器。)

image.png

分配器创建有限的MediaSample池。 随时可以使用某些MediaSample,而其他MediaSample可用于 GetBuffer 调用。 分配器使用引用计数来跟踪MediaSample。 GetBuffer 方法返回引用计数为 1 的MediaSample。 如果引用计数为零,则MediaSample将返回到分配器的池中,可在下一个 GetBuffer 调用中使用。 只要引用计数保持在零以上, GetBuffer 就不能使用MediaSample。 如果属于分配器的每个MediaSample都在使用中, 则 GetBuffer 方法会阻塞,直到MediaSample可用。

例如,假设输入pin接收MediaSample。 如果它在 Receive 方法内同步处理MediaSample,则不会递增引用计数。 Receive 返回后,输出pin释放MediaSample,引用计数为零,MediaSample返回到分配器的池。 另一方面,如果输入pin在工作线程上处理MediaSample,它会在离开 Receive 方法之前递增引用计数。 引用计数现在为 2。 当输出pin释放MediaSample时,计数为 1。MediaSample尚未返回到池。 工作线程完成MediaSample后,它将调用 Release 以释放MediaSample。 现在,MediaSample返回到池。

pin收到MediaSample时,它可以将数据复制到另一个MediaSample,也可以修改原始MediaSample,并将该MediaSample传递到下一个filterMediaSample可能会遍历图形的整个长度,每个filter依次调用 AddRef 和 Release 。 因此,输出pin在调用 Receive 后不得重复使用MediaSample,因为下游filter可能正在使用该MediaSample。 输出pin必须始终调用 GetBuffer 以获取新MediaSample

此机制可减少内存分配量,因为filter会重复使用相同的缓冲区。 它还可防止filter意外写入尚未处理的数据,因为分配器维护可用MediaSample的列表。

filter可以将单独的分配器用于输入和输出。 如果它将输入数据 (展开,则可能会执行此操作,例如,将其解压缩) 。 如果输出不大于输入,filter可能会就地处理数据,而无需将其复制到新MediaSample。 在这种情况下,两个或多个pin连接可以共享一个分配器。

filter首次创建分配器时,分配器未保留任何内存缓冲区。 此时,对 GetBuffer 方法的任何调用都将失败。 当流式处理启动时,输出pin调用 IMemAllocator::Commit,这将提交分配器,使其分配内存。 pin现在可以调用 GetBuffer。

当流式处理停止时,pin调用 IMemAllocator::Decommit,这会取消分配器的提交。 对 GetBuffer 的所有后续调用都失败,直到再次提交分配器。 此外,如果当前阻塞对 GetBuffer 的任何 调用等待MediaSample,它们将立即返回失败代码。 Decommit 方法可能释放内存,也可能不释放内存,具体取决于实现。 例如, CMemAllocator 类将等待其析构函数方法释放内存。

MediaSample的流动过程

filter有三种可能的状态:已停止、暂停和正在运行。 暂停状态的目的是在filter Graph中提示数据,以便运行命令立即响应。 filter关系图管理器控制所有状态转换。 当应用程序调用 IMediaControl::Run、 IMediaControl::P ause 或 IMediaControl::Stop 时,Filter Graph 管理器对所有filter调用相应的 IMediaFilter 方法。 停止和运行之间的转换始终会经历暂停状态,因此,如果应用程序在已停止的图形上调用 “运行 ”,filter图形管理器会在运行图形之前暂停图形。

对于大多数filter,正在运行和暂停状态是相同的。 请考虑以下filter图:
源 > 转换 > 呈现器

现在假设源filter不是实时捕获源。 当源filter暂停时,它会创建一个线程来生成新数据,并尽快将其写入MediaSample。 线程通过在转换filter的输入pin上调用 IMemInputPin::Receive 将MediaSample“推送”到下游。 转换filter接收源filter线程上的MediaSample。 它可以使用工作线程将MediaSample传送到呈现器,但通常在同一线程上传递MediaSample。 呈现器暂停时,它会等待接收MediaSample。 收到一个MediaSample后,它会无限期阻塞并保留该MediaSample。 如果是视频呈现器,则会将MediaSample显示为海报图像,并根据需要重新绘制图像。

此时,流已完全提示并准备好呈现。 如果图形保持暂停状态,MediaSample将“堆积”在第一个MediaSample后面的图形中,直到 Receive 或 IMemAllocator::GetBuffer 中阻塞每个filter。 不过,不会丢失任何数据。 取消阻塞源线程后,它只会从阻塞的点恢复。

filter和转换filter忽略从暂停到正在运行的转换,它们只是继续尽可能快地处理数据。 但是,当呈现器运行时,它将开始呈现MediaSample。 首先,它呈现暂停时保存的MediaSample。 然后,每次收到新MediaSample时,它都会计算MediaSample的呈现时间。 (有关详细信息,请参阅 DirectShow 中的时间和时钟。) 呈现器将保留每个MediaSample,直到呈现时间,此时呈现MediaSample。 在等待演示时间时,它会在 Receive 方法中阻塞,或者接收具有队列的工作线程上的新MediaSample。 来自呈现器上游的filter不涉及计划。

实时源(如捕获设备)是此常规体系结构的例外。 使用实时源时,不宜提前提示任何数据。 应用程序可能会暂停图形,然后等待很长时间后再运行它。 图形不应呈现“过时”MediaSample。 因此,实时源在暂停时不生成任何MediaSample,仅在运行时生成。 为了向filter关系图管理器发出这一事实信号,源filter的 IMediaFilter::GetState 方法返回VFW_S_CANT_CUE。 此返回代码指示filter已切换到暂停状态,即使呈现器未收到任何数据。

filter停止时,它会拒绝传递给它的任何更多MediaSample。 源filter关闭其流式处理线程,其他filter关闭它们可能已创建的任何工作线程。 pin取消提交其分配器。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 230,527评论 6 544
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,687评论 3 429
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 178,640评论 0 383
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,957评论 1 318
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,682评论 6 413
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 56,011评论 1 329
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 44,009评论 3 449
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 43,183评论 0 290
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,714评论 1 336
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,435评论 3 359
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,665评论 1 374
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 39,148评论 5 365
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,838评论 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 35,251评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,588评论 1 295
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 52,379评论 3 400
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,627评论 2 380

推荐阅读更多精彩内容