播放器 potplayer rtsp播放器

目录

potplayer:

potplayer 播放万播放下一曲

播放比例设置:

html5_rtsp_player:

GitHub - Streamedian/html5_rtsp_player: Play RTSP stream from IP camera in browser in this HTML5 player without plugins

Error: Please, upgrade your dependencies to the actual version of core-js@3

Videojs播放RTMP流媒体

http://blog.csdn.net/dong_18383219470/article/details/52998278

FFmpeg3.3.2+SDL2实现流媒体音频播放

Qt+VLC编写的流媒体播放器

RTSP流媒体播放器实现


potplayer:

下载地址:

https://softforspeed.51xiazai.cn/down/2022down/12/02/PotPlayer1.7.21846.exe

h265解码器:

Releases · Nevcairiel/LAVFilters · GitHub

potplayer 播放万播放下一曲

首先我们双击打开“PotPlayer”播放器

      这时打开播放器后,点击软件左上角的“PotPlayer”

      接着打开软件选项列表后,选择“配置/语言/其他”选择

      然后我们在打开的次级菜单中,选择“收尾处理”

      在弹出的收尾处理次级菜单中,选择“播放完当前后停止”

播放比例设置:

右键,比例,保持宽高比

html5_rtsp_player:

GitHub - Streamedian/html5_rtsp_player: Play RTSP stream from IP camera in browser in this HTML5 player without plugins

Error: Please, upgrade your dependencies to the actual version of core-js@3

解决方法:

npm install --save core-js@^3

ARM+mplayer+QT+流媒体项目源代码包下载(刘继光著)

http://download.csdn.net/index.php/mobile/source/download/liuji_guang/2771211

Videojs播放RTMP流媒体

http://blog.csdn.net/dong_18383219470/article/details/52998278

FFmpeg3.3.2+SDL2实现流媒体音频播放

http://blog.csdn.net/ywl5320/article/details/76383099

Qt+VLC编写的流媒体播放器

https://sh.qihoo.com/ctranscode?userid=1a4f8abeb7b38703c3e907bc82ac9bde&fast=1&&360sodetail=1&u=http%3A%2F%2Fblog.csdn.net%2Fu012952807%2Farticle%2Fdetails%2F51659446&m=2faad55a1713f4197f47c4be009fa606a2a0b9dd&q=qt%20%20%20%20%20%E6%B5%81%E5%AA%92%E4%BD%93%E6%92%AD%E6%94%BE&t=news&sid=d9d0cc4e29c791f47f9a37b4e4bdb72b&tc_mode=news_recom

RTSP流媒体播放器实现

        最近需要做一个RTSP流媒体播放器,研究了一下,封装了一个RTSP播放类CRTSPPlayer,解码库采用ffmpeg。由于需求比较简单,时间也有限,目前只实现了播放、停止、暂停几个基本的接口。下面是基于CRTSPPlayer类实现的简单RTSP播放器。

       目前视频只测试了H264格式,其它格式的视频还未做测试。播放器也支持直接打开本地视频播放,但播放的帧率和原始视频的码率不同步。目前还不清楚如何处理这个问题,希望懂这方面的大侠指教。

       另外,还有一个开源的库VLC也可以用来开发流媒体播放器,它支持多种流媒体协议,如RTP、RTSP等,CodeProject上已经有牛人在VLCLib的基础上封装可更易使用的库VLCWrapper(地址:VLCWrapper - A Little C++-wrapper Around libvlc - CodeProject)。用它可以很方便的开发视频播放器。

        以下是CRTSPPlayer完整的代码:

头文件: view plain copy

/********************************************************************  
filename:   CRTSPPlayer.h  
created:    2013-03-25  
author:     firehood  
purpose:    ffmpeg库实现的RTSP视频播放器 
*********************************************************************/   
#pragma once  
#include "windows.h"  
  
extern "C"  
{  
#include "libavformat\avformat.h"  
#include "libavcodec\avcodec.h"  
#include "libswscale\swscale.h"  
};  
  
// 播放状态  
enum RTSP_PLAYSTATUS  
{  
    RTSP_PLAYSTATUS_NONE,       // 未知状态(未播放)  
    RTSP_PLAYSTATUS_PLAYING,    // 正在播放  
    RTSP_PLAYSTATUS_PAUSE,      // 已暂停  
    RTSP_PLAYSTATUS_STOP,       // 已停止  
};  
  
