一、开发环境的准备
Linux下移植ffmpeg开源库。
二、代码实现播放功能
1、打开音视频流并获取音视频流信息;
2、查找视频流位置以及查找并打开视频解码器;
3、视频解码的同时处理图片像素数据;
4、最后要释放申请的内存空间。*
.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QDesktopWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = NULL);
~Widget();
private slots:
void on_pushButton_clicked();
void slotOpenFile();
void on_Close_clicked();
void on_Close_2_clicked();
private:
Ui::Widget *ui;
QString currentFileName;
};
#endif
.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QTime>
#include <QFileDialog>
#include <QScreen>
extern "C"{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
}
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
this->setWindowTitle("hello");
QObject::connect(ui->open,SIGNAL(clicked()),this,SLOT(slotOpenFile()));
}
Widget::~Widget()
{
delete ui;
}
void delay(int msec)
{
QTime dieTime = QTime::currentTime().addMSecs(msec);
while( QTime::currentTime() < dieTime )
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}
void Widget::slotOpenFile()
{
currentFileName = QFileDialog::getOpenFileName(this, tr("open-file"), tr(""),
tr("Video files(*.rmvb *.rm *.avi *.wmv *.mkv *.asf *.3gp *.mov *.mp4 *.ogv* )"));
if( !currentFileName.isEmpty() )
{
on_pushButton_clicked();
}
}
void Widget::on_pushButton_clicked()
{
AVFormatContext *pFormatCtx;
int videoIndex = -1;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame, *pFrameRGB;
unsigned char *out_buffer;
AVPacket *packet;
int ret, got_picture;
struct SwsContext *img_convert_ctx;
char file_path[1280] = {0};
strcpy(file_path,currentFileName.toUtf8().data());
av_register_all();
pFormatCtx = avformat_alloc_context();
if (avformat_open_input(&pFormatCtx, file_path, NULL, NULL) != 0)
{
printf("Couldn't open input stream.\n");
return;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
{
printf("Couldn't find stream information.\n");
return;
}
for (int i = 0; i < (int)pFormatCtx->nb_streams; i++)
{
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoIndex = i;
break;
}
}
if (videoIndex == -1)
{
printf("Didn't find a video stream.\n");
return ;
}
pCodecCtx = pFormatCtx->streams[videoIndex]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL)
{
printf("Codec not found.\n");
return ;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
{
printf("Could not open codec.\n");
return ;
}
printf("--------------- File Information ----------------\n");
av_dump_format(pFormatCtx, 0, file_path, 0);
printf("-------------------------------------------------\n");
pFrame = av_frame_alloc();
pFrameRGB = av_frame_alloc();
out_buffer = (unsigned char *)av_malloc((size_t)av_image_get_buffer_size(AV_PIX_FMT_RGB32, pCodecCtx->width, pCodecCtx->height, 1));
av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, out_buffer,
AV_PIX_FMT_RGB32, pCodecCtx->width, pCodecCtx->height, 1);
packet = (AVPacket *)av_malloc(sizeof(AVPacket));
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB32, SWS_BICUBIC, NULL, NULL, NULL);
while (av_read_frame(pFormatCtx, packet) >= 0)
{
if (packet->stream_index == videoIndex)
{
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
if (ret < 0)
{
printf("Decode Error.\n");
return ;
}
if (got_picture)
{
sws_scale(img_convert_ctx, (const unsigned char* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
pFrameRGB->data, pFrameRGB->linesize);
QImage img((uchar*)pFrameRGB->data[0],pCodecCtx->width,pCodecCtx->height,QImage::Format_RGB32);
ui->label->setPixmap(QPixmap::fromImage(img));
delay(40);
}
}
av_free_packet(packet);
}
sws_freeContext(img_convert_ctx);
av_frame_free(&pFrameRGB);
av_frame_free(&pFrame);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
}
void Widget::on_Close_clicked()
{
close();
}
void Widget::on_Close_2_clicked()
{
static bool max = false;
static QRect location = this->geometry();
if (max) {
this->setGeometry(location);
} else {
location = this->geometry();
this->setGeometry(qApp->desktop()->availableGeometry());
}
this->setProperty("canMove", max);
max = !max;
}
三、参考源码
Qt + FFmpeg简单实现视频播放
Qt + FFmpeg实时视频播放
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)