求助stm32f4 视频解码29 mp3解码decoder=MP3InitDecoder(); 调用解码申请内存这个函数,为什么返回值为零?

netty源码分析之FrameDecoder(LengthFieldBasedFrameDecoder) - 勤奋的asialee的博客 - ITeye技术网站
博客分类:
我们接下来看一个也是比较重要的的解码器LengthFieldBasedFrameDecoder,这个和DelimiterBasedFrameDecoder比起来没有那么难理解,所以我们简单的看一下。
和之前一样,我们先来看一下局部变量。
private final int maxFrameL
private final int lengthFieldO
private final int lengthFieldL
private final int lengthFieldEndO
private final int lengthA
private final int initialBytesToS
private final boolean failF
private boolean discardingTooLongF
private long tooLongFrameL
private long bytesToD
maxFrameLength 这个定义最大帧的长度
lengthFieldOffset 长度属性的起始指针(偏移量)
lengthFieldLength 长度属性的长度,即存放数据包长度的变量的的字节所占的长度
lengthFieldEndOffset 这个是一个快捷属性,是根据lengthFieldOffset和lengthFieldLength计算出来的,即就是起始偏移量+长度=结束偏移量
lengthAdjustment 这个是一个长度调节值,例如当总长包含头部信息的时候,这个可以是个负数,就比较好实现了
initialBytesToStrip 这个属性也比较好理解,就是解码后的数据包需要跳过的头部信息的字节数
failFast 这个和DelimiterBasedFrameDecoder是一致的,就是如果设置成true,当发现解析的数据超过maxFrameLenght就立马报错,否则当整个帧的数据解析完后才报错
discardingTooLongFrame 这个也是一个导出属性,就是当前编码器的状态,是不是处于丢弃超长帧的状态
tooLongFrameLength 这个是当出现超长帧的时候,这个超长帧的长度
bytesToDiscard 这个来定义,当出现超长帧的时候,丢弃的数据的字节数
接下来我们就深入主题,来看这个类的实现,最后我们再分析下javadoc,这样我们就能够彻底的掌握这个编码器了。
if (discardingTooLongFrame) {
long bytesToDiscard = this.bytesToD
int localBytesToDiscard = (int) Math.min(bytesToDiscard, buffer.readableBytes());
buffer.skipBytes(localBytesToDiscard);
bytesToDiscard -= localBytesToD
this.bytesToDiscard = bytesToD
failIfNecessary(ctx, false);
if (buffer.readableBytes() & lengthFieldEndOffset) {
这个逻辑是判断,如果当前的编码器处于丢弃超长帧的状态,这个状态肯定是上传编码的时候被设置成这个状态的,然后取上次丢弃的字节数和当前buffer里面的可读数据的最小值,后面的程序理解起来不是那么直接,这个bytesToDiscard属性主要是在后面设置的,bytesToDiscard = frameLength - buffer.readableBytes(); frameLength是当前超长帧的字节数,buffer.readableBytes是当前buffer里面的数据的字节数,所以它的含义就是告诉编码器下次还要丢弃的字节数,举个例子,最大帧的长度是1000,当前帧的长度是1024,所以超过了最大帧了,比如当前buffer里面长度是18个字节,所以bytesToDiscard就是1024-18 = 1006,含义就是说下次解码的时候还要丢弃1006个字节,那上面的代码就比较好理解了,就是说在计算下一次编码需要丢弃的字节数。后面是就是调用failIfNecessary函数了。
我们先来看一下它的实现吧:
private void failIfNecessary(ChannelHandlerContext ctx, boolean firstDetectionOfTooLongFrame) {
if (bytesToDiscard == 0) {
// Reset to the initial state and tell the handlers that
// the frame was too large.
long tooLongFrameLength = this.tooLongFrameL
this.tooLongFrameLength = 0;
discardingTooLongFrame =
if ((!failFast) ||
(failFast && firstDetectionOfTooLongFrame))
fail(ctx, tooLongFrameLength);
// Keep discarding and notify handlers if necessary.
if (failFast && firstDetectionOfTooLongFrame)
fail(ctx, this.tooLongFrameLength);
如果bytesToDiscard是0,就是说下次编码的时候不需要丢弃了,说明这个超长帧读取完毕,那么将这个编码器的状态设置为非丢弃超长帧状态,如果不是failFast状态或者是failFast又是第一次出现超长帧,就报错,意思其实挺明白,如果不是failFast状态,在这个超长帧读取完毕后理应抛出异常,如果是failFast是第一次发现了超长帧,所以也要抛出异常。else分支很好理解,就是说发现了超长帧,并且客户配置的是立马抛出异常,我们就直接抛出异常即可。
我们接着来看decode的代码实现:
if (buffer.readableBytes() & lengthFieldEndOffset) {
int actualLengthFieldOffset = buffer.readerIndex() + lengthFieldO
long frameL
switch (lengthFieldLength) {
frameLength = buffer.getUnsignedByte(actualLengthFieldOffset);
frameLength = buffer.getUnsignedShort(actualLengthFieldOffset);
frameLength = buffer.getUnsignedMedium(actualLengthFieldOffset);
frameLength = buffer.getUnsignedInt(actualLengthFieldOffset);
frameLength = buffer.getLong(actualLengthFieldOffset);
throw new Error("should not reach here");
这段代码结构性很好,也很好理解,如果发现可读的字节数不够,就返回null,等待下次messageReceived通知,然后根据length的长度进行读操作。
我们接着超下看:
if (frameLength & 0) {
buffer.skipBytes(lengthFieldEndOffset);
throw new CorruptedFrameException(
"negative pre-adjustment length field: " + frameLength);
frameLength += lengthAdjustment + lengthFieldEndO
if (frameLength & lengthFieldEndOffset) {
buffer.skipBytes(lengthFieldEndOffset);
throw new CorruptedFrameException(
"Adjusted frame length (" + frameLength + ") is less " +
"than lengthFieldEndOffset: " + lengthFieldEndOffset);
如果我们发现读到的长度是负值,我们将read指针重新设置成读之前的位置,并抛出异常。
计算帧的长度,这个里面是lengthAdjustment + lengthFieldEndOffset,这个比较好理解,这个里面同样做了判断,就是当前帧的长度,不能比lenghtFieldEndOffset小,含义就是帧的数据内容可能为0,但是不可能为负
if (frameLength & maxFrameLength) {
// Enter the discard mode and discard everything received so far.
discardingTooLongFrame =
tooLongFrameLength = frameL
bytesToDiscard = frameLength - buffer.readableBytes();
buffer.skipBytes(buffer.readableBytes());
failIfNecessary(ctx, true);
// never overflows because it's less than maxFrameLength
int frameLengthInt = (int) frameL
if (buffer.readableBytes() & frameLengthInt) {
这个代码就是在处理超长帧的问题,这个在上面我们已经进行解析了
如果发现当前帧的长度超过超长帧的定义,我们将当前的解码器标记为丢弃超长帧状态
计算下一次编码还需要丢弃的长度
修改buffer的读指针
调用failIfNecessary这个函数,判断是否需要抛出异常,关于failIfNecessary函数我们上面已经讲了
然后返回null标记此次解码失败,等待下次messageReceived通知
然后做一次判断,看当前可读数据是不是够一个int型的字节,因为现在马上要读取数据帧的长度了
if (initialBytesToStrip & frameLengthInt) {
buffer.skipBytes(frameLengthInt);
throw new CorruptedFrameException(
"Adjusted frame length (" + frameLength + ") is less " +
"than initialBytesToStrip: " + initialBytesToStrip);
buffer.skipBytes(initialBytesToStrip);
// extract frame
int readerIndex = buffer.readerIndex();
int actualFrameLength = frameLengthInt - initialBytesToS
ChannelBuffer frame = extractFrame(buffer, readerIndex, actualFrameLength);
buffer.readerIndex(readerIndex + actualFrameLength);
这个是decode的最后的实现了
最开始是做了一个判断,就是起始的跳过字节数的变量太大,也要抛出异常的
计算数据帧的长度,就是数据包头部里面定义的长度减去需要跳过的字节数
最后就是提取数据并修改读指针,最后返回数据帧
我们最后来看下这个类的javadoc吧,我感觉netty的作者作为和我们同年龄的80后青年,不但代码写的好,注释也写的很好,这种分享精神很值得我们学习。
第一种情况:从lenght从头开始,长度为2,不跳过头部
lengthFieldOffset
lengthFieldLength
lengthAdjustment
initialBytesToStrip = 0 (= do not strip header)
BEFORE DECODE (14 bytes)
AFTER DECODE (14 bytes)
+--------+----------------+
+--------+----------------+
| Length | Actual Content |-----&| Length | Actual Content |
| 0x000C | "HELLO, WORLD" |
| 0x000C | "HELLO, WORLD" |
+--------+----------------+
+--------+----------------+
第二种情况,从length从头开始,长度为2,跳过头部
lengthFieldOffset
lengthFieldLength
lengthAdjustment
initialBytesToStrip = 2 (= the length of the Length field)
BEFORE DECODE (14 bytes)
AFTER DECODE (12 bytes)
+--------+----------------+
+----------------+
| Length | Actual Content |-----&| Actual Content |
| 0x000C | "HELLO, WORLD" |
| "HELLO, WORLD" |
+--------+----------------+
+----------------+
这个和上面的区别是,数据经过解码后头部被去掉了
第三种情况,2个字节长度的头部,offset是0,但是长度代表的是整个数据帧的长度,即就是包含头部
lengthFieldOffset
lengthFieldLength
lengthAdjustment
= -2 (= the length of the Length field)
initialBytesToStrip =
BEFORE DECODE (14 bytes)
AFTER DECODE (14 bytes)
+--------+----------------+
+--------+----------------+
| Length | Actual Content |-----&| Length | Actual Content |
| 0x000E | "HELLO, WORLD" |
| 0x000E | "HELLO, WORLD" |
+--------+----------------+
+--------+----------------+
第四种情况,5个字节长度的头部,但是数据帧的lenght的字节数是3,offset是2,不跳过头部
lengthFieldOffset
= 2 (= the length of Header 1)
lengthFieldLength
lengthAdjustment
initialBytesToStrip = 0
BEFORE DECODE (17 bytes)
AFTER DECODE (17 bytes)
+----------+----------+----------------+
+----------+----------+----------------+
| Header 1 |
| Actual Content |-----&| Header 1 |
| Actual Content |
| 0x00000C | "HELLO, WORLD" |
| 0x00000C | "HELLO, WORLD" |
+----------+----------+----------------+
+----------+----------+----------------+
第五种情况,5个字节长度的头部,但是数据帧的lenght的字节数是3,offset是0,不跳过头部
lengthFieldOffset
lengthFieldLength
lengthAdjustment
= 2 (= the length of Header 1)
initialBytesToStrip = 0
BEFORE DECODE (17 bytes)
AFTER DECODE (17 bytes)
+----------+----------+----------------+
+----------+----------+----------------+
| Header 1 | Actual Content |-----&|
| Header 1 | Actual Content |
| 0x00000C |
| "HELLO, WORLD" |
| 0x00000C |
| "HELLO, WORLD" |
+----------+----------+----------------+
+----------+----------+----------------+
这个稍微解释一下,由于我们的头部是5个字节,但是length数据域只有3个字节,所以lengthAdjustment是2,表明需要2个字节来调整整个帧的长度。
第六种情况,4个字节长度的头部,但是数据帧的lenght的字节数是2,offset是1,跳过头部第一个数据域和长度域
lengthFieldOffset
= 1 (= the length of HDR1)
lengthFieldLength
lengthAdjustment
= 1 (= the length of HDR2)
initialBytesToStrip = 3 (= the length of HDR1 + LEN)
BEFORE DECODE (16 bytes)
AFTER DECODE (13 bytes)
+------+--------+------+----------------+
+------+----------------+
| HDR1 | Length | HDR2 | Actual Content |-----&| HDR2 | Actual Content |
| 0xCA | 0x000C | 0xFE | "HELLO, WORLD" |
| 0xFE | "HELLO, WORLD" |
+------+--------+------+----------------+
+------+----------------+
这个我稍微解释一下,HDR1是一个字节,Lenght是2个字节,HDR2是两个字节,解码后需要包含HDR2,所以lenghtFieldOffset是1,lenghtFieldLenght是2,lenghtAdjustment是1,实际上就是HDR2的长度,initailBytesToStrip是3,实际上就是HDR1+LEN的长度。
第七种情况,4个字节长度的头部,但是数据帧的lenght的字节数是2,offset是1,跳过头部第一个数据域和长度域,消息的长度代表整个数据帧的长度
lengthFieldOffset
lengthFieldLength
lengthAdjustment
= -3 (= the length of HDR1 + LEN, negative)
initialBytesToStrip =
BEFORE DECODE (16 bytes)
AFTER DECODE (13 bytes)
+------+--------+------+----------------+
+------+----------------+
| HDR1 | Length | HDR2 | Actual Content |-----&| HDR2 | Actual Content |
| 0xCA | 0x0010 | 0xFE | "HELLO, WORLD" |
| 0xFE | "HELLO, WORLD" |
这个我稍微解释一下,HDR1是一个字节,Lenght是2个字节,HDR2是两个字节,解码后需要包含HDR2,所以lenghtFieldOffset是1,lenghtFieldLenght是2,lenghtAdjustment是-3,实际上就是HDR1+LEN的长度,initailBytesToStrip是3,实际上就是HDR1+LEN的长度。
浏览 14286
浏览: 685178 次
来自: 北京
感觉LogManager打开了所有的LogSegment(文件 ...
大神 你好 我再使用ueditor 进行编辑的时候发现他会在我 ...MP3_Decoder 用matlab实现的mp3解码器,硬件电路完整
259万源代码下载-
&文件名称: MP3_Decoder& & [
& & & & &&]
&&所属分类:
&&开发工具: matlab
&&文件大小: 29 KB
&&上传时间:
&&下载次数: 47
&&提 供 者:
&详细说明:用matlab实现的mp3解码器,硬件电路完整-Using matlab to achieve the mp3 decoder, hardware integrity
文件列表(点击判断是否您需要的文件,如果是垃圾请在下面评价投诉):
&&MP3_Decoder\license.txt&&...........\Project M Files\alias_reduction.m&&...........\...............\bit_conv.m&&...........\...............\bit_rate_check.m&&...........\...............\count1_parser.m&&...........\...............\decoder.m&&...........\...............\desktop.ini&&...........\...............\fill_D.m&&...........\...............\fill_windows.m&&...........\...............\filterbank.m&&...........\...............\frequency_check.m&&...........\...............\frequency_inverter.m&&...........\...............\freq_inv.mat&&...........\...............\huffman_parser.m&&...........\...............\huffman_tables.m&&...........\...............\IMDCT.m&&...........\...............\reorder_spectrum.m&&...........\...............\requantizer.m&&...........\...............\scalefac_range.m&&...........\...............\scale_compress2slens.m&&...........\...............\scale_length_selec.m&&...........\...............\scsfi_expander.m&&...........\...............\stereo_processing.m&&...........\Project M Files&&MP3_Decoder
&[]:纯粹是垃圾&[]:很好,推荐下载
&近期下载过的用户:
&相关搜索:
&输入关键字,在本站259万海量源码库中尽情搜索:
&[] - 利用Matlab实现mp3文件的解码和播放的源程序。
&[] - MATLAB版本的mp3播放器(GUI),其中包含matlab MP3解码编码工具包,可实现在matlab平台下对MP3文件的读写操作,非常实用。
&[] - mp3解码文件,详细介绍了如何对一个mp3格式文件进行分解
&[] - 基于matlab的mp3的读写函数Mp3 toolbox for Matlab. Alfredo Fernandez Franco Aalborg University Departament of Acoustics M.Sc. Student
&[] - 一个用matlab实现的mp3解码源程序,对进行mp3开发的初学者非常有用
&[] - mp3 解码的verilog代码,通过仿真综合及验证,能够播放所有的.mp3文件。压缩包包括所有的verilog源码以及详细的文档。
&[] - AAC编码器的matlab实现,可以导出AAC编码中间过程的系数
&[] - 用于音频质量评价的客观算法,由加拿大mcgill大学开发,内有详细说明。
&[] - mp3 解码的verilog代码,通过仿真综合及验证,能够播放所有的.mp3文件。压缩包包括所有的verilog源码以及详细的文档。
&[] - 毕业论文,mp3编码研究及实现,讲解深入而精辟,非常值得一看.Delphi_Mp3Decoder 一个用 编写的Mp3解码播放器,使用WaveOut函数输出音 内有调速功能及算法。感 VCL 254万源代码下载-
&文件名称: Delphi_Mp3Decoder& & [
& & & & &&]
&&所属分类:
&&开发工具: Delphi
&&文件大小: 202 KB
&&上传时间:
&&下载次数: 43
&&提 供 者:
&详细说明:一个用Delphi编写的Mp3解码播放器,使用WaveOut函数输出音频,内有调速功能及算法。感兴趣的可以下载来参考-A Delphi Mp3 decoding player audio output, use the WaveOut function, speed control function and algorithm. Interested can download the reference! !
文件列表(点击判断是否您需要的文件,如果是垃圾请在下面评价投诉):
&&MpegLayer3Demo.exe&&bits.obj&&mpaudec.obj&&Unit1.dfm&&MpegLayer3Demo.dpr&&ll.pas&&MpegLayer3Decode.pas&&Unit1.pas&&MpegLayer3Demo.res
&[]:很好,推荐下载
&近期下载过的用户:
&相关搜索:
&输入关键字,在本站254万海量源码库中尽情搜索:
&[] - 标准H264解码播放,采用VC6编写的播放库源码,h.264解码其中还包含有delphi写的调用例子和VC6写的通过JRTP网络传输解码播放,采用Directx7.0 offscreen解码显示,解码支持各种分辨率,是学习H264和Directx,JRTP的绝佳例子,代码为本人原创
&[] - fft源代码,在delphi环境下开发的。没有密码,随意下。
&[] - delphi的音频控件,用不起来acm的可以试试看
&[] - 在delphi中实现环形缓冲区,可以实现多线程读写
&[] - XVID应用程序编码接口 非常好用 不错的文档对开发开源压缩视频的朋友
&[] - 一个非常好用的MP3音乐播放控件,带例子。适合Delphi和C++使用。查看: 12652|回复: 10
helix软件解码MP3,适合没有VS1003超级高富帅解码芯片的兄弟
主题帖子精华
新手上路, 积分 41, 距离下一级还需 9 积分
在线时间0 小时
用的是 stm32F407Discovery&168M& 带I2S接口(裸奔)
由于Discovery自带一颗CS43L22 音频DAC,放着也浪费,就移植Helix,来软件解码MP3。
解码320kbs的MP3文件没什么问题。
2bac807a_646.jpg (0 Bytes, 下载次数: 0)
22:54 上传
2bb9ca46b82e2689e64dea3f972a00e6_531.jpg (0 Bytes, 下载次数: 0)
22:54 上传
这是官方的资源占用
5ff3bb253_654.jpg (0 Bytes, 下载次数: 0)
22:54 上传
这是实际编译没有优化0的资源占用
适合没有牛x的vs1003解码芯片,有颗强大的mcu的,都可以试试。
22:24 上传
点击文件名下载附件
1.27 MB, 下载次数: 999
22:24 上传
点击文件名下载附件
10.75 MB, 下载次数: 2566
主题帖子精华
在线时间450 小时
主题帖子精华
初级会员, 积分 74, 距离下一级还需 126 积分
在线时间2 小时
哇,刚好1003效果不佳,刚好手里有块407,试试。
主题帖子精华
新手上路, 积分 41, 距离下一级还需 9 积分
在线时间0 小时
自己小顶顶
主题帖子精华
初级会员, 积分 172, 距离下一级还需 28 积分
在线时间6 小时
CS43L22 音质怎么样?
Discovery板刚出的时候我很关注他的音质,因为对HiFi感兴趣,但据说也不是很好
主题帖子精华
新手上路, 积分 41, 距离下一级还需 9 积分
在线时间0 小时
回复【5楼】arm51avr:
---------------------------------
音质还行吧,听不出和电脑的差别。
主题帖子精华
新手上路, 积分 41, 距离下一级还需 9 积分
在线时间0 小时
回复【楼主位】暮雨微凉:
---------------------------------
楼主的代码很有参考价值。我试了一下。发现歌曲播放速度明显偏慢,音调也不对,请问这怎么解决
主题帖子精华
在线时间137 小时
回复【7楼】凌晨一点:
---------------------------------
I2S&nbspLL需要调整。原厂是48khz采样率,你需要自行调整为适合44.1k的I2S&nbspLL
主题帖子精华
新手上路, 积分 41, 距离下一级还需 9 积分
在线时间0 小时
回复【8楼】ricefat:
---------------------------------
嗯,楼主操作DAC的代码应该是参考官方例程的,
有一个函数
void&AduioPlayer_Init(uint32_t&AudioFreq)
{
&&&I2S3_Init(AudioFreq);&
}
他应该能自动根据MP3文件来初始化IIS&的PLL吧
主题帖子精华
新手上路, 积分 41, 距离下一级还需 9 积分
在线时间0 小时
回复【8楼】ricefat:
---------------------------------
解决了。的确是这个问题。原厂在system_stm32f4xx.c这个文件中初始化了IIS的时钟&&
&&&&&&&&nbspLLI2S_N&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|&192
&&*-----------------------------------------------------------------------------
&&*&&&&&&&&nbspLLI2S_R&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&|&5
&&*-----------------------------------------------------------------------------
&&*&&&&&&&&I2S&input&clock&&&&&&&&&&&&&&&&&&&&&&&&|&
把PLLI2S_N&&改成221&就可以了
主题帖子精华
高级会员, 积分 691, 距离下一级还需 309 积分
在线时间30 小时
播放&MP3&VS1003&或是&VS1053&都比&iPOD&差很多,VSxxx&系列播放MP3很混浊.
Powered by

我要回帖

更多关于 urldecoder 解码 的文章

 

随机推荐