class CRTSPPlayer  
{  
public:  
    CRTSPPlayer(HWND hWnd, LPRECT lpRect);  
    ~CRTSPPlayer(void);  
public:  
    // 打开媒体文件  
    BOOL OpenMedia(LPCTSTR pFileName);  
    // 播放  
    void Play();  
    // 暂停  
    void Pause();  
    // 停止  
    void Stop();  
    // 获取播放状态  
    RTSP_PLAYSTATUS GetPlayStatus(void);  
private:  
    // 解码初始化  
    int DecodeInit(LPCTSTR pFileName);  
    // 卸载  
    void DecodeUninit();  
    // 开始解码线程  
    BOOL StartDecodeThread();  
    // 停止解码线程  
    void StopDecodeThread();  
    // 解码线程  
    static int WINAPI ThreadDecodeVideo(LPVOID lpParam);  
    // 开始解码任务  
    int BeginDecode();  
    // 显示  
    void Display();  
    // 图像转换  
    int ImgConvert(AVPicture * dst, PixelFormat dstFormt, const AVPicture * src, PixelFormat srcFormt, int src_width, int src_height);  
    // 设置播放状态  
    void SetPlayStatus(RTSP_PLAYSTATUS playStatus);  
private:  
    HANDLE  m_hDecodeThread;  
    BOOL    m_bExitDecodeThread;  
    TCHAR   m_strFilePath[MAX_PATH];  
  
    AVFormatContext* m_pFormatContext;  
    AVCodecContext*  m_pCodecContext;  
    AVCodec* m_pCodec;  
    AVPacket m_struPacket;  
    int m_nStreamIndex;  
    AVFrame* m_pFrameYUV;  
    AVFrame* m_pFrameRGB;  
    int     m_nFrameWidth;   
    int     m_nFrameHeight;  
    BYTE*   m_pBufRGB;        // 解码后的RGB数据  
  
    RTSP_PLAYSTATUS  m_nPlayStatus;  
    HWND    m_hWnd;  
    RECT    m_rcWnd;  
};  

源文件:


/********************************************************************  
filename:   CRTSPPlayer.cpp  
created:    2013-03-25  
author:     firehood  
purpose:    ffmpeg库实现的RTSP视频播放器 
*********************************************************************/   
#include "StdAfx.h"  
#include "RTSPPlayer.h"  
  
#pragma comment(lib, "avformat.lib")  
#pragma comment(lib, "avcodec.lib")  
#pragma comment(lib, "swscale.lib")  
#pragma comment(lib, "avutil.lib")  
  
#define SHOW_TITLE  
  
const char* WcharToUtf8(const wchar_t *pwStr)    
{    
    if (pwStr == NULL)    
    {    
        return NULL;    
    }    
  
    int len = WideCharToMultiByte(CP_UTF8, 0, pwStr, -1, NULL, 0, NULL, NULL);    
    if (len <= 0)    
    {    
        return NULL;    
    }    
    char *pStr = new char[len];    
    WideCharToMultiByte(CP_UTF8, 0, pwStr, -1, pStr, len, NULL, NULL);    
    return pStr;    
}    
  
CRTSPPlayer::CRTSPPlayer(HWND hWnd, LPRECT lpRect):  
m_hWnd(hWnd),  
m_rcWnd(*lpRect),  
m_hDecodeThread(NULL),  
m_bExitDecodeThread(FALSE),  
m_nFrameWidth(0),  
m_nFrameHeight(0),  
m_pFormatContext(NULL),  
m_pCodecContext(NULL),  
m_pCodec(NULL),  
m_nStreamIndex(-1),  
m_pFrameYUV(NULL),  
m_pFrameRGB(NULL),  
m_pBufRGB(NULL),  
m_nPlayStatus(RTSP_PLAYSTATUS_NONE)  
{  
    memset(m_strFilePath,0,sizeof(m_strFilePath));  
}  
  
CRTSPPlayer::~CRTSPPlayer(void)  
{  
    DecodeUninit();  
}  
  
// 打开媒体文件  
BOOL CRTSPPlayer::OpenMedia(LPCTSTR pFileName)  
{  
    if(pFileName == NULL)  
        return FALSE;  
    DecodeUninit();  
    memcpy(m_strFilePath,pFileName,sizeof(m_strFilePath));  
    DecodeInit(m_strFilePath);  
    return TRUE;  
}  
  
// 播放  
void CRTSPPlayer::Play()  
{   
    if(GetPlayStatus() == RTSP_PLAYSTATUS_STOP)  
    {  
        DecodeInit(m_strFilePath);  
    }  
    BOOL bRet = StartDecodeThread();  
    if(bRet)  
    {  
        SetPlayStatus(RTSP_PLAYSTATUS_PLAYING);  
    }  
}  
  
