首页
技术博客
PHP教程
数据库技术
前端开发
HTML5
Nginx
php论坛
新用户注册
|
会员登录
PHP教程
技术博客
编程问答
PNG素材
编程语言
前端技术
Android
PHP教程
HTML5教程
数据库
Linux技术
Nginx技术
PHP安全
WebSerer
职场攻略
JavaScript
开放平台
业界资讯
大话程序猿
登录
极速注册
取消
热门标签 | HotTags
foreach
js
main
subset
tree
dockerfile
python3
expression
netty
bitmap
bit
fetch
php7
text
match
erlang
require
ip
merge
keyword
default
httprequest
bytecode
heap
timezone
web
shell
byte
ascii
client
solr
cmd
golang
regex
future
instance
format
jar
cPlusPlus
hashset
stream
eval
blob
select
hash
uri
web3
replace
settings
vbscript
tags
object
cSharp
triggers
flutter
perl
process
email
random
case
rsa
dll
go
python2
split
io
filter
function
javascript
runtime
controller
utf-8
c语言
post
loops
httpclient
schema
typescript
iostream
当前位置:
开发笔记
>
编程语言
> 正文
格式
作者:mySi2502876237 | 来源:互联网 | 2023-06-17 16:45
版本 v1.0,存在内存问题 在 void v4l2_process_image(struct buffer buf)中对 v4l2 采集来的一帧进行处理,存在 struct buffer bu f
版本 v1.0,存在内存问题
在 void v4l2_process_image(struct buffer buf)中对 v4l2 采集来的一帧进行处理,存在 struct buffer bu
f 中
buffer 结构定义为:
struct buffer {
void * start;
size_t length;
};
buffer.start 为 YUV422 格式数据的起始地址。
有关 YUV 格式:
YUV 格式通常有两大类:打包(packed)格式和平面(planar)格式。前者将 YUV 分量存放在同一个数组中,
通常是几个相邻的像素组成一个宏像素(macro-pixel);而后者使用三个数组分开存放 YUV 三个分量,就像
是一个三维平面一样。
对于 YUV422(YUV2,V4L2_PIX_FMT_YUYV)格式,属于打包格式,存储顺序为:
Byte Order. Each cell is one byte.
start + 0: Y'00 Cb00 Y'01 Cr00 Y'02 Cb01 Y'03 Cr01
start + 8: Y'10 Cb10 Y'11 Cr10 Y'12 Cb11 Y'13 Cr11
start + 16: Y'20 Cb20 Y'21 Cr20 Y'22 Cb21 Y'23 Cr21
start + 24: Y'30 Cb30 Y'31 Cr30 Y'32 Cb31 Y'33 Cr31
参见: http://www.linuxtv.org/downloads/v4l-dvb-apis/re09.html#id2765148 (2010.7.12)
对于 YUV420(YUV2,V4L2_PIX_FMT_YVU420)格式,属于平面格式,存储顺序为:
Byte Order. Each cell is one byte.
start + 0: Y'00 Y'01 Y'02 Y'03
start + 4: Y'10 Y'11 Y'12 Y'13
start + 8: Y'20 Y'21 Y'22 Y'23
start + 12: Y'30 Y'31 Y'32 Y'33
start + 16: Cr00 Cr01
start + 18: Cr10 Cr11
start + 20: Cb00 Cb01
start + 22: Cb10 Cb11
参见: http://www.linuxtv.org/downloads/v4l-dvb-apis/re14.html#id2770792 (2010.7.12)
v4l2 抓取的帧为 YUV422,但 ffmpeg 中 mpeg4 编码的输入帧格式为 YUV420,在 ffmpeg 编码中输入的帧结构
为 AVFrame ,其数据结构中有关帧数据的部分为:
{
uint8_t *data[4];
int linesize[4]; // number of bytes per line
其它信息(是否是 key_frame,已编码图像书 coded_picture_number、
是否作为参考帧 reference、宏块类型 *mb_type 等等,目前未用到);
}
另外要提到的一种数据结构 AVPicture :
typedef struct AVPicture {
uint8_t *data[4];
int linesize[4]; //number of bytes per line
} AVPicture;
AVPicture 的存在有以下原因,AVPicture 将 Picture 的概念从 Frame 中提取出来,就只
由 Picture(图片)本身的信息,亮度、色度和行大小。而 Frame 还有如是否是 key_frame 之类的信息。
所以要从 v4l2 采集到的帧(v4l2_process_image 中 buf.start)转换为 YUV420 格式给编码器,需要两个 A
VFrame(其实 AVPicture 已经足够了):
AVFrame *srcbuf ; //源格式 YUV422
AVFrame *dstbuf ; //目标 YUV420
对于 YUV422 格式只用到了 srcbuf->data[0]存放 YUV 数据(打包格式),和 srcbuf->linesize[0]这是一
帧每行所站的 bytes 数(YUV422 为 width *2)。
对于 YUV420 格式(平面格式),则 data[0]、data[1]、data[2]对应 YUV 三个平面。
data[0]:Y 起始 addr,size 个 y 数据。 (size=width *height)
data[1] = data[0] + size; // U 起始 addr ,size/4 个 U
data[2] = data[1] + size / 4; // V 起始 addr,size/4 个 V
从 YUV422 转换为 YUV420 格式可以利用 ffmpeg 下 libavcodec/imgconvert.c 中的
void yuyv422_to_yuv420p(AVPicture *dst, const AVPicture *src,
int width, int height) 函数,
但要设置好 srcbuf , dstbuf,(强制类型转换)并为分配好内存,刚开始就是在这方面出现问题,后面
再提。
总结,现在有了 buffer buf 结构的帧数据(在 buf.start 中以 YUV422 存储),先要将其放到 AVFrame *
srcbuf 中(仍为 YUV422 格式),再用 yuyv422_to_yuv420p 转换为 YUV420 格式并存在 AVFrame *dstb
uf ,dstbuf 交给编码器 mpeg4 编码。
在版本 v1.0,为初次遇到的内存错误:
●
dstbuf = avcodec_alloc_frame();
只是这样就以为为 srcbuf , dstbuf 分配好了内存。
srcbuf->data[0] = (uint8_t*)buf.start;srcbuf->data[0]指向 buf.start 就开始 yuyv422_to_yuv42
0p 转换了。(见 main.c v4l2_process_image 函数)
运行时错误信息: 段错误
调试信息:
Breakpoint 1, v4l2_process_image (buf=...) at main.c:29
29 srcbuf = avcodec_alloc_frame();
(gdb) s
30 dstbuf = avcodec_alloc_frame();
(gdb) s
31 srcbuf->data[0] = (uint8_t*)buf.start;
(gdb) s
32 srcbuf->linesize[0] = V4L2_WIDTH*2;
(gdb) p srcbuf->data[0]
$1 = (uint8_t *) 0xb7bf6000
(gdb) p srcbuf->data[0][0]@10
Cannot access memory at address 0xb7bf6000
(gdb) p buf.start[0]@10
Attempt to dereference a generic pointer.
(gdb) p dstbuf->data[0]
$2 = (uint8_t *) 0x0
(gdb) p dstbuf->data[0][0]@5
Cannot access memory at address 0x0
srcbuf->data[0]已指向 buf.start,但是无法访问数组的数据,可能是指针为 void*的原因,(uint8_t
*)强制转换也没用。
dstbuf->data[0]的值为 (uint8_t *) 0x0,并没有指向可用的内存。所以 srcbuf = avcodec_alloc_fr
ame()并没有分配内存,可能只是声明了 srcbuf 为 AVFrame。还需要用 malloc()分配内存。
在版本 v1.1,针对以上问题的处理为:
●
uint8_t *picture_bufdst,*picture_bufsrc;
AVFrame *srcbuf = NULL; //源 YUV422
AVFrame *dstbuf = NULL; //目标 YUV420
srcbuf = avcodec_alloc_frame();
dstbuf = avcodec_alloc_frame();
picture_bufsrc = malloc(640 * 480 *2);
srcbuf->data[0] = picture_bufsrc;
memcpy(srcbuf->data[0], buf.start, 640 * 480 * 2);
srcbuf->linesize[0] = V4L2_WIDTH*2; //每行 bytes 数
picture_bufdst = malloc((640 * 480 * 3) / 2); /* size for YUV 420 */
dstbuf->data[0] = picture_bufdst; //Y 起始 addr,size 个 Y
dstbuf->data[1] = dstbuf->data[0] + 640*480; // U 起始 addr ,size/4 个 U
dstbuf->data[2] = dstbuf->data[1] + 640*480/4; // V 起始 addr,size/4 个 V
dstbuf->linesize[0] = c->width;
dstbuf->linesize[1] = c->width / 2;
dstbuf->linesize[2] = c->width / 2;
可见,不但要分配内存,还要使 data[0]等指针指向正确的位置。即对 AVFrame 的初始化(其实也就是内
存分配)。
以下为调试信息:
(gdb) p srcbuf->data[0][0]@10
$2 = "\213r\214t\214t\213u\212r"
(gdb) p buf.start[0]@10
Attempt to dereference a generic pointer.
(gdb) p dstbuf->data[0][0]@5
$3 = "\000\000\000\000"
buf.start[0]仍无法访问, srcbuf , dstbuf 已可用.
在版本 v1.2 改进:
●
encod_init() 为编码的初始化相关的函数。
Srcbuf 直接指向 buf.start ,省略了 memcpy()。
在版本 v1.3 改进:
●
AVCodecContext *c,c->pix_fmt = PIX_FMT_YUYV422 可设置 Pixel forma,将其设为 YUV422 格式,
出错:only YUV420 and YUV422 are supported ,原来是设错了,但知道了支持的格式了。
改为 c->pix_fmt = PIX_FMT_YUV422P ,这样省去了到 YUV420 的转换。
首先 srcbuf 直接指向 buf.start ,出现了段错误,
(gdb) p srcbuf->data[0][0]@10
Cannot access memory at address 0xb7bf5000
(gdb) s
73 out_size = avcodec_encode_video(c, outbuf, OUTBUF_SIZE, srcbuf);
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0x00b76fc6 in ?? () from /lib/tls/i686/cmov/libc.so.6
(gdb) q
再用 memcpy(srcbuf->data[0], buf.start, 640 * 480 * 2);
(gdb) p srcbuf->data[0][0]@10
$1 = "Bk@|>l>{Bm"
77 out_size = avcodec_encode_video(c, outbuf, OUTBUF_SIZE, srcbuf);
(gdb) p out_size
$1 = 0
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0x00b76fc6 in ?? () from /lib/tls/i686/cmov/libc.so.6
srcbuf->data[0]有数据,但仍然在 avcodec_encode_video 中出现段错误。
原因呢?
在 ffmpeg 中对各种格式的解释为:
PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
引自:file:///usr/share/doc/ffmpeg-doc/html/pixfmt_8h.html#a60883d4958a60b91661e97027a85072a
在 V4L2 下的解释:
V4L2_PIX_FMT_YUV422P 4 × 4 pixel image
Byte Order. Each cell is one byte.
start + 0: Y'00 Y'01 Y'02 Y'03
start + 4: Y'10 Y'11 Y'12 Y'13
start + 8: Y'20 Y'21 Y'22 Y'23
start + 12: Y'30 Y'31 Y'32 Y'33
start + 16: Cb00 Cb01
start + 18: Cb10 Cb11
start + 20: Cb20 Cb21
start + 22: Cb30 Cb31
start + 24: Cr00 Cr01
start + 26: Cr10 Cr11
start + 28: Cr20 Cr21
start + 30: Cr30 Cr31
引自:http://www.linuxtv.org/downloads/v4l-dvb-apis/re16.html#id3090524
其 YUV422 是指 PIX_FMT_YUV422P ,仍为平面格式(planar),而 video4linux 输入的应该是 PIX_FMT
_YUYV422 打包格式,所以始终还是要进行转换。
所以本文涉及的 YUV 三中格式总结为:
YUYV422:v4l 输出格式,打包格式
YUV420P,YUV422P:平面格式,ffmpeg 编码器支持的输入格式。(带 P 的为 planar?)
process
struct
buffer
数组
byte
http
linux
vb
api
写下你的评论吧 !
吐个槽吧,看都看了
会员登录
|
用户注册
推荐阅读
text
pack布局管理器的使用方法及注意事项
本文介绍了pack布局管理器在Perl/Tk中的使用方法及注意事项。通过调用pack()方法,可以控制部件在显示窗口中的位置和大小。同时,本文还提到了在使用pack布局管理器时,应注意将部件分组以便在水平和垂直方向上进行堆放。此外,还介绍了使用Frame部件或Toplevel部件来组织部件在窗口内的方法。最后,本文强调了在使用pack布局管理器时,应避免在中间切换到grid布局管理器,以免造成混乱。 ...
[详细]
蜡笔小新 2023-12-10 16:03:24
text
如何用GStreamer删除H264格式的中间部分视频
本文讨论了如何使用GStreamer来删除H264格式视频文件中的中间部分,而不需要进行重编码。作者提出了使用gst_element_seek(...)函数来实现这个目标的思路,并提到遇到了一个解决不了的BUG。文章还列举了8个解决方案,希望能够得到更好的思路。 ...
[详细]
蜡笔小新 2023-12-10 08:46:57
default
Java太阳系小游戏分析和源码详解
本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ...
[详细]
蜡笔小新 2023-12-14 19:53:34
text
在类中定义数组时出错 - Error on defining arrays in class
Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ...
[详细]
蜡笔小新 2023-12-14 17:38:12
ip
android listview OnItemClickListener失效原因
最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ...
[详细]
蜡笔小新 2023-12-14 14:25:50
default
关于cuowu类的错误提示和使用AdjustmentListener的问题
本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ...
[详细]
蜡笔小新 2023-12-13 22:09:56
default
python创建一个窗口_等一个大佬啊 要求用python创建一个窗口,窗口按钮功能是创建一个球体或立方体。明天上课之前交给我...
展开全部下面的代码是创建一个立方体Thisexamplescreatesanddisplaysasimplebox.#Thefirstlineloadstheinit_disp ...
[详细]
蜡笔小新 2023-12-13 16:26:09
text
Android工程师面试准备及设计模式使用场景
本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ...
[详细]
蜡笔小新 2023-12-11 18:25:26
ip
基于Socket的多个客户端之间的聊天功能实现方法
本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ...
[详细]
蜡笔小新 2023-12-11 15:55:40
ip
从入门到高手,让你21天成为VB.NET高手的源代码下载地址
本文介绍了一个从入门到高手的VB.NET源代码,通过学习这些源代码,可以在21天内成为VB.NET高手。文章提供了下载地址,并提醒读者加入作者的QQ群和收藏作者的博客。 ...
[详细]
蜡笔小新 2023-12-10 18:37:37
byte
C++Builder实现获取USB优盘序列号的方法
本文介绍了使用C++Builder实现获取USB优盘序列号的方法,包括相关的代码和说明。通过该方法,可以获取指定盘符的USB优盘序列号,并将其存放在缓冲中。该方法可以在Windows系统中有效地获取USB优盘序列号,并且适用于C++Builder开发环境。 ...
[详细]
蜡笔小新 2023-12-09 08:17:53
web
webpack二刷之二、loader资源模块加载器
loader资源模块加载器webpack资源模块加载webpack内部(内部loader)默认只会处理javascript文件,也就是说它会把打包过程中所有遇到的 ...
[详细]
蜡笔小新 2023-10-17 21:26:42
byte
STM32 IO口模拟串口通讯
转自:http:ziye334.blog.163.comblogstatic224306191201452833850647前阵子,调项目时需要用到低波 ...
[详细]
蜡笔小新 2023-10-17 19:54:28
ip
Android开发笔记:使用Picasso加载网络图片等比例缩放
在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ...
[详细]
蜡笔小新 2023-12-14 17:34:00
ip
Linux重启网络命令实例及关机和重启示例教程
本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ...
[详细]
蜡笔小新 2023-12-14 15:52:52
mySi2502876237
这个家伙很懒,什么也没留下!
Tags | 热门标签
foreach
js
main
subset
tree
dockerfile
python3
expression
netty
bitmap
bit
fetch
php7
text
match
erlang
require
ip
merge
keyword
default
httprequest
bytecode
heap
timezone
web
shell
byte
ascii
client
RankList | 热门文章
1
node . js fs . file handle . datasync()方法
2
bashshell命令行选项与修传入参数处理
3
Python内存数据库/引擎
4
4HTTP响应报文
5
转:builder模式分析
6
防止用户重复提交表单 - 表单令牌
7
制作自己的第一个报表
8
eclipse project is missing required java project
9
sql / mysql搜索两个关键字的一个字段
10
远程访问局域网svn服务器
11
组成数组不成功,请大神指点
12
怎么办怎么办?我和的电脑IP起冲突了?
13
Python面向对象思想与应用入门教程【类与对象】
14
USACO 1.5 Checker Challenge (checker)
15
南阳 oj 448 寻找最大数
PHP1.CN | 中国最专业的PHP中文社区 |
DevBox开发工具箱
|
json解析格式化
|
PHP资讯
|
PHP教程
|
数据库技术
|
服务器技术
|
前端开发技术
|
PHP框架
|
开发工具
|
在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved |
京公网安备 11010802041100号
|
京ICP备19059560号-4
| PHP1.CN 第一PHP社区 版权所有