上一篇文章:https://blog.csdn.net/yinsui1839/article/details/127643856?spm=1001.2014.3001.5502

这两天一直阅读ffplay.c,发现AvPackct在发送给解码器之前总会调用av_packet_alloc 进行申请内存存放AvPackt然后用完后再av_packet_free()。那为什么不一次申请够,循环利用,再到程序结尾再释放,所以就有了这次改动

StreamDataPool.h 可以看我前一篇博客

//
// Created by 19321 on 2022/8/20.
//#ifndef MY_APPLICATION_STREAMDATAPOOL_H
#define MY_APPLICATION_STREAMDATAPOOL_H#include <iostream>
#include <list>
#include <cstring>
extern "C" {
#include "libavutil/avstring.h"
#include "libavutil/channel_layout.h"
#include "libavutil/eval.h"
#include "libavutil/mathematics.h"
#include "libavutil/pixdesc.h"
#include "libavutil/imgutils.h"
#include "libavutil/dict.h"
#include "libavutil/fifo.h"
#include "libavutil/parseutils.h"
#include "libavutil/samplefmt.h"
#include "libavutil/time.h"
#include "libavutil/bprint.h"
#include "libavformat/avformat.h"
#include "libavdevice/avdevice.h"
#include "libswscale/swscale.h"
#include "libavutil/opt.h"
#include "libavcodec/avfft.h"
#include "libswresample/swresample.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libswscale/version.h"
#include "libswresample/swresample.h"
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/channel_layout.h"
#include "libavutil/display.h"
#include "libavutil/mathematics.h"
#include "libavutil/imgutils.h"
#include "libavutil/parseutils.h"
#include "libavutil/eval.h"
#include "libavutil/dict.h"
#include "libavutil/opt.h"
#include "libavcodec/avcodec.h"
#include "libavfilter/avfilter.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"#include <SDL.h>
#include <SDL_thread.h>}#include "StreamDataPool.h"
using namespace std;#define MAX_CAMERA_BUFFER_SIZE 1000
#define WIGHT 640
#define HEIGHT 480
#define IMAGE_SIZE (WIGHT*HEIGHT)#include <iostream>
#include <list>
#include "StreamDataPool.h"
#include <functional>using namespace std;template<class T>
class StreamDataPool {
public:T *buf = NULL;int mSize;int mWriteOps = 0;int mReadOps = 0;bool isVaild = false;int nb_packets;int size;int64_t duration;int abort_request;int serial;SDL_mutex *mutex;SDL_cond *cond;string mName;bool writeData(T *data) {if (buf == NULL) return false;if (((mWriteOps + 1) % mSize) == mReadOps) {printf("writeOps false %d %d \n", mWriteOps, mReadOps);return false;}buf[mWriteOps] = *data;mWriteOps = (mWriteOps + 1) % mSize;return true;}T *readData() {if (buf == NULL) return NULL;if (mReadOps == mWriteOps) {printf("readData false %d %d \n", mWriteOps, mReadOps);return NULL;}int readOps = mReadOps;mReadOps = (mReadOps + 1) % mSize;return &buf[readOps];}list<void *> ReadBufferList(bool isOnlyRead) {list<void *> dataList;if (buf == NULL) return dataList;int readOps = mReadOps;while (readOps != mWriteOps) {dataList.push_back(&buf[readOps]);readOps = (readOps + 1) % mSize;}if (!isOnlyRead) {mReadOps = readOps;}return dataList;}void pop() {if (mReadOps == mWriteOps) return;mReadOps = (mReadOps + 1) % mSize;}void setSize(int size) {mSize = size;mWriteOps = 0;mReadOps = 0;buf = new T[size];}void setSize(int size, string name) {mSize = size;mWriteOps = 0;mReadOps = 0;serial = 0;buf = new T[size];mName = name;}void destroy() {isVaild = false;if (buf != NULL) {delete buf;buf = NULL;}}bool isFull(){if(mWriteOps - mReadOps == mSize) return true;}bool isEnty(){if(mReadOps - mWriteOps) return true;return false; }void clean(){mWriteOps = 0;mReadOps = 0;}
};class PktNode{public:int index = 0;int64_t pts = 0;int type = 0;PktNode(){};PktNode(int Index ,int64_t Pts,int Type ){this->index=Index;this->pts=Pts;this->type=Type;};PktNode &operator=(PktNode &data) {this->index=data.index;this->pts=data.pts;this->type=data.type;return *this;}
};class PktPool {public:AVPacket *pkt = NULL;int serial=0;int index = 0;static int curIndex;PktPool() {pkt = av_packet_alloc();};~PktPool(){av_packet_free(&pkt);}PktPool &operator=(AVPacket *data) {if(pkt != NULL){av_packet_move_ref(this->pkt, data);}return *this;}PktPool &operator=(PktPool &data) {av_packet_move_ref(this->pkt, data.pkt);return *this;}void free(){av_packet_unref(this->pkt);}static PktPool *PktPoolPtr;static PktPool *GetPktPool() {curIndex = (curIndex + 1) % MAX_CAMERA_BUFFER_SIZE;PktPoolPtr[curIndex].index = curIndex;return &PktPoolPtr[curIndex];}
};PktPool* PktPool::PktPoolPtr = new PktPool[MAX_CAMERA_BUFFER_SIZE];
int PktPool::curIndex = 0;#endif //MY_APPLICATION_STREAMDATAPOOL_H

ffplay.cpp

/*
*主要修改了PacketQueue *q 改为 StreamDataPool<PktNode> *q
*优化代码每一次packet_queue_put_private都会调用av_fifo_write,解码的时候还要调用*av_fifo_read获取,减少FFmepeg API使用
*/
static int packet_queue_put_private(StreamDataPool<PktNode> *q, PktPool *pktPool)
{bool ret;if (q->abort_request)return -1;PktNode pktNode(pktPool->index, pktPool->pkt->pts, pktPool->pkt->stream_index);ret = q->writeData(&pktNode);if (ret == false)return -1;q->nb_packets++;q->size += pktPool->pkt->size;q->duration += pktPool->pkt->duration;/* XXX: should duplicate packet data in DV case */SDL_CondSignal(q->cond);return 0;
}static int packet_queue_put(StreamDataPool<PktNode> *q, AVPacket *pkt)
{int ret;PktPool *pktPool = PktPool::GetPktPool();//在内存池里获取到对应的pktPool容器if (pktPool == NULL){av_packet_unref(pkt);return -1;}SDL_LockMutex(q->mutex);*pktPool = pkt;  //赋值pktPool->serial = q->serial;packet_queue_put_private(q,pktPool);SDL_UnlockMutex(q->mutex);return ret;
}/* return < 0 if aborted, 0 if no packet and > 0 if packet.  g++ fftools/ffplay.cpp -I /usr/local/include -I /usr/include/SDL2/ -L /usr/local/lib  -lavformat -lavcodec -lavutil -lswscale -lSDL2  -lavformat -lavcodec -lavdevice -lavutil -lz -lm -lswresample -lpostproc*/static int packet_queue_get(StreamDataPool<PktNode> *q, AVPacket *pkt, int block, int *serial)
{int ret;SDL_LockMutex(q->mutex);for (;;){if (q->abort_request){ret = -1;break;}PktNode *pktNode = q->readData();//从数据队列获取对应的节点PktPool *pktPool = NULL;if (pktNode != NULL){pktPool = &PktPool::PktPoolPtr[pktNode->index];//获取对应的数据内存段}if (pktPool != NULL){q->nb_packets--;q->size -= pktPool->pkt->size;q->duration -= pktPool->pkt->duration;av_packet_move_ref(pkt, pktPool->pkt);if (serial)*serial = pktPool->serial;ret = 1;break;}else if (!block){ret = 0;break;}else{SDL_CondWait(q->cond, q->mutex);}}// printf("ret = %d",ret);SDL_UnlockMutex(q->mutex);return ret;
}

原版:

/*
*原版
*优化代码每一次packet_queue_put_private都会调用av_fifo_write,解码的时候还要调用*av_fifo_read获取,减少FFmepeg API使用
*/
static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt)
{MyAVPacketList pkt1;int ret;if (q->abort_request)return -1;pkt1.pkt = pkt;pkt1.serial = q->serial;ret = av_fifo_write(q->pkt_list, &pkt1, 1);if (ret < 0)return ret;q->nb_packets++;q->size += pkt1.pkt->size + sizeof(pkt1);q->duration += pkt1.pkt->duration;/* XXX: should duplicate packet data in DV case */SDL_CondSignal( q->cond);return 0;
}static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
{AVPacket *pkt1;int ret;pkt1 = av_packet_alloc();if (!pkt1) {av_packet_unref(pkt);return -1;}av_packet_move_ref(pkt1, pkt);SDL_LockMutex(q->mutex);ret = packet_queue_put_private(q, pkt1);SDL_UnlockMutex(q->mutex);if (ret < 0)av_packet_free(&pkt1);return ret;
}static int packet_queue_put_nullpacket(PacketQueue *q, AVPacket *pkt, int stream_index)
{pkt->stream_index = stream_index;return packet_queue_put(q, pkt);
}/* packet queue handling */
static int packet_queue_init(PacketQueue *q)
{memset(q, 0, sizeof(PacketQueue));q->pkt_list = av_fifo_alloc2(1, sizeof(MyAVPacketList), AV_FIFO_FLAG_AUTO_GROW);if (!q->pkt_list)return AVERROR(ENOMEM);q->mutex = SDL_CreateMutex();if (!q->mutex) {av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());return AVERROR(ENOMEM);}q->cond = SDL_CreateCond();if (!q->cond) {av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());return AVERROR(ENOMEM);}q->abort_request = 1;return 0;
}

