ShowVideoWidget.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. 
  2. #include "showVideoWidget.h"
  3. #include "ui_showVideoWidget.h"
  4. #include <QPainter>
  5. #include <QDebug>
  6. #include <QOpenGLWidget>
  7. #include <QOpenGLShaderProgram>
  8. #include <QOpenGLFunctions>
  9. #include <QOpenGLTexture>
  10. #include <QFile>
  11. #include <QOpenGLTexture>
  12. #include <QOpenGLBuffer>
  13. #include <QMouseEvent>
  14. #include <QTimer>
  15. #include <QDrag>
  16. #include <QMimeData>
  17. #include <QApplication>
  18. #include <QDesktopWidget>
  19. #include <QScreen>
  20. #include <QDateTime>
  21. #include "AppConfig.h"
  22. #define ATTRIB_VERTEX 3
  23. #define ATTRIB_TEXTURE 4
  24. ///用于绘制矩形
  25. //! [3]
  26. static const char *vertexShaderSource =
  27. "attribute highp vec4 posAttr;\n"
  28. "attribute lowp vec4 colAttr;\n"
  29. "varying lowp vec4 col;\n"
  30. "uniform highp mat4 matrix;\n"
  31. "void main() {\n"
  32. " col = colAttr;\n"
  33. " gl_Position = posAttr;\n"
  34. "}\n";
  35. static const char *fragmentShaderSource =
  36. "varying lowp vec4 col;\n"
  37. "void main() {\n"
  38. " gl_FragColor = col;\n"
  39. "}\n";
  40. //! [3]
  41. ShowVideoWidget::ShowVideoWidget(QWidget *parent) :
  42. QOpenGLWidget(parent),
  43. ui(new Ui::ShowVideoWidget)
  44. {
  45. ui->setupUi(this);
  46. connect(ui->pushButton_close, &QPushButton::clicked, this, &ShowVideoWidget::sig_CloseBtnClick);
  47. ui->pushButton_close->hide();
  48. mIsPlaying = false;
  49. mPlayFailed = false;
  50. ui->widget_erro->hide();
  51. ui->widget_name->hide();
  52. textureUniformY = 0;
  53. textureUniformU = 0;
  54. textureUniformV = 0;
  55. id_y = 0;
  56. id_u = 0;
  57. id_v = 0;
  58. m_pVSHader = NULL;
  59. m_pFSHader = NULL;
  60. m_pShaderProgram = NULL;
  61. m_pTextureY = NULL;
  62. m_pTextureU = NULL;
  63. m_pTextureV = NULL;
  64. m_vertexVertices = new GLfloat[8];
  65. mVideoFrame.reset();
  66. m_nVideoH = 0;
  67. m_nVideoW = 0;
  68. mPicIndex_X = 0;
  69. mPicIndex_Y = 0;
  70. setAcceptDrops(true);
  71. mCurrentVideoKeepAspectRatio = AppConfig::gVideoKeepAspectRatio;
  72. mIsShowFaceRect = false;
  73. mIsCloseAble = true;
  74. mIsOpenGLInited = false;
  75. mLastGetFrameTime = 0;
  76. }
  77. ShowVideoWidget::~ShowVideoWidget()
  78. {
  79. delete ui;
  80. }
  81. void ShowVideoWidget::setIsPlaying(bool value)
  82. {
  83. mIsPlaying = value;
  84. FunctionTransfer::runInMainThread([&]()
  85. {
  86. if (!mIsPlaying)
  87. {
  88. ui->pushButton_close->hide();
  89. }
  90. update();
  91. });
  92. }
  93. void ShowVideoWidget::setPlayFailed(bool value)
  94. {
  95. mPlayFailed = value;
  96. FunctionTransfer::runInMainThread([&]()
  97. {
  98. update();
  99. });
  100. }
  101. void ShowVideoWidget::setCameraName(QString name)
  102. {
  103. mCameraName = name;
  104. FunctionTransfer::runInMainThread([&]()
  105. {
  106. update();
  107. });
  108. }
  109. void ShowVideoWidget::setVideoWidth(int w, int h)
  110. {
  111. if (w <= 0 || h <= 0) return;
  112. m_nVideoW = w;
  113. m_nVideoH = h;
  114. qDebug()<<__FUNCTION__<<w<<h<<this->isHidden();
  115. if (mIsOpenGLInited)
  116. {
  117. FunctionTransfer::runInMainThread([&]()
  118. {
  119. resetGLVertex(this->width(), this->height());
  120. });
  121. }
  122. }
  123. void ShowVideoWidget::setCloseAble(bool isCloseAble)
  124. {
  125. mIsCloseAble = isCloseAble;
  126. }
  127. void ShowVideoWidget::clear()
  128. {
  129. FunctionTransfer::runInMainThread([&]()
  130. {
  131. mVideoFrame.reset();
  132. mFaceInfoList.clear();
  133. update();
  134. });
  135. }
  136. void ShowVideoWidget::enterEvent(QEvent *event)
  137. {
  138. // qDebug()<<__FUNCTION__;
  139. if (mIsPlaying && mIsCloseAble)
  140. ui->pushButton_close->show();
  141. }
  142. void ShowVideoWidget::leaveEvent(QEvent *event)
  143. {
  144. // qDebug()<<__FUNCTION__;
  145. ui->pushButton_close->hide();
  146. }
  147. void ShowVideoWidget::mouseMoveEvent(QMouseEvent *event)
  148. {
  149. if ((event->buttons() & Qt::LeftButton) && mIsPlaying)
  150. {
  151. QDrag *drag = new QDrag(this);
  152. QMimeData *mimeData = new QMimeData;
  153. ///为拖动的鼠标设置一个图片
  154. // QPixmap pixMap = QPixmap::grabWindow(this->winId());
  155. QPixmap pixMap = this->grab();
  156. // QPixmap fullScreenPixmap = QPixmap::grabWindow(QApplication::desktop()->winId());
  157. // QPixmap pixMap = fullScreenPixmap.copy(200,100,600,400);
  158. QString name = mCameraName;
  159. if (name.isEmpty())
  160. {
  161. name = "drag";
  162. }
  163. QString filePath = QString("%1/%2.png").arg(AppConfig::AppDataPath_Tmp).arg(name);
  164. pixMap.save(filePath);
  165. QList<QUrl> list;
  166. QUrl url = "file:///" + filePath;
  167. list.append(url);
  168. mimeData->setUrls(list);
  169. drag->setPixmap(pixMap);
  170. ///实现视频画面拖动,激发拖动事件
  171. mimeData->setData("playerid", mPlayerId.toUtf8());
  172. drag->setMimeData(mimeData);
  173. // qDebug()<<__FUNCTION__<<"11111";
  174. drag->start(Qt::CopyAction| Qt::MoveAction);
  175. // qDebug()<<__FUNCTION__<<"99999";
  176. }
  177. else
  178. {
  179. QWidget::mouseMoveEvent(event);
  180. }
  181. }
  182. void ShowVideoWidget::inputOneFrame(VideoFramePtr videoFrame)
  183. {
  184. FunctionTransfer::runInMainThread([&]()
  185. {
  186. int width = videoFrame.get()->width();
  187. int height = videoFrame.get()->height();
  188. if (m_nVideoW <= 0 || m_nVideoH <= 0 || m_nVideoW != width || m_nVideoH != height)
  189. {
  190. setVideoWidth(width, height);
  191. }
  192. mLastGetFrameTime = QDateTime::currentMSecsSinceEpoch();
  193. mVideoFrame.reset();
  194. mVideoFrame = videoFrame;
  195. update(); //调用update将执行 paintEvent函数
  196. });
  197. }
  198. void ShowVideoWidget::initializeGL()
  199. {
  200. qDebug()<<__FUNCTION__<<mVideoFrame.get();
  201. mIsOpenGLInited = true;
  202. initializeOpenGLFunctions();
  203. glEnable(GL_DEPTH_TEST);
  204. //现代opengl渲染管线依赖着色器来处理传入的数据
  205. //着色器:就是使用openGL着色语言(OpenGL Shading Language, GLSL)编写的一个小函数,
  206. // GLSL是构成所有OpenGL着色器的语言,具体的GLSL语言的语法需要读者查找相关资料
  207. //初始化顶点着色器 对象
  208. m_pVSHader = new QOpenGLShader(QOpenGLShader::Vertex, this);
  209. //顶点着色器源码
  210. const char *vsrc = "attribute vec4 vertexIn; \
  211. attribute vec2 textureIn; \
  212. varying vec2 textureOut; \
  213. void main(void) \
  214. { \
  215. gl_Position = vertexIn; \
  216. textureOut = textureIn; \
  217. }";
  218. //编译顶点着色器程序
  219. bool bCompile = m_pVSHader->compileSourceCode(vsrc);
  220. if(!bCompile)
  221. {
  222. }
  223. //初始化片段着色器 功能gpu中yuv转换成rgb
  224. m_pFSHader = new QOpenGLShader(QOpenGLShader::Fragment, this);
  225. //片段着色器源码(windows下opengl es 需要加上float这句话)
  226. const char *fsrc =
  227. #if defined(WIN32)
  228. "#ifdef GL_ES\n"
  229. "precision mediump float;\n"
  230. "#endif\n"
  231. #else
  232. #endif
  233. "varying vec2 textureOut; \
  234. uniform sampler2D tex_y; \
  235. uniform sampler2D tex_u; \
  236. uniform sampler2D tex_v; \
  237. void main(void) \
  238. { \
  239. vec3 yuv; \
  240. vec3 rgb; \
  241. yuv.x = texture2D(tex_y, textureOut).r; \
  242. yuv.y = texture2D(tex_u, textureOut).r - 0.5; \
  243. yuv.z = texture2D(tex_v, textureOut).r - 0.5; \
  244. rgb = mat3( 1, 1, 1, \
  245. 0, -0.39465, 2.03211, \
  246. 1.13983, -0.58060, 0) * yuv; \
  247. gl_FragColor = vec4(rgb, 1); \
  248. }";
  249. //将glsl源码送入编译器编译着色器程序
  250. bCompile = m_pFSHader->compileSourceCode(fsrc);
  251. if(!bCompile)
  252. {
  253. }
  254. ///用于绘制矩形
  255. m_program = new QOpenGLShaderProgram(this);
  256. m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
  257. m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
  258. m_program->link();
  259. m_posAttr = m_program->attributeLocation("posAttr");
  260. m_colAttr = m_program->attributeLocation("colAttr");
  261. #define PROGRAM_VERTEX_ATTRIBUTE 0
  262. #define PROGRAM_TEXCOORD_ATTRIBUTE 1
  263. //创建着色器程序容器
  264. m_pShaderProgram = new QOpenGLShaderProgram;
  265. //将片段着色器添加到程序容器
  266. m_pShaderProgram->addShader(m_pFSHader);
  267. //将顶点着色器添加到程序容器
  268. m_pShaderProgram->addShader(m_pVSHader);
  269. //绑定属性vertexIn到指定位置ATTRIB_VERTEX,该属性在顶点着色源码其中有声明
  270. m_pShaderProgram->bindAttributeLocation("vertexIn", ATTRIB_VERTEX);
  271. //绑定属性textureIn到指定位置ATTRIB_TEXTURE,该属性在顶点着色源码其中有声明
  272. m_pShaderProgram->bindAttributeLocation("textureIn", ATTRIB_TEXTURE);
  273. //链接所有所有添入到的着色器程序
  274. m_pShaderProgram->link();
  275. //激活所有链接
  276. m_pShaderProgram->bind();
  277. //读取着色器中的数据变量tex_y, tex_u, tex_v的位置,这些变量的声明可以在
  278. //片段着色器源码中可以看到
  279. textureUniformY = m_pShaderProgram->uniformLocation("tex_y");
  280. textureUniformU = m_pShaderProgram->uniformLocation("tex_u");
  281. textureUniformV = m_pShaderProgram->uniformLocation("tex_v");
  282. // 顶点矩阵
  283. const GLfloat vertexVertices[] = {
  284. -1.0f, -1.0f,
  285. 1.0f, -1.0f,
  286. -1.0f, 1.0f,
  287. 1.0f, 1.0f,
  288. };
  289. memcpy(m_vertexVertices, vertexVertices, sizeof(vertexVertices));
  290. //纹理矩阵
  291. static const GLfloat textureVertices[] = {
  292. 0.0f, 1.0f,
  293. 1.0f, 1.0f,
  294. 0.0f, 0.0f,
  295. 1.0f, 0.0f,
  296. };
  297. //设置属性ATTRIB_VERTEX的顶点矩阵值以及格式
  298. glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, m_vertexVertices);
  299. //设置属性ATTRIB_TEXTURE的纹理矩阵值以及格式
  300. glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, 0, 0, textureVertices);
  301. //启用ATTRIB_VERTEX属性的数据,默认是关闭的
  302. glEnableVertexAttribArray(ATTRIB_VERTEX);
  303. //启用ATTRIB_TEXTURE属性的数据,默认是关闭的
  304. glEnableVertexAttribArray(ATTRIB_TEXTURE);
  305. //分别创建y,u,v纹理对象
  306. m_pTextureY = new QOpenGLTexture(QOpenGLTexture::Target2D);
  307. m_pTextureU = new QOpenGLTexture(QOpenGLTexture::Target2D);
  308. m_pTextureV = new QOpenGLTexture(QOpenGLTexture::Target2D);
  309. m_pTextureY->create();
  310. m_pTextureU->create();
  311. m_pTextureV->create();
  312. //获取返回y分量的纹理索引值
  313. id_y = m_pTextureY->textureId();
  314. //获取返回u分量的纹理索引值
  315. id_u = m_pTextureU->textureId();
  316. //获取返回v分量的纹理索引值
  317. id_v = m_pTextureV->textureId();
  318. glClearColor(0.0,0.0,0.0,0.0);//设置背景色-黑色
  319. //qDebug("addr=%x id_y = %d id_u=%d id_v=%d\n", this, id_y, id_u, id_v);
  320. }
  321. void ShowVideoWidget::resetGLVertex(int window_W, int window_H)
  322. {
  323. if (m_nVideoW <= 0 || m_nVideoH <= 0 || !AppConfig::gVideoKeepAspectRatio) //铺满
  324. {
  325. mPicIndex_X = 0.0;
  326. mPicIndex_Y = 0.0;
  327. // 顶点矩阵
  328. const GLfloat vertexVertices[] = {
  329. -1.0f, -1.0f,
  330. 1.0f, -1.0f,
  331. -1.0f, 1.0f,
  332. 1.0f, 1.0f,
  333. };
  334. memcpy(m_vertexVertices, vertexVertices, sizeof(vertexVertices));
  335. //纹理矩阵
  336. static const GLfloat textureVertices[] = {
  337. 0.0f, 1.0f,
  338. 1.0f, 1.0f,
  339. 0.0f, 0.0f,
  340. 1.0f, 0.0f,
  341. };
  342. //设置属性ATTRIB_VERTEX的顶点矩阵值以及格式
  343. glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, m_vertexVertices);
  344. //设置属性ATTRIB_TEXTURE的纹理矩阵值以及格式
  345. glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, 0, 0, textureVertices);
  346. //启用ATTRIB_VERTEX属性的数据,默认是关闭的
  347. glEnableVertexAttribArray(ATTRIB_VERTEX);
  348. //启用ATTRIB_TEXTURE属性的数据,默认是关闭的
  349. glEnableVertexAttribArray(ATTRIB_TEXTURE);
  350. }
  351. else //按比例
  352. {
  353. int pix_W = window_W;
  354. int pix_H = m_nVideoH * pix_W / m_nVideoW;
  355. int x = this->width() - pix_W;
  356. int y = this->height() - pix_H;
  357. x /= 2;
  358. y /= 2;
  359. if (y < 0)
  360. {
  361. pix_H = window_H;
  362. pix_W = m_nVideoW * pix_H / m_nVideoH;
  363. x = this->width() - pix_W;
  364. y = this->height() - pix_H;
  365. x /= 2;
  366. y /= 2;
  367. }
  368. mPicIndex_X = x * 1.0 / window_W;
  369. mPicIndex_Y = y * 1.0 / window_H;
  370. //qDebug()<<window_W<<window_H<<pix_W<<pix_H<<x<<y;
  371. float index_y = y *1.0 / window_H * 2.0 -1.0;
  372. float index_y_1 = index_y * -1.0;
  373. float index_y_2 = index_y;
  374. float index_x = x *1.0 / window_W * 2.0 -1.0;
  375. float index_x_1 = index_x * -1.0;
  376. float index_x_2 = index_x;
  377. const GLfloat vertexVertices[] = {
  378. index_x_2, index_y_2,
  379. index_x_1, index_y_2,
  380. index_x_2, index_y_1,
  381. index_x_1, index_y_1,
  382. };
  383. memcpy(m_vertexVertices, vertexVertices, sizeof(vertexVertices));
  384. #if TEXTURE_HALF
  385. static const GLfloat textureVertices[] = {
  386. 0.0f, 1.0f,
  387. 0.5f, 1.0f,
  388. 0.0f, 0.0f,
  389. 0.5f, 0.0f,
  390. };
  391. #else
  392. static const GLfloat textureVertices[] = {
  393. 0.0f, 1.0f,
  394. 1.0f, 1.0f,
  395. 0.0f, 0.0f,
  396. 1.0f, 0.0f,
  397. };
  398. #endif
  399. //设置属性ATTRIB_VERTEX的顶点矩阵值以及格式
  400. glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, m_vertexVertices);
  401. //设置属性ATTRIB_TEXTURE的纹理矩阵值以及格式
  402. glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, 0, 0, textureVertices);
  403. //启用ATTRIB_VERTEX属性的数据,默认是关闭的
  404. glEnableVertexAttribArray(ATTRIB_VERTEX);
  405. //启用ATTRIB_TEXTURE属性的数据,默认是关闭的
  406. glEnableVertexAttribArray(ATTRIB_TEXTURE);
  407. }
  408. }
  409. void ShowVideoWidget::resizeGL(int window_W, int window_H)
  410. {
  411. mLastGetFrameTime = QDateTime::currentMSecsSinceEpoch();
  412. // qDebug()<<__FUNCTION__<<m_pBufYuv420p<<window_W<<window_H;
  413. if(window_H == 0)// 防止被零除
  414. {
  415. window_H = 1;// 将高设为1
  416. }
  417. //设置视口
  418. glViewport(0, 0, window_W, window_H);
  419. int x = window_W - ui->pushButton_close->width() - 22;
  420. int y = 22;
  421. ui->pushButton_close->move(x, y);
  422. x = 0;
  423. y = window_H / 2 - ui->widget_erro->height() / 2;
  424. ui->widget_erro->move(x, y);
  425. ui->widget_erro->resize(window_W, ui->widget_erro->height());
  426. x = 0;
  427. y = window_H - ui->widget_name->height() - 6;
  428. ui->widget_name->move(x, y);
  429. ui->widget_name->resize(window_W, ui->widget_name->height());
  430. resetGLVertex(window_W, window_H);
  431. }
  432. void ShowVideoWidget::paintGL()
  433. {
  434. // qDebug()<<__FUNCTION__<<mCameraName<<m_pBufYuv420p;
  435. mLastGetFrameTime = QDateTime::currentMSecsSinceEpoch();
  436. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  437. if (ui->pushButton_close->isVisible())
  438. if (!mIsPlaying || !mIsCloseAble)
  439. {
  440. ui->pushButton_close->hide();
  441. }
  442. if (!mCameraName.isEmpty() && mIsPlaying)
  443. {
  444. ui->widget_name->show();
  445. QFontMetrics fontMetrics(ui->label_name->font());
  446. int fontSize = fontMetrics.width(mCameraName);//获取之前设置的字符串的像素大小
  447. QString str = mCameraName;
  448. if(fontSize > (this->width() / 2))
  449. {
  450. str = fontMetrics.elidedText(mCameraName, Qt::ElideRight, (this->width() / 2));//返回一个带有省略号的字符串
  451. }
  452. ui->label_name->setText(str);
  453. ui->label_name->setToolTip(mCameraName);
  454. }
  455. else
  456. {
  457. ui->widget_name->hide();
  458. }
  459. if (mIsPlaying && mPlayFailed)
  460. {
  461. ui->widget_erro->show();
  462. }
  463. else
  464. {
  465. ui->widget_erro->hide();
  466. }
  467. ///设置中按比例发生改变 则需要重置x y偏量
  468. if (mCurrentVideoKeepAspectRatio != AppConfig::gVideoKeepAspectRatio)
  469. {
  470. mCurrentVideoKeepAspectRatio = AppConfig::gVideoKeepAspectRatio;
  471. resetGLVertex(this->width(), this->height());
  472. }
  473. ///绘制矩形框
  474. if (mIsShowFaceRect && !mFaceInfoList.isEmpty())
  475. {
  476. m_program->bind();
  477. glEnableVertexAttribArray(0);
  478. glEnableVertexAttribArray(1);
  479. for (int i = 0; i < mFaceInfoList.size(); i++)
  480. {
  481. FaceInfoNode faceNode = mFaceInfoList.at(i);
  482. QRect rect = faceNode.faceRect;
  483. int window_W = this->width();
  484. int window_H = this->height();
  485. int pix_W = rect.width();
  486. int pix_H = rect.height();
  487. int x = rect.x();
  488. int y = rect.y();
  489. float index_x_1 = x *1.0 / m_nVideoW * 2.0 -1.0;
  490. float index_y_1 = 1.0 - (y *1.0 / m_nVideoH * 2.0);
  491. float index_x_2 = (x + pix_W) * 1.0 / m_nVideoW * 2.0 - 1.0;
  492. float index_y_2 = index_y_1;
  493. float index_x_3 = index_x_2;
  494. float index_y_3 = 1.0 - ((y + pix_H) * 1.0 / m_nVideoH * 2.0);
  495. float index_x_4 = index_x_1;
  496. float index_y_4 = index_y_3;
  497. index_x_1 += mPicIndex_X;
  498. index_x_2 += mPicIndex_X;
  499. index_x_3 += mPicIndex_X;
  500. index_x_4 += mPicIndex_X;
  501. index_y_1 -= mPicIndex_Y;
  502. index_y_2 -= mPicIndex_Y;
  503. index_y_3 -= mPicIndex_Y;
  504. index_y_4 -= mPicIndex_Y;
  505. const GLfloat vertices[] = {
  506. index_x_1, index_y_1,
  507. index_x_2, index_y_2,
  508. index_x_3, index_y_3,
  509. index_x_4, index_y_4,
  510. };
  511. // #7AC451 - 122, 196, 81 - 0.47843f, 0.768627f, 0.317647f
  512. const GLfloat colors[] = {
  513. 0.47843f, 0.768627f, 0.317647f,
  514. 0.47843f, 0.768627f, 0.317647f,
  515. 0.47843f, 0.768627f, 0.317647f,
  516. 0.47843f, 0.768627f, 0.317647f
  517. };
  518. glVertexAttribPointer(m_posAttr, 2, GL_FLOAT, GL_FALSE, 0, vertices);
  519. glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, colors);
  520. glLineWidth(2.2f); //设置画笔宽度
  521. glDrawArrays(GL_LINE_LOOP, 0, 4);
  522. }
  523. glDisableVertexAttribArray(1);
  524. glDisableVertexAttribArray(0);
  525. m_program->release();
  526. }
  527. VideoFrame * videoFrame = mVideoFrame.get();
  528. if (videoFrame != nullptr)
  529. {
  530. uint8_t *m_pBufYuv420p = videoFrame->buffer();
  531. if (m_pBufYuv420p != NULL)
  532. {
  533. m_pShaderProgram->bind();
  534. //加载y数据纹理
  535. //激活纹理单元GL_TEXTURE0
  536. glActiveTexture(GL_TEXTURE0);
  537. //使用来自y数据生成纹理
  538. glBindTexture(GL_TEXTURE_2D, id_y);
  539. //使用内存中m_pBufYuv420p数据创建真正的y数据纹理
  540. glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_nVideoW, m_nVideoH, 0, GL_RED, GL_UNSIGNED_BYTE, m_pBufYuv420p);
  541. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  542. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  543. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  544. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  545. //加载u数据纹理
  546. glActiveTexture(GL_TEXTURE1);//激活纹理单元GL_TEXTURE1
  547. glBindTexture(GL_TEXTURE_2D, id_u);
  548. glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_nVideoW/2, m_nVideoH/2, 0, GL_RED, GL_UNSIGNED_BYTE, (char*)m_pBufYuv420p+m_nVideoW*m_nVideoH);
  549. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  550. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  551. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  552. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  553. //加载v数据纹理
  554. glActiveTexture(GL_TEXTURE2);//激活纹理单元GL_TEXTURE2
  555. glBindTexture(GL_TEXTURE_2D, id_v);
  556. glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_nVideoW/2, m_nVideoH/2, 0, GL_RED, GL_UNSIGNED_BYTE, (char*)m_pBufYuv420p+m_nVideoW*m_nVideoH*5/4);
  557. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  558. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  559. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  560. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  561. //指定y纹理要使用新值 只能用0,1,2等表示纹理单元的索引,这是opengl不人性化的地方
  562. //0对应纹理单元GL_TEXTURE0 1对应纹理单元GL_TEXTURE1 2对应纹理的单元
  563. glUniform1i(textureUniformY, 0);
  564. //指定u纹理要使用新值
  565. glUniform1i(textureUniformU, 1);
  566. //指定v纹理要使用新值
  567. glUniform1i(textureUniformV, 2);
  568. //使用顶点数组方式绘制图形
  569. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  570. m_pShaderProgram->release();
  571. }
  572. }
  573. }