h.264并行解码算法3D-Wave实现(基于多核共享内存系统)
3D-Wave算法是2D-Wave的扩展。3D-Wave相对于只在帧内并行的2D-Wave来说,多了帧间并行,不用等待前一帧完成解码后才开始下一帧的解码,而是只要宏块的帧间参考部分以及帧内依赖宏块解码完毕即可开始当前宏块的解码。由于帧间参考所用的运动向量是动态的值,因此称此算法为Dynamic 3D-Wave。
在3D-Wave算法中,宏块的帧间参考部分是指宏块进行运动补偿时需要依赖的相应参考帧的某些宏块,所依赖的这些帧间宏块当中,最右下角的那个宏块会是最晚被解码的,因此我们可以把它当作帧间依赖。另外,如果当前宏块采用的是双向预测,那么它将有两个帧间依赖。

3D-Wave实现
如前文所说,3D-Wave算法中,宏块需要分别等待帧内依赖、帧间依赖解码完成才能开始当前宏块的解码操作。由于这两个依赖的完成时间会有先后之分,因此可能会出现以下两种情况
| 情形 1 | 情形 2 | |
| step 1 | 帧间依赖解码完成 | 帧内依赖解码完成,启动解码 |
| step 2 | 帧内依赖解码完成,启动解码 | 帧间依赖解码完成 |
| step 3 | 解码宏块 | 解码宏块 |
| step 4 | 通知依赖于本宏块的其它宏块 | 通知依赖于本宏块的其它宏块 |
其中解码宏块必须由帧内依赖解码完成后一同启动,因为帧间依赖在解码完成时,并不知道哪个宏块会依赖于它,而帧内依赖由于位置是固定的,因此在帧内依赖解码完成后能直接启动解码,得到mvp(运动向量的预测值)然后求得mv,从而确定当前宏块与帧间依赖的关系,帧间依赖根据这个关系来通知当前宏块:帧间依赖解码已完成。
根据上面的分析,有如下实现方案:
用一个三位数组Ready[f][x][y]来表示某一帧的某一宏块是否解码完成;
用一个三位数组KoL[f][x][y]来表示某一帧的某一宏块的帧间依赖关系,(f,x,y)是当前宏块,KoL[f][x][y]内存放的是帧间依赖于这个宏块的其它宏块,用链表实现;

在帧间依赖先解码完成的情况下,去把Ready数组中该帧间依赖所在的位置的元素置1。待帧内依赖解码完成,当前宏块开始解码时,去查看Ready数组中帧间依赖的元素,会得知该帧间依赖已解码完成。

在帧内依赖先解码完成的情况下,当前宏块开始解码,去查看Ready数组中帧间依赖的元素时,会发现帧间依赖尚未解码完成,因此需要用KoL把当前宏块与帧间依赖关联在一起,然后解码任务会由于帧间依赖没有解码完成而被挂起。待帧间依赖解码完成,去把Ready数组中的相应元素置1,并通过KoL链表数组通知帧间依赖于该宏块的宏块,恢复解码任务。