// 暂停  
void CRTSPPlayer::Pause()  
{  
    StopDecodeThread();  
    SetPlayStatus(RTSP_PLAYSTATUS_PAUSE);  
}  
  
// 停止  
void CRTSPPlayer::Stop()  
{  
    StopDecodeThread();  
    DecodeUninit();  
    SetPlayStatus(RTSP_PLAYSTATUS_STOP);  
}  
  
BOOL CRTSPPlayer::StartDecodeThread()  
{  
    if(m_hDecodeThread == NULL)  
    {  
        m_hDecodeThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadDecodeVideo, this, 0, NULL);  
    }  
    return m_hDecodeThread ? TRUE : FALSE;  
}  
  
void CRTSPPlayer::StopDecodeThread()  
{  
    if(m_hDecodeThread)  
    {  
        m_bExitDecodeThread = TRUE;  
        WaitForSingleObject(m_hDecodeThread,INFINITE);  
        CloseHandle(m_hDecodeThread);  
        m_hDecodeThread = NULL;  
    }  
}  
  
int CRTSPPlayer::ImgConvert(AVPicture * dst, PixelFormat dst_pix_fmt, const AVPicture * src, PixelFormat src_pix_fmt, int src_width, int src_height)  
{  
  
    unsigned char * srcSlice[4];  
    int srcStride[4] = {0};  
  
    unsigned char * dstSlice[4];  
    int dstStride[4] = {0};  
  
  
    for (int i=0; i<4; i++)  
    {  
        srcSlice[i] = src->data[i];  
        srcStride[i] = src->linesize[i];  
  
        dstSlice[i] = dst->data[i];  
        dstStride[i] = dst->linesize[i];  
    }  
  
    SwsContext *pSwsContext = sws_getContext(src_width, src_height, src_pix_fmt, src_width, src_height, dst_pix_fmt, SWS_BICUBIC, NULL, NULL, NULL);  
  
    int nRet = sws_scale(pSwsContext, srcSlice, srcStride, 0, src_height, dstSlice, dstStride);  
  
    if (pSwsContext != NULL)  
    {  
        sws_freeContext(pSwsContext);  
    }  
  
    return nRet;  
}  
  
int WINAPI CRTSPPlayer::ThreadDecodeVideo(LPVOID lpParam)  
{  
    CRTSPPlayer *pPlayer = (CRTSPPlayer*)lpParam;  
  
    pPlayer->BeginDecode();  
  
    return 0;  
}  
  
int CRTSPPlayer::DecodeInit(LPCTSTR pFileName)  
{  
    if(pFileName == NULL)  
    {  
        return -1;  
    }  
  
    av_register_all();  
  
#ifdef  UNICODE     
    const char *filePath = WcharToUtf8(pFileName);   
    // Open video  
    if (av_open_input_file(&m_pFormatContext, filePath, NULL, 0, NULL) != 0)  
    {  
        return -2; // Couldn't open file  
    }  
    delete[] filePath;  
#else  
    // Open video  
    if (av_open_input_file(&m_pFormatContext, pFileName, NULL, 0, NULL) != 0)  
    {  
        return -2; // Couldn't open file  
    }  
#endif  
    // Retrieve stream information  
    if (av_find_stream_info(m_pFormatContext) < 0)  
    {  
        return -3; // Couldn't find stream information  
    }  
  
    // Find the first video stream  
    for (UINT i=0; i<m_pFormatContext->nb_streams; i++)  
    {  
        if (m_pFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)  
        {  
            m_nStreamIndex = i;  
            break;  
        }  
    }  
    if (m_nStreamIndex == -1)  
    {  
        return -4; // Didn't find a video stream  
    }  
  
    // Get a pointer to the codec context for the video stream  
    m_pCodecContext = m_pFormatContext->streams[m_nStreamIndex]->codec;  
  
    // Find the decoder for the video stream  
    m_pCodec = avcodec_find_decoder(m_pCodecContext->codec_id);  
    if (m_pCodec == NULL)  
    {  
        return -5 ; // Codec not found  
    }  
  
    // Inform the codec that we can handle truncated bitstreams -- i.e.,  
    // bitstreams where frame boundaries can fall in the middle of packets  
    if (m_pCodec->capabilities & CODEC_CAP_TRUNCATED)  
    {  
        m_pCodecContext->flags |= CODEC_FLAG_TRUNCATED;  // we do not send complete frames  
    }  
  
    // Open codec  
    if (avcodec_open(m_pCodecContext, m_pCodec) < 0)  
    {  
        return -6; // Could not open codec  
    }  
  
    // Allocate video frame  
    m_pFrameYUV = avcodec_alloc_frame();  
  
    // Allocate an AVFrame structure  
    m_pFrameRGB = avcodec_alloc_frame();  
  
    // Determine required buffer size and allocate buffer  
    int numBytes = avpicture_get_size(PIX_FMT_BGR24, m_pCodecContext->width, m_pCodecContext->height);  
    m_pBufRGB = new BYTE [numBytes];  
    memset(m_pBufRGB,0,numBytes);  
    // Assign appropriate parts of buffer to image planes in m_pFrameRGB  
    avpicture_fill((AVPicture *)m_pFrameRGB, m_pBufRGB, PIX_FMT_BGR24, m_pCodecContext->width, m_pCodecContext->height);  
  
    m_nFrameWidth  = m_pCodecContext->width;  
    m_nFrameHeight = m_pCodecContext->height;  
  
    return 0;  
}  
  