ffplay.cpp 主要替换PacketQueue *q 为StreamDataPool<PktNode> *q,剔除av_fifo_write av_fifo_read 改为从数据池里获取

编译:g++ ffplay.cpp StreamDataPool.cpp StreamDataPool.h -I /usr/local/include -I /usr/include/SDL2/ -L /usr/local/lib  -lavformat -lavcodec -lavutil -lswscale -lSDL2  -lavformat -lavcodec -lavdevice -lavutil -lz -lm -lswresample -lpostproc

编译后可正常播放视频https://download.csdn.net/download/yinsui1839/86876644

ffplay 内存优化相关推荐

  1. 深度学习框架的内存优化机制

    深度学习框架的内存优化机制 https://www.cnblogs.com/DicksonJYL/p/9576896.html 这篇博文简单介绍下深度学习框架的内存优化方式,主要参考资料1,也就是MX ...

  2. Android优化之内存优化倒计时篇

    本文来自网易云社区 作者:聂雷震 本篇文章介绍的内容是如何在安卓手机上实现高效的倒计时效果,这个高效有两个标准:1.刷新频率足够高,让用户觉得这个倒计时的确是倒计时,而不是幻灯片:2.不能占用太多的内 ...

  3. ANDROID内存优化(大汇总——中)

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 写在最前: 本文的思路主要借鉴了2014年AnDevCon开发者大会的一个演讲PPT,加上 ...

  4. JVM 内存优化设置

    from:http://blog.sina.com.cn/s/blog_707577700100vy4m.html 在一些规模稍大的应用中,Java虚拟机(JVM)的内存设置尤为重要,想在项目中取得好 ...

  5. Android内存优化(三)避免可控的内存泄漏

    相关文章 Android性能优化系列 Java虚拟机系列 前言 内存泄漏向来都是内存优化的重点,它如同幽灵一般存于我们的应用当中,有时它不会现身,但一旦现身就会让你头疼不已.因此,如何避免.发现和解决 ...

  6. SQL Server 2014 内存优化表(1)实现内存优化表

    内存优化表(Memory-Optimized Tables)是SQL Server 2014的新特性,目前仅适用于评估版(Evaluation Edition).开发版(Developer Editi ...

  7. Redis学习-内存优化

    以下为个人学习Redis的备忘录--内存优化,基于Redis4.0.2 1.随时查看info memory,了解内存使用状况: 127.0.0.1:6379> info memory # Mem ...

  8. Android的内存优化

    腾讯公司在五月三十一日开展[腾讯Bugly移动开发人员沙龙]大会.大会上面叶方正老师解说了 关于Android的内存优化的问题,只是我感觉叶老师许多其它的站在了測试的角度上去解释了这一方面,叶老师给我 ...

  9. win7只能管理计算机软件吗,win7可以管理多少内存,win7内存优化软件

    谁都希望自己所使用的电脑运行速度快,尤其是对于那些喜欢打游戏的朋友来说,更要学会优化管理内存,以此提高内存的使用效率,尽可能地提高运行速度.学会管理优化内存,才能确保系统运行快,接下来小编给大家分享提 ...

最新文章

  1. selenium常用命令之操作页面元素及获取元素内容的事件整理
  2. html计算平均分,Calculate phastCon Score for a gene —- 计算基因的phastCon平均分,判断基因保守型...
  3. 黑马程序员之List--队列、栈...
  4. ubuntu 各版本的区别
  5. 如何用比特币现金地址和数字签名证明所有权
  6. numpy-自定义ufunc函数和广播
  7. Angular自学笔记(?)ContentChild和ContentChildren
  8. ux设计中的各种地图_如何在UX设计中使用颜色
  9. c++将.cpp编译为.so文件
  10. 日语学习-多邻国-平假名3
  11. 连微信红包都在催我们长大:90后首次成为红包主力军
  12. linux-headers,如何升级linux-headers-generic?
  13. 童鞋们,颜色采色器,实用工具
  14. 网易云ncm转mp3
  15. sftp服务器配置管理系统,配置sftp服务器
  16. Win7如何解决精简版的迅雷7无法运行
  17. 地区三级联动数据库(中国行政区划分数据库)【2018年1月】
  18. STM32CubeIDE USB Audio声卡 WM8978 + I2S
  19. 搭建FTP站点(Windows)
  20. Arduino开发实例-433M无线模块数据发送与接收

热门文章

  1. 蓝桥杯 算法训练 未名湖边的烦恼 C语言
  2. 好用的报表分析软件有哪些?
  3. SSH连接越狱iPhone
  4. HPROSE PRC通讯
  5. 云服务器liunx系统怎么安装,云服务器怎么安装linux系统
  6. 关于element-ui的blur事件失效,select的blur的bug,以及row在@blur延迟的解决
  7. 小程序获取openid和unionid方法
  8. Android集成友盟推送功能
  9. K-means 算法实现二维数据聚类
  10. 【TS TSP】基于matlab禁忌搜索算法求解31城市旅行商问题【含Matlab源码 1143期】