目录

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

播放比例设置:

右键,比例,保持宽高比

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;
}  

播放器 potplayer rtsp播放器相关推荐

  1. Windows平台RTMP|RTSP播放器为什么要兼容GDI绘制

    为什么要支持GDI 先说结论,Windows平台播放渲染这块,一般来说99%以上的机器都是支持D3D的,实现GDI模式绘制,除了为了好的兼容性外,在远程连接的场景下,D3D创建不成功,需要使用GDI模 ...

  2. Windows平台RTMP播放器/RTSP播放器如何在播放窗口添加OSD文字叠加

    好多开发者在做Windows平台特别是单屏多画面显示时,希望像监控摄像机一样,可以在播放画面添加OSD台标,以实现字符叠加效果,大多开发者可很轻松的实现以上效果,针对此,本文以大牛直播SDK (Git ...

  3. RTSP播放器开发过程中需要考虑哪些关键因素

    好多开发者,在自研或者选择市面上的播放器的时候,除了常规的播放功能,还有很多点值得关注,如延迟.资源占用.网络异常处理.多实例支持.长时间运行稳定性等.以下是我们开发直播播放器过程中,考虑的部分关键因 ...

  4. 【技术分享】如何实现功能完备性能优异的RTMP、RTSP播放器?

    技术背景 这几年,我们对接了太多有RTSP或RTMP直播播放器诉求的开发者,他们当中除了寻求完整的解决方案的,还有些是技术探讨,希望能借鉴我们播放端的开发思路或功能特性,完善自己的产品. 忙里偷闲,今 ...

  5. Android、iOS平台RTMP/RTSP播放器实现实时音量调节

    介绍移动端RTMP.RTSP播放器实时音量调节之前,我们之前也写过,为什么windows播放端加这样的接口,windows端播放器在多窗口大屏显示的场景下尤其需要,尽管我们老早就有了实时静音接口,相对 ...

  6. Windows平台RTMP/RTSP播放器如何实现实时音量调节

    为什么要做实时音量调节 RTMP或RTSP直播播放音量调节,主要用于多实例(多窗口)播放场景下,比如同时播放4路RTMP或RTSP流,如果音频全部打开,几路audio同时打开,可能会影响用户体验,我们 ...

  7. RTSP播放器开发填坑之道

    好多开发者提到,在目前开源播放器如此泛滥的情况下,为什么还需要做自研框架的RTSP播放器,自研和开源播放器,到底好在哪些方面?以下大概聊聊我们的一点经验,感兴趣的,可以关注 github: 1. 低延 ...

  8. Android平台RTMP/RTSP播放器开发系列之解码和绘制

    本文主要抛砖引玉,粗略介绍下Android平台RTMP/RTSP播放器中解码和绘制相关的部分(Github). 解码 提到解码,大家都知道软硬解,甚至一些公司觉得硬解码已经足够通用,慢慢抛弃软解了,如 ...

  9. RTSP播放器或RTMP播放器常用的事件回调设计

    很多开发者在开发RTSP或RTMP播放器的时候,不晓得哪些event回调事件是有意义的,针对此,我们以大牛直播SDK(github)的Android平台RTSP/RTMP直播播放端为例,简单介绍下常用 ...

最新文章

  1. 「Smile」一下,轻松用Java玩转机器学习
  2. 死磕Java并发:J.U.C之读写锁:ReentrantReadWriteLock
  3. 上海交通大学python教材答案-上海交通大学python期末考试样题加解析.doc
  4. 牛客网 New Game! 建图+最短路
  5. MFC添加自定义消息及处理函数
  6. 脚本——监控打印服务
  7. Information Bottleneck 信息瓶颈
  8. 部分软件免管理员权限安装
  9. 2020-12-10-计算机基础
  10. 天宇优配|混动车将告别上海免费绿牌 新能源多种技术路
  11. 猎聘、BOSS、智联、前程无忧这几个招聘网站我都用过
  12. ggplot2 theme主题参数详解
  13. linux用户读取文件过程,Python中读取写入文件并进行文件与用户交互的操作
  14. 如何用计算机放音乐,教你如何用iPhone远程遥控电脑播放音乐教程
  15. html+css实现了简单的注册页面
  16. Altium脚本开发
  17. 单片机控制WS2812B实例代码
  18. 工具:你一定要知道的项目管理高手常用10张图表
  19. 苹果usbc音频android,苹果USB-C音频线Android手机能用么?实测10款手机仅1款不支持...
  20. 北斗三号卫星导航信号及接收策略

热门文章

  1. matlab图像处理基本概念-滤波|图像分割|图像增强|边缘检测
  2. 怎么把DWG转换成DXF?快点进来看看
  3. honehone clock人体时钟插件
  4. 计算机动漫与游戏制作课程安排,计算机动漫与游戏制作专业教学计划
  5. Pushback后推到底是一个飞机的一个什么操作?
  6. JS键盘按键监听-多个按键同时按下
  7. TortoiseSVN小乌龟GIT之使用教程
  8. ptrace的使用流程
  9. 数模整数规划Python编程实现
  10. linux命令 将数据库表导出sql文件 mysqldump