网页设计新手制作的网站代码mip网站怎么做匹配
web/
2025/9/30 14:46:35/
文章来源:
网页设计新手制作的网站代码,mip网站怎么做匹配,公司网站如何做,站群系统开发在前面的文章中#xff0c;我们使用libvlc_media_player_set_hwnd设置了视频的显示的窗口。
libvlc_media_player_set_hwnd(vlc_mediaPlayer, (void *)ui.widgetShow-winId());
如果我们想要提取每一帧数据#xff0c;将数据渲染到QWidget上#xff0c;该如何操作呢我们使用libvlc_media_player_set_hwnd设置了视频的显示的窗口。
libvlc_media_player_set_hwnd(vlc_mediaPlayer, (void *)ui.widgetShow-winId());
如果我们想要提取每一帧数据将数据渲染到QWidget上该如何操作呢
以下是操作流程
1.初始化 libVLC 实例。
vlc_base libvlc_new(0, NULL);
2.创建一个媒体播放器。 vlc_media libvlc_media_new_path(vlc_base, filename.toUtf8().data());if (!vlc_media) {return;}// 创建libvlc实例和媒体播放器vlc_mediaPlayer libvlc_media_player_new_from_media(vlc_media);if (!vlc_mediaPlayer) {return;}
3.设置视频回调。 libvlc_video_set_format_callbacks(vlc_mediaPlayer, setup, NULL);// 设置自定义视频输出libvlc_video_set_callbacks(vlc_mediaPlayer, lock, unlock, display, NULL);
4.提取视频帧数据创建QImage对象。
//保存100~110帧
static void unlock(void *opaque, void *picture, void *const *planes) {// 这里可以释放视频帧的锁char *buffer (char *)*planes; //planes即为帧数据QImage image((unsigned char*)buffer, g_frame-width, g_frame-height, QImage::Format_ARGB32);m_this-updatePic(image);g_frame-mutex.unlock();
}
5.使用QLabel加载QImage对象或者使用QWidget的绘图事件绘制QImage在QWidget上。
这里使用QLabel加载。
void showWidget::slotUpdate(const QImage image)
{ui.lbImage-setPixmap(QPixmap::fromImage(image));
}
这里介绍libvlc_video_set_callbacks的lock和unlock两个回调。更多的回调介绍请看
libVLC 提取视频帧-CSDN博客
以下是libvlc_video_lock_cb声明。
typedef void *(*libvlc_video_lock_cb)(void *opaque, void **planes);
opaque是一个用户数据指针libvlc_video_set_callbacks最后一个参数会传递给lock。planes是一个指向指针的指针它指向一个指针数组每个指针指向一个视频平面对于 YUV 格式通常有三个平面Y、U 和 V。对于 RGB 格式通常只有一个平面。返回值传递给unlock的参数2。
如果应用程序需要在视频渲染前对视频帧进行一些处理那么可以在libvlc_video_lock_cb中进行这些处理并将处理后的帧数据地址赋值给 *planes。
以下是libvlc_video_unlock_cb声明。
typedef void (*libvlc_video_unlock_cb)(void *opaque, void *picture,void *const *planes);
opaque是一个用户数据指针libvlc_video_set_callbacks最后一个参数会传递给lock。picture是libvlc_video_lock_cb返回值。planes是平面像素数据。
以下是ui界面设计。 运行结果 代码示例
#pragma once#include QtWidgets/QWidget
#include ui_showWidget.h
#include QMenu
#include QActionGroup
#include vlc/vlc.h
#include QDebug
#include QFileDialog
#include QThread
#include QMouseEvent
#include QKeyEventenum Rate
{Rate2X,Rate1_5X,Rate1_25X,Rate1_0X,Rate0_75X,Rate0_5X
};class showWidget : public QWidget
{Q_OBJECTpublic:showWidget(QWidget *parent nullptr);~showWidget();public:void updatePic(const QImage image);private slots:void slotOpenFile();void slotPlay();void slotPause();void slotStop();void slotValueChanged(int value);void slotCurrentIndexChanged(int index);private://事件处理回调static void vlcEvents(const libvlc_event_t *ev, void *param);private:Ui::showWidgetClass ui;private:libvlc_instance_t *vlc_base nullptr;libvlc_media_t *vlc_media nullptr;libvlc_media_player_t *vlc_mediaPlayer nullptr;QListfloat m_lstRate;QListQString m_lstAudioDevice;
};这里使用声明了static showWidget* m_this nullptr。在构造函数中使用m_this this赋值。在unlock回调中构造好QImage对象使用m_this-updatePic(image)更新界面。
cpp源码。
#include showWidget.h
#include QTimer
#include QTime
#include QMutex
#include stdlib.h #pragma execution_character_set(utf-8)static showWidget* m_this nullptr;struct Frame
{int width;int height;uchar * pixels;QMutex mutex;
};static Frame *g_frame nullptr;// 自定义视频输出模块的回调函数
static void *lock(void *opaque, void **planes) {g_frame-mutex.lock();*planes g_frame-pixels;return 0;
}//保存100~110帧
static void unlock(void *opaque, void *picture, void *const *planes) {// 这里可以释放视频帧的锁char *buffer (char *)*planes; //planes即为帧数据QImage image((unsigned char*)buffer, g_frame-width, g_frame-height, QImage::Format_ARGB32);m_this-updatePic(image);g_frame-mutex.unlock();
}static void display(void *opaque, void *picture) {// 这里可以进行视频帧的显示或其他处理(void)opaque;
}static unsigned setup(void **opaque, char *chroma,unsigned *width, unsigned *height,unsigned *pitches,unsigned *lines)
{qDebug() chroma: QString(chroma) width: *width , height: *height;/* 开辟存放图像数据的内存块 */if (g_frame){if (g_frame-pixels){delete[] g_frame-pixels;g_frame-pixels NULL;}delete g_frame;g_frame NULL;}int w *width;int h *height;g_frame new Frame;g_frame-pixels new uchar[w * h * 4]; // 申请大小也为4通道的像素memset(g_frame-pixels, 0, w * h * 4);memcpy(chroma, RV32, 4);g_frame-width w;g_frame-height h;*pitches w * 4;*lines h;return 1;
}showWidget::showWidget(QWidget *parent): QWidget(parent)
{ui.setupUi(this);m_this this;this-setWindowTitle(视频播放器);vlc_base libvlc_new(0, NULL);ui.cbxRate-setCurrentIndex(Rate1_0X);m_lstRate 2.0 1.5 1.25 1.0 0.75 0.5;ui.btnOpen-setFocusPolicy(Qt::NoFocus);ui.btnPlay-setFocusPolicy(Qt::NoFocus);ui.btnPause-setFocusPolicy(Qt::NoFocus);ui.btnStop-setFocusPolicy(Qt::NoFocus);ui.hSliderVolumn-setFocusPolicy(Qt::NoFocus);ui.cbxRate-setFocusPolicy(Qt::NoFocus);connect(ui.btnOpen, QPushButton::clicked, this, showWidget::slotOpenFile);connect(ui.btnPlay, QPushButton::clicked, this, showWidget::slotPlay);connect(ui.btnPause, QPushButton::clicked, this, showWidget::slotPause);connect(ui.btnStop, QPushButton::clicked, this, showWidget::slotStop);connect(ui.hSliderVolumn, QSlider::valueChanged, this, showWidget::slotValueChanged);connect(ui.cbxRate,SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentIndexChanged(int)));
}showWidget::~showWidget()
{libvlc_release(vlc_base); //减少libvlc实例的引用计数并销毁
}void showWidget::updatePic(const QImage image)
{ui.lbImage-setPixmap(QPixmap::fromImage(image));
}void showWidget::slotOpenFile()
{/*选择文件*/QString filename QFileDialog::getOpenFileName(this, 选择打开的文件, D:/, tr(*.*));std::replace(filename.begin(), filename.end(), QChar(/), QChar(\\));vlc_media libvlc_media_new_path(vlc_base, filename.toUtf8().data());if (!vlc_media) {return;}// 创建libvlc实例和媒体播放器vlc_mediaPlayer libvlc_media_player_new_from_media(vlc_media);if (!vlc_mediaPlayer) {return;}libvlc_video_set_format_callbacks(vlc_mediaPlayer, setup, NULL);// 设置自定义视频输出libvlc_video_set_callbacks(vlc_mediaPlayer, lock, unlock, display, NULL);// 等待元数据加载完成libvlc_media_parse(vlc_media);// 获取各种元数据const char *title libvlc_media_get_meta(vlc_media, libvlc_meta_Title);const char *artist libvlc_media_get_meta(vlc_media, libvlc_meta_Artist);const char *album libvlc_media_get_meta(vlc_media, libvlc_meta_Album);const char *url libvlc_media_get_meta(vlc_media, libvlc_meta_URL);const char *date libvlc_media_get_meta(vlc_media, libvlc_meta_Date);const char *lang libvlc_media_get_meta(vlc_media, libvlc_meta_Language);int duration libvlc_media_get_duration(vlc_media); // 获取时长单位毫秒qDebug(Title: %s, title ? title : N/A);qDebug(Artist: %s, artist ? artist : N/A);qDebug(Album: %s, album ? album : N/A);qDebug(Duration: %d ms, duration);qDebug(url: %s, url ? url : N/A);qDebug(date: %s, date ? date : N/A);qDebug(lang: %s, lang ? lang : N/A);libvlc_media_track_t **tracks;int track_count libvlc_media_tracks_get(vlc_media,tracks);for (unsigned i 0; i track_count; i) {libvlc_media_track_t* track tracks[i];// 显示轨道信息printf(Track #%u: %s\n, i, track-psz_description);// 这里可以获取到每一个轨道的信息比如轨道类型 track-i_type// 可能是 libvlc_track_video, libvlc_track_audio 或者 libvlc_track_text (字幕)if (track-i_type libvlc_track_video) {// 处理视频轨道信息qDebug(width %d,track-video-i_width);qDebug(height %d, track-video-i_height);qDebug(rate_num %d, track-video-i_frame_rate_num);qDebug(rate_den %d, track-video-i_frame_rate_den);}else if (track-i_type libvlc_track_audio) {// 处理音频轨道信息qDebug(channels %d, track-audio-i_channels);qDebug(rate %d, track-audio-i_rate);}else if (track-i_type libvlc_track_text) {// 处理字幕轨道信息}}//获取事件管理器libvlc_event_manager_t *em libvlc_media_player_event_manager(vlc_mediaPlayer);// 注册事件监听器libvlc_event_attach(em, libvlc_MediaPlayerTimeChanged, vlcEvents, this);libvlc_event_attach(em, libvlc_MediaPlayerEndReached, vlcEvents, this);libvlc_event_attach(em, libvlc_MediaPlayerStopped, vlcEvents, this);libvlc_event_attach(em, libvlc_MediaPlayerPlaying, vlcEvents, this);libvlc_event_attach(em, libvlc_MediaPlayerPaused, vlcEvents, this);QTimer::singleShot(1000, this, showWidget::slotPlay);libvlc_video_filter_list_get(vlc_base);
}void showWidget::slotPlay()
{if (vlc_mediaPlayer){libvlc_media_player_play(vlc_mediaPlayer);}
}void showWidget::slotPause()
{if (vlc_mediaPlayer)libvlc_media_player_pause(vlc_mediaPlayer);
}void showWidget::slotStop()
{if (vlc_mediaPlayer)libvlc_media_player_stop(vlc_mediaPlayer);
}void showWidget::slotValueChanged(int value)
{if (vlc_mediaPlayer)libvlc_audio_set_volume(vlc_mediaPlayer, value);
}void showWidget::slotCurrentIndexChanged(int index)
{if (vlc_mediaPlayer)libvlc_media_player_set_rate(vlc_mediaPlayer, m_lstRate[index]);
}//事件回调
void showWidget::vlcEvents(const libvlc_event_t *ev, void *param)
{showWidget *w (showWidget*)param;//处理不同的事件switch (ev-type) {case libvlc_MediaPlayerTimeChanged:{//qDebug() VLC媒体播放器时间已更改;qint64 len libvlc_media_player_get_time(w-vlc_mediaPlayer);libvlc_time_t lenSec len / 1000;libvlc_time_t totalLen libvlc_media_player_get_length(w-vlc_mediaPlayer);libvlc_time_t totalLenSec totalLen / 1000;int thh, tmm, tss;thh lenSec / 3600;tmm (lenSec % 3600) / 60;tss (lenSec % 60);QTime time(thh, tmm, tss);w-ui.lbCurTime-setText(time.toString(hh:mm:ss));thh totalLenSec / 3600;tmm (totalLenSec % 3600) / 60;tss (totalLenSec % 60);QTime TotalTime(thh, tmm, tss);w-ui.lbTotalTime-setText(TotalTime.toString(hh:mm:ss));double pos (double)lenSec / totalLenSec * 100;w-ui.horizontalSlider-setValue(pos);}break;case libvlc_MediaPlayerEndReached:qDebug() VLC播放完毕.;break;case libvlc_MediaPlayerStopped:qDebug() VLC停止播放;break;case libvlc_MediaPlayerPlaying:qDebug() VLC开始播放;break;case libvlc_MediaPlayerPaused:qDebug() VLC暂停播放;break;}
}
经过上面的步骤我们已经完成了整个视频的渲染我们不停的生成的是 QImage 对象因此对 CPU 负荷较高。其实在绘制这块我们可以使用 Opencv 或者 openGL 去绘制利用 GPU 减轻 CPU 计算负荷。下一节使用openGL进行绘制减轻CPU的压力。
更多参考
libVLC 添加图片和文本水印-CSDN博客
libVLC 音频输出设备切换-CSDN博客
libVLC 音频立体声模式切换-CSDN博客
libVLC 提取视频帧-CSDN博客
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/84507.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!