伪代码如下
void decode_mb(int x, int y, int f, bool mv_pred_done, int RMB_start)
{
/*
*一个宏块由于“挂起”与“恢复”,可能会重复执行decode_mb,
*而求mvp等步骤只需要执行一次
*/
if(!mv_pred_done)
{
/* 求mvp */
Motion_Vector_Prediction(x, y);
/* 通过mvp得到mv,得到帧间依赖,帧间依赖可能不止一个 */
RMB_List = RMB_Calculation(x, y);
} /* 遍历帧间依赖,如果有依赖没解码完成,应该“挂起”,即return */
for(i = RMB_List.start; i<RMB_List.last; i++)
{
(g,u,v) = get_frame_number_and_MB_coord(RMB_List.rmb[i]);
if(!Ready[g][u][v])
{
/* 有依赖没解码完成,把当前MB加入到它的KoL */
Subscribe(Kol[g][u][v], x, y, f, i+1);
/* “挂起” */
return;
}
} /* 实际的宏块重建工作 */
Picture_Prediction(x, y);
Deblocking_Info(x, y);
Deblocking_Filter(x, y); Ready[f][x][y] = true; /* 恢复帧间依赖于本MB的MB */
for(each quadruple(u, v, g, start) in KoL[f][x][y])
tp_submit(decode_mb, u, v, g, ture, start); /*
*from 2D-Wave
*decrement dependency counters and tail submit
*/
if(y < WIDTH-1){
atomic_dec(dep_count[x][y+1]);
if(dep_count[x][y+1] == 0)
tp_submit(decode_mb, x, y+1, f, false, 0);
}
if(x < HEIGHT-1 && y != 0){
atomic_dec(dep_count[x+1][y-1]);
if(dep_count[x+1][y-1] == 0)
tp_submit(decode_mb, x+1, y-1, f, false, 0);
}
}
优化
优化思路与2D-Wave算法一样,尽可能使得一个核心解码相邻宏块。
void decode_mb(int x, int y, int f, bool mv_pred_done, int RMB_start)
{
down_left_avail = 0;
right_avail = 0; do{
/*
*一个宏块由于“挂起”与“恢复”,可能会重复执行decode_mb,
*而求mvp等步骤只需要执行一次
*/
if(!mv_pred_done)
{
/* 求mvp */
Motion_Vector_Prediction(x, y);
/* 通过mvp得到mv,得到帧间依赖,帧间依赖可能不止一个 */
RMB_List = RMB_Calculation(x, y);
} /* 遍历帧间依赖,如果有依赖没解码完成,应该“挂起”,即return */
for(i = RMB_List.start; i<RMB_List.last; i++)
{
(g,u,v) = get_frame_number_and_MB_coord(RMB_List.rmb[i]);
if(!Ready[g][u][v])
{
/* 有依赖没解码完成,把当前MB加入到它的KoL */
Subscribe(Kol[g][u][v], x, y, f, i+1);
/* “挂起” */
return;
}
} /* 实际的宏块重建工作 */
Picture_Prediction(x, y);
Deblocking_Info(x, y);
Deblocking_Filter(x, y); Ready[f][x][y] = true; /* 恢复帧间依赖于本MB的MB */
for(each quadruple(u, v, g, start) in KoL[f][x][y])
tp_submit(decode_mb, u, v, g, ture, start); /*
*from 2D-Wave
*decrement dependency counters and tail submit
*/
if(y < WIDTH-1){
atomic_dec(dep_count[x][y+1]);
if(dep_count[x][y+1] == 0)
right_avail = 1;
}
if(x < HEIGHT-1 && y != 0){
atomic_dec(dep_count[x+1][y-1]);
if(dep_count[x+1][y-1] == 0)
right_avail = 1;
} /* give priority to right MB */
if(down_left_avail && right_avail)
{
tp_submit(decode_mb, x+1, y-1, f, false, 0);
y++;
mv_pred_done = false;
}
else if(down_left_avail)
{
x++; y--;
mv_pred_done = false;
}
else if(right_avail)
{
y++;
mv_pred_down = false;
}
}while(down_left_avail || right_avail);
}
没资源时挂起任务,有资源时恢复任务,这是一种常见的任务同步需求。我们这里由于假设任务是非抢占类型的,即一个任务不能中间停止,只能从开头执行结束,因此用return代替挂起,重启任务代替恢复。如果在一般的操作系统上实现的话,有各种各样的同步工具,如semaphore、lock、Event等。
关于h.264并行解码算法的更详细分析请参考Ben Juurlink · Mauricio Alvarez-Mesa · Chi Ching Chi · Arnaldo Azevedo · Cor Meenderinck · Alex Ramirez:《Scalable Parallel Programming Applied to H.264/AVC Decoding》
h.264并行解码算法3D-Wave实现(基于多核共享内存系统)的更多相关文章
- h.264并行解码算法2D-Wave实现(基于多核共享内存系统)
cache-coherent shared-memory system 我们最平常使用的很多x86.arm芯片都属于多核共享内存系统,这种系统表现为多个核心能直接对同一内存进行读写访问.尽管内存的存取 ...
- h.264并行解码算法2D-Wave实现(基于多核非共享内存系统)
在<Scalable Parallel Programming Applied to H.264/AVC Decoding>书中,作者基于双芯片18核的Cell BE系统实现了2D-Wav ...
- h.264并行解码算法分析
并行算法类型可以分为两类 Function-level Decomposition,按照功能模块进行并行 Data-level Decomposition,按照数据划分进行并行 Function-le ...
- h.264并行熵解码
在前面讨论并行解码的章节中,我们专注于讨论解码的宏块重建部分,甚至把宏块重建描述成宏块解码,这是因为在解码工作中,宏块重建确实占了相当大的比重,不过解码还包含其它的部分,按照解码流程可粗略分为: 读取 ...
- 让dcef3支持mp3和h.264 mp4解码播放
嵌入式Chromium框架(简称CEF) 是一个由Marshall Greenblatt在2008建立的开源项目,它主要目的是开发一个基于Google Chromium的Webbrowser控件.CE ...
- h.264硬件解码
// H264HWDecoder.m // H264EncoderDecoder // // Created by lujunjie on 2016/11/28. // Copyright © 201 ...
- 音视频编解码技术(一):MPEG-4/H.264 AVC 编解码标准
一.H264 概述 H.264,通常也被称之为H.264/AVC(或者H.264/MPEG-4 AVC或MPEG-4/H.264 AVC) 1. H.264视频编解码的意义 H.264的出现就是为了创 ...
- 【视频编解码·学习笔记】2. H.264简介
一.H.264视频编码标准 H.264视频编码标准是ITU-T与MPEG合作产生的又一巨大成果,自颁布之日起就在业界产生了巨大影响.严格地讲,H.264标准是属于MPEG-4家族的一部分,即MPEG- ...
- H.264视频的RTP荷载格式
Status of This Memo This document specifies an Internet standards track protocol for the Internet ...
随机推荐
- UIWindow详解
UIScreen(屏幕),UIWindow(窗口),UIView(视图)是iOS的几个基本界面元素.其中UIWindow(窗口)和UIView(视图)是为iPhone应用程序构造用户界面的可视组件.U ...
- C 函数指针数组
名字有点绕口,其实更应该翻译为指针函数数组. 记录下对Head-First C这一节的理解,几乎每天班车上都会咪两眼,几乎每次都是看不懂,敲一敲的时候才有些明白. 通俗点讲,这功能解决的是,具有同种签 ...
- springmvc使用@ResponseBody返回json乱码解决方法
1.springmvc 3.2以上的版本解决乱码的方法: 第一步:在配置中加入: <mvc:annotation-driven> <mvc:message-converters re ...
- 用Eclipse+xdebug调试PHP总是在首行自动断点解决方法
问题描述: 使用Eclipse+PDT+xdebug调试PHP程序时,总是在程序的第一行(首行)自动断点,不方便调试. 解决方法: 分别在下面3个位置配置,取消 Break at First Line ...
- Java SE (1)之 JFrame 组件 GridLayout布局
package com.sunzhiyan; import java.awt.*; import javax.swing.*; public class Demo_2 extends JFrame{ ...
- Javascript 汉字转拼音
调用方式: var pinyin = convert("欢迎光临"); alert(pinyin); 新建JS文件:PYConvert.js,内容如下: var PinYin = ...
- ExtJs中处理时间,出现NaN-NaN-NaN的解决方式
关键字: extjs日期格式问题(二) 一般我们的前台代码Ext.grid.ColumnModel里会这样写,以便显示日期格式: Js代码 1..... 2.{header:"birth ...
- 7-1 DBA顾问培训内容@20141230
1, 逻辑读还是物理读? 查询语句的实际执行计划. F5 预计执行计划. --如何产生实际执行计划 ??. --Session收集指令. workload repository report fo ...
- CSS 分组 和 嵌套 选择器
Grouping Selectors 在样式表中有很多具有相同样式的元素. h1{color:green;}h2{color:green;}p{color:green;} 为了尽量减少代码,你可以使用 ...
- WPF 启动初始界面
不经意间发现了wpf的这个小玩意,感觉蛮有意思的.我在项目中添加了一张图片 如图: wpf-1.JPG(10.73 K) 2010-6-6 17:04:47 然后再这张图片的属性中设置它的生成操作为S ...