void CRTSPPlayer::DecodeUninit()  
{  
    // Close the codec  
    if (m_pCodecContext)  
    {  
        avcodec_close(m_pCodecContext);  
        //av_free(m_pCodec);  
        m_pCodecContext = NULL;  
        m_pCodec = NULL;  
    }  
  
    // Close the video file  
    if (m_pFormatContext)  
    {  
        av_close_input_file(m_pFormatContext);  
        m_pFormatContext = NULL;  
    }  
  
    if (m_pFrameYUV)  
    {  
        av_free(m_pFrameYUV);  
        m_pFrameYUV = NULL;  
    }  
  
    if (m_pFrameRGB)  
    {  
        av_free(m_pFrameRGB);  
        m_pFrameRGB = NULL;  
    }  
  
    if (m_pBufRGB)  
    {  
        delete [] m_pBufRGB;  
        m_pBufRGB = NULL;  
    }  
}  
  
int CRTSPPlayer::BeginDecode()  
{  
    int bytesRemaining = 0, bytesDecoded;  
    BYTE * rawData = NULL;  
  
    int frameFinished = 0;  
  
    m_struPacket.data = NULL;  
    m_struPacket.size = 0;  
  
    m_bExitDecodeThread = FALSE;  
  
    while (!m_bExitDecodeThread && m_pFormatContext)  
    {  
        // Read the next packet, skipping all packets that aren't for this stream  
        do  
        {  
            // Read new packet  
            if (av_read_frame(m_pFormatContext, &m_struPacket) < 0)  
            {  
  
                return -2;  
            }  
        } while (m_struPacket.stream_index != m_nStreamIndex);  
  
        bytesRemaining = m_struPacket.size;  
        rawData = m_struPacket.data;  
  
        // Work on the current packet until we have decoded all of it  
        while (bytesRemaining > 0)  
        {  
            // Decode the next chunk of data  
            bytesDecoded = avcodec_decode_video(m_pCodecContext, m_pFrameYUV, &frameFinished, rawData, bytesRemaining);  
  
            // Was there an error?  
            if (bytesDecoded < 0)  
            {  
                return -1;  
            }  
  
            bytesRemaining -= bytesDecoded;  
            rawData += bytesDecoded;  
  
            // Did we finish the current frame? Then we can return  
            if (frameFinished)  
            {  
                ImgConvert(  
                    (AVPicture *)m_pFrameRGB,  
                    PIX_FMT_BGR24,  
                    (AVPicture *)m_pFrameYUV,  
                    m_pCodecContext->pix_fmt,  
                    m_pCodecContext->width,  
                    m_pCodecContext->height);  
  
                Display();  
            }  
        }  
    }  
    m_hDecodeThread = NULL;  
    return 0;  
}  
  
