VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

有编程疑问吗?还请到提问专区发帖提问!
搜索
查看: 349|回复: 6

[求助] 音频数据缓存

[复制链接]
09_avatar_middle
在线会员 啊啊大 发表于 2018-7-12 16:22:19 | 显示全部楼层 |阅读模式
5驿站币
本帖最后由 啊啊大 于 2018-7-12 16:22 编辑

音频数据采集的时候大小不固定怎么做缓存
  1. MyInt32 SpeakerCapture::CaptureAudio()
  2. {
  3.         if (m_pAudioCaptureEvent == nullptr || m_pFormatCtx == nullptr || m_pCodecCtx == nullptr || m_pFrameSrc == nullptr)
  4.         {
  5.                 CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, _T("CAudioCapture::CaptureFunc m_pAudioCaptureEvent == nullptr || m_pFormatCtx == nullptr || m_pCodecCtx == nullptr || m_pFrameSrc == nullptr!"));

  6.                 assert(false);
  7.                 return 0;
  8.         }

  9.         int iResult = -1;
  10.         int iGot = -1;
  11.         AVPacket* pPacket = (AVPacket *)av_malloc(sizeof(AVPacket));
  12.         AVPacket* pPacketTemp = (AVPacket *)av_malloc(sizeof(AVPacket));
  13.         if (pPacket == nullptr)
  14.         {
  15.                 CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, _T("CAudioCapture::CaptureFunc av_malloc Failed!"));

  16.                 assert(false);
  17.                 return 0;
  18.         }

  19. #if defined DEF_STL_THREAD
  20.         while (!m_CaptuureThreadExit.IsExit(0))
  21. #else
  22.         while (!m_bThreadExit)
  23. #endif
  24.         {
  25.                 try
  26.                 {
  27.                         iResult = av_read_frame(m_pFormatCtx, pPacket);//这里获取数据第一次大小是1920后面的大小不固定如何做缓存这个大小要控制在4096和192000之间,之前用了一个环形缓冲区但是没有达到效果,下面要进行解码
  28.                         if (iResult >= 0)
  29.                         {
  30.                                 }
  31.                                 if (pPacket->stream_index == m_iAudioIndex)
  32.                                 {
  33.                                         iResult = avcodec_decode_audio4(m_pCodecCtx, m_pFrameSrc, &iGot, pPacket);解码
  34.                                         if (iResult < 0)
  35.                                         {
  36.                                                 CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, _T("CAudioCapture::CaptureFunc avcodec_decode_audio4 Failed!"));
  37.                                                 av_free_packet(pPacket);
  38.                                                 continue;
  39.                                         }
  40.                                         if (iGot == 1)
  41.                                         {
  42.                                                 if (m_AudioFormatConvert.Convert((const uint8_t **)m_pFrameSrc->data, m_pFrameSrc->nb_samples, pPacket->size))////这里把解码后的数据进行重采样,大小必须在4096和192000之间
  43.                                                 {
  44.                                                         m_pAudioCaptureEvent->OnCaptureData((const char*)m_AudioFormatConvert.GetData(), m_AudioFormatConvert.GetDataLen());/这里获取数据然后进行内存对齐,这里获取的数据就是上面函数重采样后的数据进行内存对齐然后编码
  45.                                                 }
  46.                                                 else
  47.                                                 {
  48.                                                         CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, _T("CAudioCapture::CaptureFunc Convert Failed!"));
  49.                                                 }
  50.                                         }
  51.                                 }
  52.                                 else
  53.                                 {
  54.                                         CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, _T("CAudioCapture::CaptureFunc iGot != 1!"));
  55.                                 }
  56.                         }
  57.                         else
  58.                         {
  59.                                 CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, _T("CAudioCapture::CaptureFunc av_read_frame Failed!"));
  60.                         }

  61.                         av_free_packet(pPacket);
  62.                 }
  63.                 catch (...)
  64.                 {
  65.                         CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, _T("CAudioCapture::CaptureFunc Exception!"));
  66.                 }
  67.         }

  68.         CLog::GetInstance().Log(ENUM_LOG_LEVEL::enum_Log_Level5, _T("CAudioCapture::CaptureFunc Exit!"));
  69.         return 0;
  70. }
复制代码





上一篇:新手初问
下一篇:请教一下,C++如何将UCS-2编码的文件内容读取出来并输出出来

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

51_avatar_middle
online_admins Syc 发表于 2018-7-12 16:48:50 | 显示全部楼层
用 C++ STL 中的 vector 不行吗?先调用其 reserve 方法提前开辟 192000 大小的空间,防止后续重复申请导致的效率问题。

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复

使用道具 举报

09_avatar_middle
ico_lz  楼主| 啊啊大 发表于 2018-7-12 17:13:48 | 显示全部楼层
Syc 发表于 2018-7-12 16:48
用 C++ STL 中的 vector 不行吗?先调用其 reserve 方法提前开辟 192000 大小的空间,防止后续重复申请导致 ...

主要是一次的数据填不满,线程要执行好几次之后才能填满,我调试了一下要满足4096的大小至少要执行2次,但是这时候取数据的线程发现没有数据就会崩溃,所以最好在一次内把数据采集够了,然后再往下执行。而且有的时候采集的数据还大于192000这个数,这个时候还不能全用,得把多出来部分存起来等待下次用。。真的无语。

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复

使用道具 举报

51_avatar_middle
online_admins Syc 发表于 2018-7-12 17:33:06 | 显示全部楼层
啊啊大 发表于 2018-7-12 17:13
主要是一次的数据填不满,线程要执行好几次之后才能填满,我调试了一下要满足4096的大小至少要执行2次, ...

具体你这块的逻辑我不是十分清楚,但是能否进行线程间的同步操作,因为你不能确定具体需要几次能把数据填满,有的电脑2次,有的电脑可能多次,所以取数据的线程能否进行轮训,如果发现没有数据或者没满就过一会再来取

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复

使用道具 举报

09_avatar_middle
ico_lz  楼主| 啊啊大 发表于 2018-7-12 17:40:09 | 显示全部楼层
Syc 发表于 2018-7-12 17:33
具体你这块的逻辑我不是十分清楚,但是能否进行线程间的同步操作,因为你不能确定具体需要几次能把数据填 ...

线程间是没有加锁的

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复

使用道具 举报

09_avatar_middle
ico_lz  楼主| 啊啊大 发表于 2018-7-12 17:48:57 | 显示全部楼层
啊啊大 发表于 2018-7-12 17:40
线程间是没有加锁的

我想在它解码之前就把它缓存满然后拿去解码,后面就不会有问题了。

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复

使用道具 举报

09_avatar_middle
ico_lz  楼主| 啊啊大 发表于 2018-7-12 18:07:28 | 显示全部楼层
Syc 发表于 2018-7-12 17:33
具体你这块的逻辑我不是十分清楚,但是能否进行线程间的同步操作,因为你不能确定具体需要几次能把数据填 ...

而且另外线程是和另一个功能共用的:比如我一个是录制声卡,另一个是录制麦克风,他们的代码几乎一样,处理流程也一样,区别就在于录制声卡时和麦克风的设备名字不一样而已,其他的包括解码编码采样大小都是一样的,不一样的就是声卡的采集出来的数据大小不固定,而麦克风的数据大小是固定的。我在想可不可单独设置只有 采集声卡的时候才加锁,其他时间不同加锁。这样不用修改太多。

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2018-12-11 02:54

Powered by Discuz! X3.4

© 2009-2018 cctry.com

快速回复 返回顶部 返回列表