赞
踩
Windows操作系统提供了多种便捷的截图方式,常见的有以下几种:
libVLC 中通过libvlc_video_take_snapshot核心接口来截图。
以下是如何使用 libVLC 设置视频裁剪区域的基本步骤:
1. 初始化 libVLC 和媒体播放器
首先,你需要初始化 libVLC 实例和媒体播放器对象。
- #include <vlc/vlc.h>
-
- int main(int argc, char* argv[])
- {
- libvlc_instance_t* inst;
- libvlc_media_player_t* mp;
- libvlc_media_t* m;
-
- // 加载 libVLC 引擎
- inst = libvlc_new(0, NULL);
-
- // 创建一个新的 item
- m = libvlc_media_new_location(inst, "your_video_path_here");
- mp = libvlc_media_player_new_from_media(m);
-
- // 不再需要媒体对象
- libvlc_media_release(m);
- }
2. 播放视频
- // 播放媒体播放器
- libvlc_media_player_play(mp);
-
- // 保持程序运行,直到视频播放完成
- while (libvlc_media_player_is_playing(mp)) {
- // 可以在这里加入延时
- }
-
- // 清理 libVLC
- libvlc_media_player_stop(mp);
- libvlc_media_player_release(mp);
- libvlc_release(inst);
-
- return 0;
3.截图
这里为了方便,路径写死了。
- if (vlc_mediaPlayer)
- {
- QString path = "./snap.png";
- libvlc_video_take_snapshot(vlc_mediaPlayer, 0, path.toUtf8().data(), 0, 0);
- }
以下是VLC播放器中使用的截图界面,我们仿照这个做一个界面。
以下是效果图。
菜单添加action,并响应槽函数。
- m_snapAction = m_videoMenu->addAction("截图");
- connect(m_snapAction, &QAction::triggered, this, &showWidget::slotSnap);
槽函数如下图所示,为了方便,路径写死了。
- void showWidget::slotSnap()
- {
- if (vlc_mediaPlayer)
- {
- QString path = "./snap.png";
- libvlc_video_take_snapshot(vlc_mediaPlayer, 0, path.toUtf8().data(), 0, 0);
- }
- }
生成目录下snap.png。
完整源码:
- #pragma once
- #define LIBVLC_USE_PTHREAD_CANCEL 1
- #include <QtWidgets/QWidget>
- #include "ui_showWidget.h"
- #include <QMenu>
- #include <QActionGroup>
- #include <vlc/vlc.h>
-
- #include <QDebug>
- #include <QFileDialog>
- #include <QThread>
- #include <QMouseEvent>
- #include <QKeyEvent>
-
- enum Rate
- {
- Rate2X,
- Rate1_5X,
- Rate1_25X,
- Rate1_0X,
- Rate0_75X,
- Rate0_5X
- };
-
- class showWidget : public QWidget
- {
- Q_OBJECT
-
- public:
- showWidget(QWidget *parent = nullptr);
- ~showWidget();
-
- protected:
- virtual void mousePressEvent(QMouseEvent *event);
- virtual void mouseDoubleClickEvent(QMouseEvent *event);
- virtual void keyPressEvent(QKeyEvent *event);
-
- private slots:
- void slotOpenFile();
- void slotPlay();
- void slotPause();
- void slotStop();
- void slotValueChanged(int value);
- void slotCurrentIndexChanged(int index);
- void slotActionTriggered(QAction *action);
- void slotCropActionTriggered(QAction *action);
- void slotScaleActionTriggered(QAction *action);
-
- void slotSnap();
-
- private:
- //事件处理回调
- static void vlcEvents(const libvlc_event_t *ev, void *param);
-
- //初始化menu
- void initMenu();
-
- private:
- Ui::showWidgetClass ui;
-
- private:
- libvlc_instance_t *vlc_base = nullptr;
- libvlc_media_t *vlc_media = nullptr;
- libvlc_media_player_t *vlc_mediaPlayer = nullptr;
-
- QList<float> m_lstRate;
-
- QMenu *m_menu = nullptr;
- QAction *m_video = nullptr;
-
- QAction *m_scaleAction = nullptr; //缩放
- QAction *m_aspectRatioAction = nullptr; //宽高比
- QAction *m_cropAction = nullptr; //裁剪
- QAction *m_snapAction = nullptr;//截图
-
- QMenu *m_videoMenu = nullptr;
-
- //宽高比
- QMenu *m_aspectRatioMenu = nullptr;
- QAction *m_default = nullptr;
- QAction *m_16_9 = nullptr;
- QAction *m_4_3 = nullptr;
- QAction *m_1_1 = nullptr;
- QAction *m_16_10 = nullptr;
- QAction *m_2_21_1 = nullptr;
- QAction *m_2_35_1= nullptr;
- QAction *m_2_38_1 = nullptr;
- QAction *m_5_4 = nullptr;
-
- QActionGroup *m_group = nullptr;
- QAction *m_preAspectRatio = nullptr;
- //宽高比
- //裁剪
- QMenu *m_cropMenu = nullptr;
- QAction *m__cropDefault = nullptr;
- QAction *m__crop16_10 = nullptr;
- QAction *m__crop16_9 = nullptr;
- QAction *m__crop4_3 = nullptr;
- QAction *m__crop1_85_1 = nullptr;
- QAction *m__crop2_21_1 = nullptr;
- QAction *m__crop2_35_1 = nullptr;
- QAction *m__crop2_39_1 = nullptr;
- QAction *m__crop5_3 = nullptr;
- QAction *m__crop5_4 = nullptr;
- QAction *m__crop1_1 = nullptr;
-
- QActionGroup *m_cropGroup = nullptr;
- QAction *m_preCrop= nullptr;
- //裁剪
-
- //缩放
- QMenu *m_scaleMenu = nullptr;
- QAction *m_scale1_4 = nullptr;
- QAction *m_scale1_2 = nullptr;
- QAction *m_scale1_1 = nullptr;
- QAction *m_scale2_1 = nullptr;
-
- QActionGroup *m_scaleGroup = nullptr;
- QAction *m_preScale = nullptr;
- //缩放
-
- char *m_defalutRate = nullptr;
- char *m_defalutCrop = nullptr;
- float m_defalutScale = 0;
- };
cpp
- #include "showWidget.h"
- #include <QTimer>
- #include <QTime>
-
- #pragma execution_character_set("utf-8")
-
- showWidget::showWidget(QWidget *parent)
- : QWidget(parent)
- {
- ui.setupUi(this);
-
- this->setWindowTitle("视频播放器");
-
- ui.cbxRate->setCurrentIndex(Rate1_0X);
-
- m_lstRate << 2.0 << 1.5 << 1.25 << 1.0 << 0.75 << 0.5;
-
- initMenu();
-
- 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.btnSnap, &QPushButton::clicked, this, &showWidget::slotSnap);
- 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::mousePressEvent(QMouseEvent *event)
- {
- switch (event->button())
- {
- case Qt::RightButton:
- //this->setWindowState(Qt::WindowMinimized);
- m_menu->exec(event->globalPos());
- break;
- default:
- QWidget::mousePressEvent(event);
- }
- }
-
- void showWidget::mouseDoubleClickEvent(QMouseEvent *event)
- {
- if (this->isFullScreen())
- {
- this->showNormal();
- }
- else
- {
- this->showFullScreen();
- }
- }
-
- void showWidget::keyPressEvent(QKeyEvent *event)
- {
- if (!vlc_mediaPlayer)
- return;
-
- int value = ui.hSliderVolumn->value();
- if (event->key() == Qt::Key_W) //添加音量
- {
- qDebug() << "up";
- slotValueChanged(value+10);
- }
- else if (event->key() == Qt::Key_S) //减小音量
- {
- slotValueChanged(value - 10);
- }
- else if (event->key() == Qt::Key_Space)
- {
- if (vlc_mediaPlayer && libvlc_media_player_get_state(vlc_mediaPlayer) == libvlc_Playing)
- {
- libvlc_media_player_pause(vlc_mediaPlayer);
- }
- else if (vlc_mediaPlayer && libvlc_media_player_get_state(vlc_mediaPlayer) == libvlc_Paused)
- {
- libvlc_media_player_play(vlc_mediaPlayer);
- }
- }
- }
-
- void showWidget::slotOpenFile()
- {
- /*选择文件*/
- QString filename = QFileDialog::getOpenFileName(this, "选择打开的文件", "D:/", tr("*.*"));
- std::replace(filename.begin(), filename.end(), QChar('/'), QChar('\\'));
- vlc_base = libvlc_new(0, NULL);
- 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_media_parse(vlc_media);
-
- m_defalutRate = libvlc_video_get_aspect_ratio(vlc_mediaPlayer);
- m_defalutCrop = libvlc_video_get_crop_geometry(vlc_mediaPlayer);
-
- libvlc_video_set_mouse_input(vlc_mediaPlayer, 0);
- libvlc_video_set_key_input(vlc_mediaPlayer, 0);
-
- // 获取各种元数据
- 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);
-
- libvlc_media_player_set_hwnd(vlc_mediaPlayer, (void *)ui.widgetShow->winId());
-
- QTimer::singleShot(1000, this, &showWidget::slotPlay);
-
- }
-
- void showWidget::slotPlay()
- {
- if (vlc_mediaPlayer)
- {
- libvlc_media_player_play(vlc_mediaPlayer);
- m_defalutScale = libvlc_video_get_scale(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::slotActionTriggered(QAction *action)
- {
- if (!vlc_mediaPlayer)
- return;
-
- if (action == m_default)
- libvlc_video_set_aspect_ratio(vlc_mediaPlayer,m_defalutRate);
- else if(action == m_16_9)
- libvlc_video_set_aspect_ratio(vlc_mediaPlayer, "16:9");
- else if (action == m_4_3)
- libvlc_video_set_aspect_ratio(vlc_mediaPlayer, "4:3");
- else if (action == m_1_1)
- libvlc_video_set_aspect_ratio(vlc_mediaPlayer, "1:1");
- else if (action == m_16_10)
- libvlc_video_set_aspect_ratio(vlc_mediaPlayer, "16:10");
- else if (action == m_2_21_1)
- libvlc_video_set_aspect_ratio(vlc_mediaPlayer, "221:100");
- else if (action == m_2_35_1)
- libvlc_video_set_aspect_ratio(vlc_mediaPlayer, "235:100");
- else if (action == m_2_38_1)
- libvlc_video_set_aspect_ratio(vlc_mediaPlayer, "238:100");
- else if (action == m_5_4)
- libvlc_video_set_aspect_ratio(vlc_mediaPlayer, "5:4");
-
- action->setIcon(QIcon(":/image/images/point.png"));
- m_preAspectRatio->setIcon(QIcon());
- m_preAspectRatio = action;
- }
-
- void showWidget::slotCropActionTriggered(QAction *action)
- {
- if (!vlc_mediaPlayer)
- return;
-
- if (action == m__cropDefault)
- libvlc_video_set_crop_geometry(vlc_mediaPlayer, m_defalutCrop);
- else if (action == m__crop16_10)
- libvlc_video_set_crop_geometry(vlc_mediaPlayer, "16:10");
- else if (action == m__crop16_9)
- libvlc_video_set_crop_geometry(vlc_mediaPlayer, "16:9");
- else if (action == m__crop4_3)
- libvlc_video_set_crop_geometry(vlc_mediaPlayer, "4:3");
- else if (action == m__crop1_85_1)
- libvlc_video_set_crop_geometry(vlc_mediaPlayer, "185:100");
- else if (action == m__crop2_21_1)
- libvlc_video_set_crop_geometry(vlc_mediaPlayer, "221:100");
- else if (action == m__crop2_35_1)
- libvlc_video_set_crop_geometry(vlc_mediaPlayer, "235:100");
- else if (action == m__crop2_39_1)
- libvlc_video_set_crop_geometry(vlc_mediaPlayer, "239:100");
- else if (action == m__crop5_3)
- libvlc_video_set_crop_geometry(vlc_mediaPlayer, "5:3");
- else if (action == m__crop5_4)
- libvlc_video_set_crop_geometry(vlc_mediaPlayer, "5:4");
- else if (action == m__crop1_1)
- libvlc_video_set_crop_geometry(vlc_mediaPlayer, "1:1");
-
- action->setIcon(QIcon(":/image/images/point.png"));
- m_preCrop->setIcon(QIcon());
- m_preCrop = action;
- }
-
- void showWidget::slotScaleActionTriggered(QAction *action)
- {
- if (!vlc_mediaPlayer)
- return;
-
- if (action == m_scale1_4)
- libvlc_video_set_scale(vlc_mediaPlayer, 0.25);
- else if (action == m_scale1_2)
- libvlc_video_set_scale(vlc_mediaPlayer, 0.5);
- else if (action == m_scale1_1)
- libvlc_video_set_scale(vlc_mediaPlayer, 1);
- else if (action == m_scale2_1)
- libvlc_video_set_scale(vlc_mediaPlayer, 2);
-
- action->setIcon(QIcon(":/image/images/point.png"));
- m_preScale->setIcon(QIcon());
- m_preScale = action;
- }
-
- void showWidget::slotSnap()
- {
- if (vlc_mediaPlayer)
- {
- QString path = "./snap.png";
- libvlc_video_take_snapshot(vlc_mediaPlayer, 0, path.toUtf8().data(), 0, 0);
- }
- }
-
- //事件回调
- 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;
- }
- }
-
- void showWidget::initMenu()
- {
- //总菜单
- m_menu = new QMenu(this);
- m_video = m_menu->addAction("视频");
-
- //视频菜单
- m_videoMenu = new QMenu(this);
- m_scaleAction = m_videoMenu->addAction("缩放");
- m_aspectRatioAction = m_videoMenu->addAction("宽高比");
- m_cropAction = m_videoMenu->addAction("裁剪");
- m_snapAction = m_videoMenu->addAction("截图");
- connect(m_snapAction, &QAction::triggered, this, &showWidget::slotSnap);
-
- m_video->setMenu(m_videoMenu);
-
- //宽高比菜单
- m_aspectRatioMenu = new QMenu(this);
- m_aspectRatioAction->setMenu(m_aspectRatioMenu);
-
- //设置宽高比菜单
- m_default = m_aspectRatioMenu->addAction(QIcon(":/image/images/point.png"), "默认");
- m_16_9 = m_aspectRatioMenu->addAction("16:9");
- m_4_3 = m_aspectRatioMenu->addAction("4:3");
- m_1_1 = m_aspectRatioMenu->addAction("1:1");
- m_16_10 = m_aspectRatioMenu->addAction("16:10");
- m_2_21_1 = m_aspectRatioMenu->addAction("2.21:1");
- m_2_35_1 = m_aspectRatioMenu->addAction("2.35:1");
- m_2_38_1 = m_aspectRatioMenu->addAction("2.38:1");
- m_5_4 = m_aspectRatioMenu->addAction("5:4");
-
- m_preAspectRatio = m_default;
-
- m_group = new QActionGroup(this);
- m_group->addAction(m_default);
- m_group->addAction(m_16_9);
- m_group->addAction(m_4_3);
- m_group->addAction(m_1_1);
- m_group->addAction(m_16_10);
- m_group->addAction(m_2_21_1);
- m_group->addAction(m_2_35_1);
- m_group->addAction(m_2_38_1);
- m_group->addAction(m_5_4);
-
- connect(m_group, &QActionGroup::triggered, this, &showWidget::slotActionTriggered);
-
- //设置裁剪菜单
- m_cropMenu = new QMenu(this);
- m_cropAction->setMenu(m_cropMenu);
-
- m__cropDefault = m_cropMenu->addAction(QIcon(":/image/images/point.png"), "默认");
- m__crop16_10 = m_cropMenu->addAction("16:10");
- m__crop16_9 = m_cropMenu->addAction("16:9");
- m__crop4_3 = m_cropMenu->addAction("4:3");
- m__crop1_85_1 = m_cropMenu->addAction("1.85:1");
- m__crop2_21_1 = m_cropMenu->addAction("2.21:1");
- m__crop2_35_1 = m_cropMenu->addAction("2.35:1");
- m__crop2_39_1 = m_cropMenu->addAction("2.39:1");
- m__crop5_3 = m_cropMenu->addAction("5:3");
- m__crop5_4 = m_cropMenu->addAction("5:4");
- m__crop1_1 = m_cropMenu->addAction("1:1");
-
- m_preCrop = m__cropDefault;
-
- m_cropGroup = new QActionGroup(this);
- m_cropGroup->addAction(m__cropDefault);
- m_cropGroup->addAction(m__crop16_10);
- m_cropGroup->addAction(m__crop16_9);
- m_cropGroup->addAction(m__crop4_3);
- m_cropGroup->addAction(m__crop1_85_1);
- m_cropGroup->addAction(m__crop2_21_1);
- m_cropGroup->addAction(m__crop2_35_1);
- m_cropGroup->addAction(m__crop2_39_1);
- m_cropGroup->addAction(m__crop5_3);
- m_cropGroup->addAction(m__crop5_4);
- m_cropGroup->addAction(m__crop1_1);
-
- connect(m_cropGroup, &QActionGroup::triggered, this, &showWidget::slotCropActionTriggered);
-
-
- //设置缩放菜单
- m_scaleMenu = new QMenu(this);
- m_scaleAction->setMenu(m_scaleMenu);
-
- m_scale1_4 = m_scaleMenu->addAction("1:4 四分之一");
- m_scale1_2 = m_scaleMenu->addAction("1:2 二分之一");
- m_scale1_1 = m_scaleMenu->addAction(QIcon(":/image/images/point.png"),"1:1 原始");
- m_scale2_1 = m_scaleMenu->addAction("2:1 双倍");
-
- m_scaleGroup = new QActionGroup(this);
- m_scaleGroup->addAction(m_scale1_4);
- m_scaleGroup->addAction(m_scale1_2);
- m_scaleGroup->addAction(m_scale1_1);
- m_scaleGroup->addAction(m_scale2_1);
-
- m_preScale = m_scale1_1;
-
- connect(m_scaleGroup, &QActionGroup::triggered, this, &showWidget::slotScaleActionTriggered);
- }
更多参考:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。