void CRTSPPlayer::Display()  
{  
    HDC hdc = GetDC(m_hWnd);  
    // 创建内存DC  
    HDC hMemDc = CreateCompatibleDC(hdc);       
  
    // 创建位图  
    BITMAPINFOHEADER bmpHdr = {0};    
    bmpHdr.biSize = sizeof (BITMAPINFOHEADER);    
    bmpHdr.biWidth = m_nFrameWidth;    
    bmpHdr.biHeight = -m_nFrameHeight;    
    bmpHdr.biPlanes = 1;    
    bmpHdr.biBitCount = 24;    
    bmpHdr.biCompression = BI_RGB;    
  
    BYTE *pData = NULL;     
    HBITMAP hBitmap = CreateDIBSection (NULL, (BITMAPINFO *)&bmpHdr, DIB_RGB_COLORS, (void**)&pData, NULL, 0);    
  
    try  
    {  
        memcpy(pData, m_pBufRGB, m_nFrameWidth * m_nFrameHeight * 3);  
    }  
    catch (CMemoryException* e)  
    {  
          
    }  
  
    HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDc, hBitmap);  
  
#ifdef SHOW_TITLE  
    // 设置字体参数  
    LOGFONT logfont;  
    memset(&logfont, 0, sizeof(LOGFONT));  
    logfont.lfHeight = 40;  
    logfont.lfWidth = 0;      
    logfont.lfEscapement = 0;  
    logfont.lfOrientation = 0;  
    logfont.lfWeight = 30;  
    logfont.lfItalic = 0;  
    logfont.lfUnderline = 0;  
    logfont.lfStrikeOut = 0;  
    logfont.lfCharSet = DEFAULT_CHARSET;     
    logfont.lfOutPrecision= OUT_DEFAULT_PRECIS;     
    logfont.lfClipPrecision= OUT_DEFAULT_PRECIS;     
    logfont.lfQuality = DEFAULT_QUALITY;     
    logfont.lfPitchAndFamily= DEFAULT_PITCH;    
  
    // 创建字体并选入环境  
    HFONT hFont = CreateFontIndirect(&logfont);  
    HFONT hOldFont = (HFONT)SelectObject(hMemDc, hFont);  
  
    // 设置绘图环境  
    SetBkMode(hMemDc, TRANSPARENT);    
    SetTextColor(hMemDc, RGB(255, 255, 0));  
  
    // 绘制文字  
    TextOut(hMemDc,0,0,m_strFilePath,_tcslen(m_strFilePath));  
  
    // 恢复环境释放字体  
    SelectObject(hMemDc, hOldFont);  
#endif  
    StretchBlt(    
        hdc,    
        m_rcWnd.left,     
        m_rcWnd.top,     
        m_rcWnd.right-m_rcWnd.left,     
        m_rcWnd.bottom-m_rcWnd.top,     
        hMemDc,    
        0,     
        0,     
        m_nFrameWidth,     
        m_nFrameHeight,     
        SRCCOPY);    
  
    // 恢复并释放环境      
    SelectObject(hMemDc,hOldBitmap);    
    DeleteObject(hBitmap);    
    DeleteDC(hMemDc);    
}  
  
// 获取播放状态  
RTSP_PLAYSTATUS CRTSPPlayer::GetPlayStatus(void)  
{  
    return m_nPlayStatus;  
}  
  
// 设置播放状态  
void CRTSPPlayer::SetPlayStatus(RTSP_PLAYSTATUS playStatus)  
{  
    m_nPlayStatus = playStatus;  
}  

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
多路RTSP播放器的源码是一个用于实现同时播放多个RTSP流的程序代码。RTSP(实时流传输协议)是一种用于流媒体传输的协议,允许用户通过互联网实时传输音频和视频数据。 多路RTSP播放器的源码通常包括以下重要组件: 1. 网络连接管理:源码中包含了建立和管理与服务器的连接的代码,以确保能够同时播放多个RTSP流,并处理网络异常情况。 2. 流数据接收和解码:源码中包含了接收和解码多个RTSP流数据的模块。这些模块可以将传输过来的二进制数据转换为可播放的音频和视频流。 3. 资源管理:源码中通常包含了对音频和视频资源的管理代码,包括对多个RTSP流的选择、切换和控制等。 4. UI界面:源码中会包含用于用户交互的UI界面代码,以提供用户操作和控制多个RTSP流的功能。这可能包括播放、暂停、停止和调整音量等控制选项。 5. 错误处理和日志记录:源码中通常会包含用于处理和记录错误信息的代码,以帮助调试和追踪问题。 多路RTSP播放器的源码可以使用各种编程语言实现,例如Python、C++和Java等。在编写源码时,需要仔细考虑并处理多个RTSP流之间的同步、带宽管理和资源分配等问题,以提供流畅的播放体验。 总的来说,多路RTSP播放器的源码是一个功能强大的程序代码,可以同时播放多个RTSP流,并提供丰富的用户交互和控制选项。这样的源码对于实现多路实时流媒体播放应用程序非常有用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI算法网奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值