codec_audio_encoder.cpp 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223
  1. #include "codec_audio_encoder.h"
  2. #include "../base/logger.h"
  3. #include "../base/media_common.h"
  4. #include <algorithm>
  5. #include <chrono>
  6. namespace av {
  7. namespace codec {
  8. // 静态成员初始化
  9. std::vector<std::string> AudioEncoder::supportedEncoders_;
  10. std::once_flag AudioEncoder::encodersInitFlag_;
  11. // AudioResampler 实现
  12. AudioResampler::AudioResampler()
  13. : swrCtx_(nullptr)
  14. , srcFormat_(AV_SAMPLE_FMT_NONE)
  15. , dstFormat_(AV_SAMPLE_FMT_NONE)
  16. , srcSampleRate_(0)
  17. , dstSampleRate_(0)
  18. , dstFrameSize_(0)
  19. , initialized_(false) {
  20. av_channel_layout_default(&srcLayout_, 0);
  21. av_channel_layout_default(&dstLayout_, 0);
  22. }
  23. AudioResampler::~AudioResampler() {
  24. if (swrCtx_) {
  25. swr_free(&swrCtx_);
  26. }
  27. av_channel_layout_uninit(&srcLayout_);
  28. av_channel_layout_uninit(&dstLayout_);
  29. }
  30. bool AudioResampler::init(const AVChannelLayout& srcLayout, AVSampleFormat srcFormat, int srcSampleRate,
  31. const AVChannelLayout& dstLayout, AVSampleFormat dstFormat, int dstSampleRate) {
  32. if (swrCtx_) {
  33. swr_free(&swrCtx_);
  34. }
  35. av_channel_layout_uninit(&srcLayout_);
  36. av_channel_layout_uninit(&dstLayout_);
  37. // 复制声道布局
  38. if (av_channel_layout_copy(&srcLayout_, &srcLayout) < 0 ||
  39. av_channel_layout_copy(&dstLayout_, &dstLayout) < 0) {
  40. AV_LOGGER_ERROR("复制声道布局失败");
  41. return false;
  42. }
  43. srcFormat_ = srcFormat;
  44. dstFormat_ = dstFormat;
  45. srcSampleRate_ = srcSampleRate;
  46. dstSampleRate_ = dstSampleRate;
  47. // 创建重采样上下文
  48. int ret = swr_alloc_set_opts2(&swrCtx_,
  49. &dstLayout_, dstFormat_, dstSampleRate_,
  50. &srcLayout_, srcFormat_, srcSampleRate_,
  51. 0, nullptr);
  52. if (ret < 0) {
  53. AV_LOGGER_ERRORF("创建重采样上下文失败: {}", ffmpeg_utils::errorToString(ret));
  54. return false;
  55. }
  56. // 初始化重采样器
  57. ret = swr_init(swrCtx_);
  58. if (ret < 0) {
  59. AV_LOGGER_ERRORF("初始化重采样器失败: {}", ffmpeg_utils::errorToString(ret));
  60. swr_free(&swrCtx_);
  61. return false;
  62. }
  63. // 计算输出帧大小
  64. dstFrameSize_ = av_rescale_rnd(1024, dstSampleRate_, srcSampleRate_, AV_ROUND_UP);
  65. // 创建输出帧
  66. dstFrame_ = makeAVFrame();
  67. if (!dstFrame_) {
  68. AV_LOGGER_ERROR("分配输出帧失败");
  69. return false;
  70. }
  71. dstFrame_->format = dstFormat_;
  72. dstFrame_->sample_rate = dstSampleRate_;
  73. av_channel_layout_copy(&dstFrame_->ch_layout, &dstLayout_);
  74. dstFrame_->nb_samples = dstFrameSize_;
  75. ret = av_frame_get_buffer(dstFrame_.get(), 0);
  76. if (ret < 0) {
  77. AV_LOGGER_ERRORF("分配帧缓冲区失败: {}", ffmpeg_utils::errorToString(ret));
  78. return false;
  79. }
  80. initialized_ = true;
  81. return true;
  82. }
  83. AVFramePtr AudioResampler::resample(const AVFramePtr& srcFrame) {
  84. if (!initialized_) {
  85. AV_LOGGER_ERROR("AudioResampler not initialized");
  86. return nullptr;
  87. }
  88. if (!srcFrame) {
  89. AV_LOGGER_ERROR("Source frame is null");
  90. return nullptr;
  91. }
  92. if (!swrCtx_) {
  93. AV_LOGGER_ERROR("SwrContext is null");
  94. return nullptr;
  95. }
  96. if (!dstFrame_) {
  97. AV_LOGGER_ERROR("Destination frame is null");
  98. return nullptr;
  99. }
  100. // 验证源帧的有效性
  101. if (srcFrame->nb_samples <= 0) {
  102. AV_LOGGER_ERRORF("Invalid source frame samples: {}", srcFrame->nb_samples);
  103. return nullptr;
  104. }
  105. if (!srcFrame->data[0]) {
  106. AV_LOGGER_ERROR("Source frame data is null");
  107. return nullptr;
  108. }
  109. // 计算输出样本数
  110. int dstSamples = av_rescale_rnd(srcFrame->nb_samples, dstSampleRate_, srcSampleRate_, AV_ROUND_UP);
  111. if (dstSamples <= 0) {
  112. AV_LOGGER_ERRORF("Invalid calculated destination samples: {}", dstSamples);
  113. return nullptr;
  114. }
  115. AV_LOGGER_DEBUGF("Resampling: src_samples={}, dst_samples={}, src_rate={}, dst_rate={}",
  116. srcFrame->nb_samples, dstSamples, srcSampleRate_, dstSampleRate_);
  117. // 确保输出帧有足够的空间
  118. if (dstFrame_->nb_samples < dstSamples) {
  119. AV_LOGGER_DEBUGF("Reallocating destination frame buffer: {} -> {}", dstFrame_->nb_samples, dstSamples);
  120. av_frame_unref(dstFrame_.get());
  121. // 重新设置帧格式信息(av_frame_unref 会清除这些信息)
  122. dstFrame_->format = dstFormat_;
  123. dstFrame_->sample_rate = dstSampleRate_;
  124. int ret = av_channel_layout_copy(&dstFrame_->ch_layout, &dstLayout_);
  125. if (ret < 0) {
  126. AV_LOGGER_ERRORF("复制声道布局失败: {}", ffmpeg_utils::errorToString(ret));
  127. return nullptr;
  128. }
  129. dstFrame_->nb_samples = dstSamples;
  130. ret = av_frame_get_buffer(dstFrame_.get(), 0);
  131. if (ret < 0) {
  132. AV_LOGGER_ERRORF("重新分配帧缓冲区失败: {}", ffmpeg_utils::errorToString(ret));
  133. return nullptr;
  134. }
  135. AV_LOGGER_DEBUGF("Frame buffer reallocated successfully: format={}, rate={}, channels={}, samples={}",
  136. dstFrame_->format, dstFrame_->sample_rate, dstFrame_->ch_layout.nb_channels, dstFrame_->nb_samples);
  137. }
  138. // 验证目标帧的有效性
  139. if (!dstFrame_->data[0]) {
  140. AV_LOGGER_ERROR("Destination frame data is null after allocation");
  141. return nullptr;
  142. }
  143. // 执行重采样
  144. AV_LOGGER_DEBUG("Executing swr_convert...");
  145. int convertedSamples = swr_convert(swrCtx_,
  146. dstFrame_->data, dstSamples,
  147. const_cast<const uint8_t**>(srcFrame->data), srcFrame->nb_samples);
  148. if (convertedSamples < 0) {
  149. AV_LOGGER_ERRORF("音频重采样失败: {}", ffmpeg_utils::errorToString(convertedSamples));
  150. return nullptr;
  151. }
  152. dstFrame_->nb_samples = convertedSamples;
  153. // 创建输出帧的副本
  154. AVFramePtr outputFrame = makeAVFrame();
  155. if (!outputFrame) {
  156. AV_LOGGER_ERROR("分配输出帧失败");
  157. return nullptr;
  158. }
  159. // 复制重采样后的数据
  160. outputFrame->format = dstFrame_->format;
  161. outputFrame->sample_rate = dstFrame_->sample_rate;
  162. av_channel_layout_copy(&outputFrame->ch_layout, &dstFrame_->ch_layout);
  163. outputFrame->nb_samples = convertedSamples;
  164. int ret = av_frame_get_buffer(outputFrame.get(), 0);
  165. if (ret < 0) {
  166. AV_LOGGER_ERRORF("分配输出帧缓冲区失败: {}", ffmpeg_utils::errorToString(ret));
  167. return nullptr;
  168. }
  169. // 复制音频数据
  170. ret = av_frame_copy(outputFrame.get(), dstFrame_.get());
  171. if (ret < 0) {
  172. AV_LOGGER_ERRORF("复制帧数据失败: {}", ffmpeg_utils::errorToString(ret));
  173. return nullptr;
  174. }
  175. // 复制时间戳等信息
  176. av_frame_copy_props(outputFrame.get(), srcFrame.get());
  177. // 调整时间戳
  178. if (srcFrame->pts != AV_NOPTS_VALUE) {
  179. outputFrame->pts = av_rescale_q(srcFrame->pts, {1, srcSampleRate_}, {1, dstSampleRate_});
  180. }
  181. return outputFrame;
  182. }
  183. std::vector<AVFramePtr> AudioResampler::flush() {
  184. std::vector<AVFramePtr> frames;
  185. if (!initialized_) {
  186. return frames;
  187. }
  188. while (true) {
  189. AVFramePtr frame = makeAVFrame();
  190. if (!frame) {
  191. break;
  192. }
  193. frame->format = dstFormat_;
  194. frame->sample_rate = dstSampleRate_;
  195. av_channel_layout_copy(&frame->ch_layout, &dstLayout_);
  196. frame->nb_samples = dstFrameSize_;
  197. int ret = av_frame_get_buffer(frame.get(), 0);
  198. if (ret < 0) {
  199. break;
  200. }
  201. int convertedSamples = swr_convert(swrCtx_,
  202. frame->data, dstFrameSize_,
  203. nullptr, 0);
  204. if (convertedSamples <= 0) {
  205. break;
  206. }
  207. frame->nb_samples = convertedSamples;
  208. frames.push_back(std::move(frame));
  209. }
  210. return frames;
  211. }
  212. // AudioEncoder 实现
  213. AudioEncoder::AudioEncoder()
  214. : AbstractEncoder(MediaType::AUDIO), bufferedSamples_(0) {
  215. AV_LOGGER_DEBUG("创建音频编码器");
  216. }
  217. AudioEncoder::~AudioEncoder() {
  218. close();
  219. AV_LOGGER_DEBUG("音频编码器已销毁");
  220. }
  221. ErrorCode AudioEncoder::open(const CodecParams& params) {
  222. std::lock_guard<std::mutex> lock(encodeMutex_);
  223. if (state_ != CodecState::IDLE && state_ != CodecState::CLOSED) {
  224. AV_LOGGER_WARNING("编码器已打开,先关闭再重新打开");
  225. close();
  226. }
  227. if (!validateParams(params)) {
  228. return ErrorCode::INVALID_PARAMS;
  229. }
  230. audioParams_ = static_cast<const AudioEncoderParams&>(params);
  231. params_ = params;
  232. ErrorCode result = initEncoder();
  233. if (result != ErrorCode::SUCCESS) {
  234. close();
  235. return result;
  236. }
  237. // 初始化帧缓冲区
  238. result = initFrameBuffer();
  239. if (result != ErrorCode::SUCCESS) {
  240. close();
  241. return result;
  242. }
  243. setState(CodecState::OPENED);
  244. AV_LOGGER_INFOF("音频编码器已打开: {} ({}Hz, {}ch, {}kbps)",
  245. audioParams_.codecName, audioParams_.sampleRate,
  246. audioParams_.channels, audioParams_.bitRate / 1000);
  247. return ErrorCode::SUCCESS;
  248. }
  249. void AudioEncoder::close() {
  250. std::lock_guard<std::mutex> lock(encodeMutex_);
  251. if (state_ == CodecState::CLOSED || state_ == CodecState::IDLE) {
  252. return;
  253. }
  254. // 清理资源
  255. resampler_.reset();
  256. convertedFrame_.reset();
  257. // 清理帧缓冲区
  258. clearBuffer();
  259. // 清理编解码上下文
  260. codecCtx_.reset();
  261. codec_ = nullptr;
  262. setState(CodecState::CLOSED);
  263. AV_LOGGER_DEBUG("音频编码器已关闭");
  264. }
  265. ErrorCode AudioEncoder::flush() {
  266. std::lock_guard<std::mutex> lock(encodeMutex_);
  267. if (state_ != CodecState::OPENED && state_ != CodecState::RUNNING) {
  268. return ErrorCode::INVALID_STATE;
  269. }
  270. setState(CodecState::FLUSHING);
  271. // 发送空帧来刷新编码器
  272. int ret = avcodec_send_frame(codecCtx_.get(), nullptr);
  273. if (ret < 0 && ret != AVERROR_EOF) {
  274. AV_LOGGER_ERRORF("刷新编码器失败: {}", ffmpeg_utils::errorToString(ret));
  275. reportError(static_cast<ErrorCode>(ret));
  276. return static_cast<ErrorCode>(ret);
  277. }
  278. setState(CodecState::OPENED);
  279. return ErrorCode::SUCCESS;
  280. }
  281. ErrorCode AudioEncoder::encode(const AVFramePtr& frame, std::vector<AVPacketPtr>& packets) {
  282. // 状态检查(使用基类的线程安全方法)
  283. if (!isOpened()) {
  284. return ErrorCode::INVALID_STATE;
  285. }
  286. // 只在处理过程中锁定,缩小锁的粒度
  287. std::lock_guard<std::mutex> processLock(encodeMutex_);
  288. // 使用StateGuard确保异常安全的状态管理
  289. StateGuard stateGuard(this, CodecState::RUNNING);
  290. auto startTime = std::chrono::high_resolution_clock::now();
  291. ErrorCode result = ErrorCode::SUCCESS;
  292. if (frame) {
  293. // 检查是否需要使用帧缓冲机制
  294. if (codecCtx_->frame_size > 0 && frame->nb_samples != codecCtx_->frame_size) {
  295. AV_LOGGER_DEBUGF("使用帧缓冲机制处理大帧: 输入={}, 期望={}",
  296. frame->nb_samples, codecCtx_->frame_size);
  297. // 将大帧添加到缓冲区
  298. result = addToBuffer(frame);
  299. if (result != ErrorCode::SUCCESS) {
  300. return result;
  301. }
  302. // 从缓冲区提取标准大小的帧进行编码
  303. while (bufferedSamples_ >= codecCtx_->frame_size) {
  304. AVFramePtr smallFrame = extractFrameFromBuffer();
  305. if (smallFrame) {
  306. // 使用move语义明确转移所有权,避免潜在的双重释放
  307. ErrorCode encodeResult = encodeFrame(std::move(smallFrame), packets);
  308. if (encodeResult != ErrorCode::SUCCESS) {
  309. result = encodeResult;
  310. break;
  311. }
  312. } else {
  313. break;
  314. }
  315. }
  316. } else {
  317. // 直接编码(帧大小匹配)
  318. result = encodeFrame(frame, packets);
  319. }
  320. } else {
  321. // 编码空帧(用于刷新)
  322. result = encodeFrame(frame, packets);
  323. }
  324. auto endTime = std::chrono::high_resolution_clock::now();
  325. double processTime = std::chrono::duration<double, std::milli>(endTime - startTime).count();
  326. updateStats(result == ErrorCode::SUCCESS, processTime,
  327. frame ? frame->nb_samples * audioParams_.channels * av_get_bytes_per_sample(static_cast<AVSampleFormat>(frame->format)) : 0);
  328. if (frameCallback_ && frame) {
  329. frameCallback_(frame);
  330. }
  331. for (const auto& packet : packets) {
  332. if (packetCallback_) {
  333. packetCallback_(packet);
  334. }
  335. }
  336. // 只有在成功时才提交状态变更
  337. if (result == ErrorCode::SUCCESS) {
  338. stateGuard.commit();
  339. }
  340. return result;
  341. }
  342. ErrorCode AudioEncoder::finishEncode(std::vector<AVPacketPtr>& packets) {
  343. // 不需要额外的锁,因为调用者已经持有锁
  344. if (state_ != CodecState::OPENED && state_ != CodecState::RUNNING) {
  345. return ErrorCode::INVALID_STATE;
  346. }
  347. // 发送空帧来刷新编码器
  348. int ret = avcodec_send_frame(codecCtx_.get(), nullptr);
  349. if (ret < 0 && ret != AVERROR_EOF) {
  350. AV_LOGGER_ERRORF("刷新编码器失败: {}", ffmpeg_utils::errorToString(ret));
  351. return static_cast<ErrorCode>(ret);
  352. }
  353. // 接收剩余的包
  354. return receivePackets(packets);
  355. }
  356. bool AudioEncoder::validateParams(const CodecParams& params) {
  357. if (params.type != MediaType::AUDIO) {
  358. AV_LOGGER_ERROR("参数媒体类型不是音频");
  359. return false;
  360. }
  361. const auto& audioParams = static_cast<const AudioEncoderParams&>(params);
  362. if (audioParams.sampleRate <= 0) {
  363. AV_LOGGER_ERROR("采样率无效");
  364. return false;
  365. }
  366. if (audioParams.channels <= 0) {
  367. AV_LOGGER_ERROR("声道数无效");
  368. return false;
  369. }
  370. if (audioParams.bitRate <= 0) {
  371. AV_LOGGER_ERROR("比特率无效");
  372. return false;
  373. }
  374. if (audioParams.codecName.empty()) {
  375. AV_LOGGER_ERROR("编码器名称为空");
  376. return false;
  377. }
  378. return true;
  379. }
  380. ErrorCode AudioEncoder::initEncoder() {
  381. // 查找编码器
  382. codec_ = avcodec_find_encoder_by_name(audioParams_.codecName.c_str());
  383. if (!codec_) {
  384. AV_LOGGER_ERRORF("未找到编码器: {}", audioParams_.codecName);
  385. return ErrorCode::CODEC_NOT_FOUND;
  386. }
  387. if (codec_->type != AVMEDIA_TYPE_AUDIO) {
  388. AV_LOGGER_ERROR("编码器类型不是音频");
  389. return ErrorCode::INVALID_PARAMS;
  390. }
  391. // 创建编码上下文
  392. codecCtx_ = makeAVCodecContext(codec_);
  393. if (!codecCtx_) {
  394. AV_LOGGER_ERROR("分配编码上下文失败");
  395. return ErrorCode::MEMORY_ALLOC_FAILED;
  396. }
  397. // 设置编码器参数
  398. ErrorCode result = setupEncoderParams();
  399. if (result != ErrorCode::SUCCESS) {
  400. return result;
  401. }
  402. // 打开编码器
  403. int ret = avcodec_open2(codecCtx_.get(), codec_, nullptr);
  404. if (ret < 0) {
  405. AV_LOGGER_ERRORF("打开编码器失败: {}", ffmpeg_utils::errorToString(ret));
  406. return static_cast<ErrorCode>(ret);
  407. }
  408. return ErrorCode::SUCCESS;
  409. }
  410. ErrorCode AudioEncoder::setupEncoderParams() {
  411. codecCtx_->bit_rate = audioParams_.bitRate;
  412. codecCtx_->sample_rate = audioParams_.sampleRate;
  413. // 设置声道布局
  414. ErrorCode result = setupChannelLayout();
  415. if (result != ErrorCode::SUCCESS) {
  416. return result;
  417. }
  418. // 设置采样格式
  419. codecCtx_->sample_fmt = getBestSampleFormat();
  420. // 设置帧大小
  421. if (codec_->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE) {
  422. codecCtx_->frame_size = audioParams_.frameSize;
  423. }
  424. // 设置配置文件
  425. if (!audioParams_.profile.empty()) {
  426. av_opt_set(codecCtx_->priv_data, "profile", audioParams_.profile.c_str(), 0);
  427. }
  428. return ErrorCode::SUCCESS;
  429. }
  430. ErrorCode AudioEncoder::setupChannelLayout() {
  431. // 设置声道布局
  432. if (audioParams_.channelLayout.nb_channels > 0) {
  433. av_channel_layout_copy(&codecCtx_->ch_layout, &audioParams_.channelLayout);
  434. } else {
  435. // 根据声道数设置默认布局
  436. av_channel_layout_default(&codecCtx_->ch_layout, audioParams_.channels);
  437. }
  438. return ErrorCode::SUCCESS;
  439. }
  440. AVFramePtr AudioEncoder::convertFrame(const AVFramePtr& frame) {
  441. if (!frame) {
  442. return nullptr;
  443. }
  444. // 检查是否需要转换
  445. bool needConvert = false;
  446. if (frame->format != codecCtx_->sample_fmt) {
  447. needConvert = true;
  448. }
  449. if (frame->sample_rate != codecCtx_->sample_rate) {
  450. needConvert = true;
  451. }
  452. if (av_channel_layout_compare(&frame->ch_layout, &codecCtx_->ch_layout) != 0) {
  453. needConvert = true;
  454. }
  455. if (!needConvert) {
  456. // 创建一个新的独立帧副本,避免引用计数问题
  457. AVFramePtr resultFrame = makeAVFrame();
  458. if (!resultFrame) {
  459. return nullptr;
  460. }
  461. // 手动复制帧属性
  462. resultFrame->format = frame->format;
  463. resultFrame->sample_rate = frame->sample_rate;
  464. resultFrame->nb_samples = frame->nb_samples;
  465. resultFrame->pts = frame->pts;
  466. int ret = av_channel_layout_copy(&resultFrame->ch_layout, &frame->ch_layout);
  467. if (ret < 0) {
  468. AV_LOGGER_ERRORF("复制声道布局失败: {}", ffmpeg_utils::errorToString(ret));
  469. return nullptr;
  470. }
  471. // 分配新的数据缓冲区
  472. ret = av_frame_get_buffer(resultFrame.get(), 0);
  473. if (ret < 0) {
  474. AV_LOGGER_ERRORF("分配帧缓冲区失败: {}", ffmpeg_utils::errorToString(ret));
  475. return nullptr;
  476. }
  477. // 复制音频数据
  478. ret = av_frame_copy(resultFrame.get(), frame.get());
  479. if (ret < 0) {
  480. AV_LOGGER_ERRORF("复制帧数据失败: {}", ffmpeg_utils::errorToString(ret));
  481. return nullptr;
  482. }
  483. // 复制帧属性
  484. ret = av_frame_copy_props(resultFrame.get(), frame.get());
  485. if (ret < 0) {
  486. AV_LOGGER_ERRORF("复制帧属性失败: {}", ffmpeg_utils::errorToString(ret));
  487. return nullptr;
  488. }
  489. // 最终验证创建的帧副本
  490. if (!isValidFrame(resultFrame)) {
  491. AV_LOGGER_ERROR("创建的帧副本无效");
  492. return nullptr;
  493. }
  494. AV_LOGGER_DEBUG("创建了不需要转换的帧的独立副本");
  495. return resultFrame;
  496. }
  497. // 创建重采样器
  498. if (!resampler_) {
  499. resampler_ = std::make_unique<AudioResampler>();
  500. if (!resampler_->init(frame->ch_layout, static_cast<AVSampleFormat>(frame->format), frame->sample_rate,
  501. codecCtx_->ch_layout, codecCtx_->sample_fmt, codecCtx_->sample_rate)) {
  502. AV_LOGGER_ERROR("初始化音频重采样器失败");
  503. resampler_.reset(); // 确保失败时清理
  504. return nullptr;
  505. }
  506. AV_LOGGER_INFO("音频重采样器初始化成功");
  507. }
  508. // 双重检查重采样器状态
  509. if (!resampler_) {
  510. AV_LOGGER_ERROR("重采样器为空");
  511. return nullptr;
  512. }
  513. AV_LOGGER_DEBUGF("开始重采样: format={}, rate={}, channels={}",
  514. frame->format, frame->sample_rate, frame->ch_layout.nb_channels);
  515. return resampler_->resample(frame);
  516. }
  517. ErrorCode AudioEncoder::encodeFrame(const AVFramePtr& frame, std::vector<AVPacketPtr>& packets) {
  518. AVFramePtr processedFrame;
  519. if (frame) {
  520. // 格式转换
  521. processedFrame = convertFrame(frame);
  522. if (!processedFrame) {
  523. AV_LOGGER_ERROR("音频帧格式转换失败");
  524. return ErrorCode::CONVERSION_FAILED;
  525. }
  526. // 调试:输出帧信息
  527. AV_LOGGER_DEBUGF("重采样输出帧信息: format={}, rate={}, channels={}, samples={}",
  528. processedFrame->format, processedFrame->sample_rate,
  529. processedFrame->ch_layout.nb_channels, processedFrame->nb_samples);
  530. // 调试:输出编码器期望的信息
  531. AV_LOGGER_DEBUGF("编码器期望格式: format={}, rate={}, channels={}, frame_size={}",
  532. codecCtx_->sample_fmt, codecCtx_->sample_rate,
  533. codecCtx_->ch_layout.nb_channels, codecCtx_->frame_size);
  534. // 检查帧大小是否匹配
  535. if (codecCtx_->frame_size > 0 && processedFrame->nb_samples != codecCtx_->frame_size) {
  536. AV_LOGGER_ERRORF("帧大小不匹配: 输入={}, 编码器期望={}",
  537. processedFrame->nb_samples, codecCtx_->frame_size);
  538. }
  539. // 检查格式是否匹配
  540. if (processedFrame->format != codecCtx_->sample_fmt) {
  541. AV_LOGGER_ERRORF("采样格式不匹配: 输入={}, 编码器期望={}",
  542. processedFrame->format, codecCtx_->sample_fmt);
  543. }
  544. // 检查采样率是否匹配
  545. if (processedFrame->sample_rate != codecCtx_->sample_rate) {
  546. AV_LOGGER_ERRORF("采样率不匹配: 输入={}, 编码器期望={}",
  547. processedFrame->sample_rate, codecCtx_->sample_rate);
  548. }
  549. // 检查声道数是否匹配
  550. if (processedFrame->ch_layout.nb_channels != codecCtx_->ch_layout.nb_channels) {
  551. AV_LOGGER_ERRORF("声道数不匹配: 输入={}, 编码器期望={}",
  552. processedFrame->ch_layout.nb_channels, codecCtx_->ch_layout.nb_channels);
  553. }
  554. }
  555. // 验证processedFrame的有效性
  556. if (processedFrame) {
  557. // 检查帧数据指针的有效性
  558. if (!processedFrame->data || !processedFrame->data[0]) {
  559. AV_LOGGER_ERROR("处理后的帧数据指针无效");
  560. return ErrorCode::INVALID_PARAMS;
  561. }
  562. // 检查帧大小是否合理
  563. if (processedFrame->nb_samples <= 0 || processedFrame->nb_samples > 100000) {
  564. AV_LOGGER_ERRORF("处理后的帧大小异常: {}", processedFrame->nb_samples);
  565. return ErrorCode::INVALID_PARAMS;
  566. }
  567. // 检查声道数是否合理
  568. if (processedFrame->ch_layout.nb_channels <= 0 || processedFrame->ch_layout.nb_channels > 32) {
  569. AV_LOGGER_ERRORF("处理后的帧声道数异常: {}", processedFrame->ch_layout.nb_channels);
  570. return ErrorCode::INVALID_PARAMS;
  571. }
  572. AV_LOGGER_DEBUGF("即将发送帧到编码器: samples={}, format={}, rate={}, channels={}, data_ptr={}",
  573. processedFrame->nb_samples, processedFrame->format,
  574. processedFrame->sample_rate, processedFrame->ch_layout.nb_channels,
  575. static_cast<void*>(processedFrame->data[0]));
  576. } else {
  577. AV_LOGGER_DEBUG("发送空帧到编码器(flush)");
  578. }
  579. // 最后一次验证:确保编码器和帧都有效
  580. if (!codecCtx_ || !codecCtx_.get()) {
  581. AV_LOGGER_ERROR("编码器上下文无效");
  582. return ErrorCode::INVALID_STATE;
  583. }
  584. if (processedFrame) {
  585. // 最终检查:确保帧完全有效
  586. if (!isValidFrame(processedFrame)) {
  587. AV_LOGGER_ERROR("检测到无效的帧数据");
  588. return ErrorCode::INVALID_PARAMS;
  589. }
  590. AV_LOGGER_DEBUG("最终验证通过,帧数据有效");
  591. }
  592. // 发送帧到编码器
  593. AV_LOGGER_DEBUG("开始调用avcodec_send_frame...");
  594. // 在调用FFmpeg之前进行最后的安全检查
  595. if (processedFrame) {
  596. // 确保AVFrame结构本身的完整性
  597. if (processedFrame.get() == nullptr) {
  598. AV_LOGGER_ERROR("严重错误:processedFrame智能指针为null");
  599. return ErrorCode::INVALID_PARAMS;
  600. }
  601. // 检查AVFrame内部指针是否被破坏
  602. if (!processedFrame->data || !processedFrame->data[0]) {
  603. AV_LOGGER_ERROR("严重错误:即将发送的帧数据指针为空");
  604. return ErrorCode::INVALID_PARAMS;
  605. }
  606. AV_LOGGER_DEBUGF("FFmpeg调用前最终检查通过: frame_ptr={}, data_ptr={}",
  607. static_cast<void*>(processedFrame.get()),
  608. static_cast<void*>(processedFrame->data[0]));
  609. }
  610. int ret = avcodec_send_frame(codecCtx_.get(), processedFrame ? processedFrame.get() : nullptr);
  611. AV_LOGGER_DEBUGF("avcodec_send_frame返回: {}", ret);
  612. if (ret < 0) {
  613. ErrorCode error = AbstractCodec::convertFFmpegError(ret);
  614. AV_LOGGER_ERRORF("发送帧到编码器失败: {} ({})",
  615. AbstractCodec::getErrorDescription(error),
  616. ffmpeg_utils::errorToString(ret));
  617. if (processedFrame) {
  618. AV_LOGGER_ERRORF("失败的帧信息: samples={}, format={}, rate={}, channels={}",
  619. processedFrame->nb_samples, processedFrame->format,
  620. processedFrame->sample_rate, processedFrame->ch_layout.nb_channels);
  621. }
  622. return error;
  623. }
  624. // 接收编码后的包
  625. return receivePackets(packets);
  626. }
  627. ErrorCode AudioEncoder::receivePackets(std::vector<AVPacketPtr>& packets) {
  628. while (true) {
  629. AVPacketPtr packet = makeAVPacket();
  630. if (!packet) {
  631. return ErrorCode::MEMORY_ALLOC_FAILED;
  632. }
  633. int ret = avcodec_receive_packet(codecCtx_.get(), packet.get());
  634. if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
  635. break; // 需要更多输入或已结束
  636. }
  637. if (ret < 0) {
  638. ErrorCode error = AbstractCodec::convertFFmpegError(ret);
  639. AV_LOGGER_ERRORF("接收编码包失败: {} ({})",
  640. AbstractCodec::getErrorDescription(error),
  641. ffmpeg_utils::errorToString(ret));
  642. return error;
  643. }
  644. packets.push_back(std::move(packet));
  645. }
  646. return ErrorCode::SUCCESS;
  647. }
  648. AVSampleFormat AudioEncoder::getBestSampleFormat() const {
  649. if (!codec_->sample_fmts) {
  650. return audioParams_.sampleFormat;
  651. }
  652. // 首先尝试使用指定的格式
  653. for (const AVSampleFormat* fmt = codec_->sample_fmts; *fmt != AV_SAMPLE_FMT_NONE; fmt++) {
  654. if (*fmt == audioParams_.sampleFormat) {
  655. return *fmt;
  656. }
  657. }
  658. // 返回第一个支持的格式
  659. return codec_->sample_fmts[0];
  660. }
  661. int AudioEncoder::getBestSampleRate() const {
  662. if (!codec_->supported_samplerates) {
  663. return audioParams_.sampleRate;
  664. }
  665. // 首先尝试使用指定的采样率
  666. for (const int* rate = codec_->supported_samplerates; *rate != 0; rate++) {
  667. if (*rate == audioParams_.sampleRate) {
  668. return *rate;
  669. }
  670. }
  671. // 返回第一个支持的采样率
  672. return codec_->supported_samplerates[0];
  673. }
  674. std::vector<std::string> AudioEncoder::getSupportedEncoders() {
  675. std::call_once(encodersInitFlag_, findSupportedEncoders);
  676. return supportedEncoders_;
  677. }
  678. std::string AudioEncoder::getRecommendedEncoder() {
  679. auto encoders = getSupportedEncoders();
  680. // 优先选择高质量编码器
  681. const char* preferredEncoders[] = {"libfdk_aac", "aac", "libopus", "opus", "libmp3lame", "mp3"};
  682. for (const char* encoder : preferredEncoders) {
  683. if (std::find(encoders.begin(), encoders.end(), encoder) != encoders.end()) {
  684. return encoder;
  685. }
  686. }
  687. return encoders.empty() ? "" : encoders[0];
  688. }
  689. bool AudioEncoder::isSampleFormatSupported(const std::string& codecName, AVSampleFormat format) {
  690. const AVCodec* codec = avcodec_find_encoder_by_name(codecName.c_str());
  691. if (!codec || !codec->sample_fmts) {
  692. return false;
  693. }
  694. for (const AVSampleFormat* fmt = codec->sample_fmts; *fmt != AV_SAMPLE_FMT_NONE; fmt++) {
  695. if (*fmt == format) {
  696. return true;
  697. }
  698. }
  699. return false;
  700. }
  701. bool AudioEncoder::isSampleRateSupported(const std::string& codecName, int sampleRate) {
  702. const AVCodec* codec = avcodec_find_encoder_by_name(codecName.c_str());
  703. if (!codec) {
  704. return false;
  705. }
  706. if (!codec->supported_samplerates) {
  707. return true; // 支持所有采样率
  708. }
  709. for (const int* rate = codec->supported_samplerates; *rate != 0; rate++) {
  710. if (*rate == sampleRate) {
  711. return true;
  712. }
  713. }
  714. return false;
  715. }
  716. bool AudioEncoder::isChannelLayoutSupported(const std::string& codecName, const AVChannelLayout& layout) {
  717. const AVCodec* codec = avcodec_find_encoder_by_name(codecName.c_str());
  718. if (!codec) {
  719. return false;
  720. }
  721. if (!codec->ch_layouts) {
  722. return true; // 支持所有声道布局
  723. }
  724. for (const AVChannelLayout* ch_layout = codec->ch_layouts; ch_layout->nb_channels != 0; ch_layout++) {
  725. if (av_channel_layout_compare(ch_layout, &layout) == 0) {
  726. return true;
  727. }
  728. }
  729. return false;
  730. }
  731. void AudioEncoder::findSupportedEncoders() {
  732. AV_LOGGER_INFO("查找可用的音频编码器...");
  733. for (const char* encoder : AUDIO_ENCODERS) {
  734. if (CodecFactory::isCodecSupported(encoder, CodecType::ENCODER, MediaType::AUDIO)) {
  735. supportedEncoders_.emplace_back(encoder);
  736. AV_LOGGER_INFOF("找到音频编码器: {}", encoder);
  737. }
  738. }
  739. AV_LOGGER_INFOF("总共找到 {} 个可用的音频编码器", supportedEncoders_.size());
  740. }
  741. // 帧缓冲和拆分方法实现
  742. ErrorCode AudioEncoder::initFrameBuffer() {
  743. if (!codecCtx_ || codecCtx_->frame_size <= 0) {
  744. return ErrorCode::SUCCESS; // 不需要缓冲区
  745. }
  746. // 初始化临时帧
  747. tempFrame_ = makeAVFrame();
  748. if (!tempFrame_) {
  749. AV_LOGGER_ERROR("分配临时帧失败");
  750. return ErrorCode::MEMORY_ALLOC_FAILED;
  751. }
  752. // 设置临时帧格式
  753. tempFrame_->format = codecCtx_->sample_fmt;
  754. tempFrame_->sample_rate = codecCtx_->sample_rate;
  755. av_channel_layout_copy(&tempFrame_->ch_layout, &codecCtx_->ch_layout);
  756. tempFrame_->nb_samples = codecCtx_->frame_size;
  757. // 分配临时帧缓冲区
  758. int ret = av_frame_get_buffer(tempFrame_.get(), 0);
  759. if (ret < 0) {
  760. AV_LOGGER_ERRORF("分配临时帧缓冲区失败: {}", ffmpeg_utils::errorToString(ret));
  761. return ErrorCode::MEMORY_ALLOC_FAILED;
  762. }
  763. // 计算缓冲区大小(支持最大帧大小的数据)
  764. int bytesPerSample = av_get_bytes_per_sample(codecCtx_->sample_fmt);
  765. int maxBufferSize = codecCtx_->frame_size * codecCtx_->ch_layout.nb_channels * bytesPerSample * 100; // 支持100倍大小
  766. frameBuffer_.reserve(maxBufferSize);
  767. bufferedSamples_ = 0;
  768. AV_LOGGER_DEBUGF("帧缓冲初始化完成: frame_size={}, channels={}, format={}, buffer_capacity={}",
  769. codecCtx_->frame_size, codecCtx_->ch_layout.nb_channels, codecCtx_->sample_fmt, maxBufferSize);
  770. return ErrorCode::SUCCESS;
  771. }
  772. ErrorCode AudioEncoder::addToBuffer(const AVFramePtr& frame) {
  773. if (!frame || !frame->data[0]) {
  774. return ErrorCode::INVALID_PARAMS;
  775. }
  776. // 计算数据大小
  777. int bytesPerSample = av_get_bytes_per_sample(static_cast<AVSampleFormat>(frame->format));
  778. int channels = frame->ch_layout.nb_channels;
  779. int frameDataSize = frame->nb_samples * channels * bytesPerSample;
  780. AV_LOGGER_DEBUGF("添加到缓冲区: samples={}, bytes={}, buffered_samples={}",
  781. frame->nb_samples, frameDataSize, bufferedSamples_);
  782. // 检查缓冲区容量
  783. if (frameBuffer_.size() + frameDataSize > frameBuffer_.capacity()) {
  784. AV_LOGGER_ERROR("缓冲区容量不足");
  785. return ErrorCode::MEMORY_ALLOC_FAILED;
  786. }
  787. // 将音频数据添加到缓冲区
  788. // 注意:这里假设音频格式是交错的(interleaved),对于平面(planar)格式需要特殊处理
  789. if (av_sample_fmt_is_planar(static_cast<AVSampleFormat>(frame->format))) {
  790. AV_LOGGER_ERROR("暂不支持平面音频格式的缓冲处理");
  791. return ErrorCode::NOT_SUPPORTED;
  792. }
  793. const uint8_t* srcData = frame->data[0];
  794. frameBuffer_.insert(frameBuffer_.end(), srcData, srcData + frameDataSize);
  795. bufferedSamples_ += frame->nb_samples;
  796. AV_LOGGER_DEBUGF("缓冲区更新: total_samples={}, buffer_size={}",
  797. bufferedSamples_, frameBuffer_.size());
  798. return ErrorCode::SUCCESS;
  799. }
  800. AVFramePtr AudioEncoder::extractFrameFromBuffer() {
  801. if (!tempFrame_ || bufferedSamples_ < codecCtx_->frame_size) {
  802. return nullptr;
  803. }
  804. int bytesPerSample = av_get_bytes_per_sample(codecCtx_->sample_fmt);
  805. int channels = codecCtx_->ch_layout.nb_channels;
  806. int frameDataSize = codecCtx_->frame_size * channels * bytesPerSample;
  807. if (frameBuffer_.size() < frameDataSize) {
  808. AV_LOGGER_ERROR("缓冲区数据不足");
  809. return nullptr;
  810. }
  811. // 创建输出帧(手动设置格式信息)
  812. AVFramePtr outputFrame = makeAVFrame();
  813. if (!outputFrame) {
  814. return nullptr;
  815. }
  816. // 手动设置帧格式信息(避免使用av_frame_ref导致缓冲区共享)
  817. outputFrame->format = codecCtx_->sample_fmt;
  818. outputFrame->sample_rate = codecCtx_->sample_rate;
  819. int ret = av_channel_layout_copy(&outputFrame->ch_layout, &codecCtx_->ch_layout);
  820. if (ret < 0) {
  821. AV_LOGGER_ERRORF("复制声道布局失败: {}", ffmpeg_utils::errorToString(ret));
  822. return nullptr;
  823. }
  824. outputFrame->nb_samples = codecCtx_->frame_size;
  825. // 分配新的缓冲区
  826. ret = av_frame_get_buffer(outputFrame.get(), 0);
  827. if (ret < 0) {
  828. AV_LOGGER_ERRORF("分配输出帧缓冲区失败: {}", ffmpeg_utils::errorToString(ret));
  829. return nullptr;
  830. }
  831. // 验证分配的缓冲区是否有效
  832. if (!outputFrame->data || !outputFrame->data[0]) {
  833. AV_LOGGER_ERROR("分配的帧缓冲区无效");
  834. return nullptr;
  835. }
  836. AV_LOGGER_DEBUGF("成功分配帧缓冲区: format={}, samples={}, channels={}, data_ptr={}",
  837. outputFrame->format, outputFrame->nb_samples,
  838. outputFrame->ch_layout.nb_channels, static_cast<void*>(outputFrame->data[0]));
  839. // 安全检查:确保数据足够
  840. if (frameBuffer_.size() < frameDataSize || !outputFrame->data[0]) {
  841. AV_LOGGER_ERROR("数据复制前检查失败");
  842. return nullptr;
  843. }
  844. // 复制数据
  845. AV_LOGGER_DEBUGF("准备复制音频数据: src_ptr={}, dst_ptr={}, size={}",
  846. static_cast<const void*>(frameBuffer_.data()),
  847. static_cast<void*>(outputFrame->data[0]),
  848. frameDataSize);
  849. // 验证源和目标指针的有效性
  850. if (!frameBuffer_.data() || !outputFrame->data[0]) {
  851. AV_LOGGER_ERROR("内存复制:源或目标指针无效");
  852. return nullptr;
  853. }
  854. memcpy(outputFrame->data[0], frameBuffer_.data(), frameDataSize);
  855. AV_LOGGER_DEBUG("音频数据复制完成");
  856. // 设置时间戳(简化处理)
  857. outputFrame->pts = AV_NOPTS_VALUE;
  858. // 最终验证帧的完整性
  859. if (!isValidFrame(outputFrame)) {
  860. AV_LOGGER_ERROR("提取的帧无效,丢弃");
  861. return nullptr;
  862. }
  863. // 安全检查:确保缓冲区操作安全
  864. if (frameDataSize > frameBuffer_.size()) {
  865. AV_LOGGER_ERROR("缓冲区数据不足,无法移除");
  866. return nullptr;
  867. }
  868. // 从缓冲区移除已使用的数据
  869. frameBuffer_.erase(frameBuffer_.begin(), frameBuffer_.begin() + frameDataSize);
  870. bufferedSamples_ -= codecCtx_->frame_size;
  871. AV_LOGGER_DEBUGF("从缓冲区提取帧: samples={}, remaining_samples={}, remaining_bytes={}",
  872. codecCtx_->frame_size, bufferedSamples_, frameBuffer_.size());
  873. // 再次验证帧的有效性(防御性编程)
  874. if (!outputFrame->data[0]) {
  875. AV_LOGGER_ERROR("严重错误:帧数据在返回前变为空指针");
  876. return nullptr;
  877. }
  878. return outputFrame;
  879. }
  880. void AudioEncoder::clearBuffer() {
  881. frameBuffer_.clear();
  882. bufferedSamples_ = 0;
  883. tempFrame_.reset();
  884. AV_LOGGER_DEBUG("帧缓冲区已清除");
  885. }
  886. // AudioEncoderFactory 实现
  887. std::unique_ptr<AudioEncoder> AudioEncoderFactory::create(const std::string& codecName) {
  888. auto encoder = std::make_unique<AudioEncoder>();
  889. if (!codecName.empty()) {
  890. if (!CodecFactory::isCodecSupported(codecName, CodecType::ENCODER, MediaType::AUDIO)) {
  891. AV_LOGGER_ERRORF("不支持的编码器: {}", codecName);
  892. return nullptr;
  893. }
  894. }
  895. return encoder;
  896. }
  897. std::unique_ptr<AudioEncoder> AudioEncoderFactory::createBest() {
  898. std::string codecName = AudioEncoder::getRecommendedEncoder();
  899. if (codecName.empty()) {
  900. AV_LOGGER_ERROR("未找到可用的音频编码器");
  901. return nullptr;
  902. }
  903. return create(codecName);
  904. }
  905. std::unique_ptr<AudioEncoder> AudioEncoderFactory::createLossless() {
  906. auto encoders = AudioEncoder::getSupportedEncoders();
  907. // 优先选择无损编码器
  908. const char* losslessEncoders[] = {"flac", "pcm_s24le", "pcm_s16le"};
  909. for (const char* encoder : losslessEncoders) {
  910. if (std::find(encoders.begin(), encoders.end(), encoder) != encoders.end()) {
  911. return create(encoder);
  912. }
  913. }
  914. AV_LOGGER_WARNING("未找到无损音频编码器,使用默认编码器");
  915. return createBest();
  916. }
  917. // 帧验证工具实现
  918. bool AudioEncoder::isValidFrame(const AVFramePtr& frame) {
  919. return isValidFramePointer(frame.get());
  920. }
  921. bool AudioEncoder::isValidFramePointer(const AVFrame* frame) {
  922. if (!frame) {
  923. return false;
  924. }
  925. // 检查基本属性
  926. if (frame->nb_samples <= 0) {
  927. AV_LOGGER_ERROR("帧样本数无效");
  928. return false;
  929. }
  930. if (frame->format < 0) {
  931. AV_LOGGER_ERROR("帧格式无效");
  932. return false;
  933. }
  934. if (frame->sample_rate <= 0) {
  935. AV_LOGGER_ERROR("帧采样率无效");
  936. return false;
  937. }
  938. if (frame->ch_layout.nb_channels <= 0) {
  939. AV_LOGGER_ERROR("帧声道数无效");
  940. return false;
  941. }
  942. // 检查数据指针
  943. if (!frame->data[0]) {
  944. AV_LOGGER_ERROR("帧数据指针为空");
  945. return false;
  946. }
  947. // 通用的指针有效性检查
  948. uintptr_t ptr = reinterpret_cast<uintptr_t>(frame->data[0]);
  949. // 检查常见的无效指针模式
  950. if (ptr == 0) {
  951. AV_LOGGER_ERROR("帧数据指针为NULL");
  952. return false;
  953. }
  954. if (ptr == UINTPTR_MAX || ptr == (UINTPTR_MAX - 1)) {
  955. AV_LOGGER_ERRORF("帧数据指针为无效值: 0x{:x}", ptr);
  956. return false;
  957. }
  958. // 检查是否在合理的地址范围内(避免空指针附近的地址)
  959. if (ptr < 0x1000) {
  960. AV_LOGGER_ERRORF("帧数据指针在低地址空间: 0x{:x}", ptr);
  961. return false;
  962. }
  963. // 在64位系统上,检查是否在用户空间范围内
  964. #if defined(_WIN64) || defined(__x86_64__) || defined(__aarch64__)
  965. if (ptr > 0x7FFFFFFFFFFF) { // 用户空间上限
  966. AV_LOGGER_ERRORF("帧数据指针超出用户空间: 0x{:x}", ptr);
  967. return false;
  968. }
  969. #endif
  970. // 检查linesize是否合理
  971. if (frame->linesize[0] <= 0) {
  972. AV_LOGGER_ERROR("帧linesize无效");
  973. return false;
  974. }
  975. // 对于音频,检查数据大小是否合理
  976. int expected_size = frame->nb_samples * frame->ch_layout.nb_channels *
  977. av_get_bytes_per_sample(static_cast<AVSampleFormat>(frame->format));
  978. if (expected_size <= 0 || expected_size > 100 * 1024 * 1024) { // 100MB上限
  979. AV_LOGGER_ERRORF("帧数据大小不合理: {} bytes", expected_size);
  980. return false;
  981. }
  982. return true;
  983. }
  984. } // namespace codec
  985. } // namespace av