ffmpeg制作视频播放器(十四)XPlay2 read接口

XDemux.cpp新增

AVPacket *XDemux::Read()
{
    mux.lock();
    if (!ic) //容错
    {
        mux.unlock();
        return 0;
    }
    AVPacket *pkt = av_packet_alloc();
    //读取一帧,并分配空间
    int re = av_read_frame(ic, pkt);
    if (re != 0)
    {
        mux.unlock();
        av_packet_free(&pkt);
        return 0;
    }
    //pts转换为毫秒
    pkt->pts = pkt->pts*(1000 * (r2d(ic->streams[pkt->stream_index]->time_base)));
    pkt->dts = pkt->dts*(1000 * (r2d(ic->streams[pkt->stream_index]->time_base)));
    mux.unlock();
    cout << pkt->pts << " "<<flush;
    return pkt;
}

 main.cpp新增代码

    for (;;)
    {
        AVPacket *pkt = demux.Read();
        if (!pkt)break;
    }

完整代码如下:

main.cpp

#include "XPlay2.h"

#include <QApplication>
#include <iostream>
using namespace std;
#include "XDemux.h"


int main(int argc, char *argv[])
{
    ///测试XDemux
    XDemux demux;

    //香港卫视
    const char *url = "rtmp://mobliestream.c3tv.com:554/live/goodtv.sdp";
//    url = "001111.mp4";
    cout<<"demux.Open = "<<demux.Open(url);

    for (;;)
    {
        AVPacket *pkt = demux.Read();
        if (!pkt)break;
    }

    QApplication a(argc, argv);
    XPlay2 w;
    w.show();
    return a.exec();
}

XDemux.h

#ifndef XDEMUX_H
#define XDEMUX_H


#include <mutex>
struct AVFormatContext;
struct AVPacket;

class XDemux
{
public:

    //打开媒体文件,或者流媒体 rtmp http rstp
    virtual bool Open(const char *url);

    //空间需要调用者释放 ,释放AVPacket对象空间,和数据空间 av_packet_free
    virtual AVPacket *Read();


    XDemux();
    virtual ~XDemux();

    //媒体总时长(毫秒)
    int totalMs = 0;
protected:
    std::mutex mux;
    //解封装上下文
    AVFormatContext *ic = NULL;
    //音视频索引,读取时区分音视频
    int videoStream = 0;
    int audioStream = 1;

};


#endif // XDEMUX_H

XDemux.cpp

#include "XDemux.h"
#include <iostream>
using namespace std;
extern "C" {
    #include "libavformat/avformat.h"
}

#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"avcodec.lib")
static double r2d(AVRational r)
{
    return r.den == 0 ? 0 : (double)r.num / (double)r.den;
}
bool XDemux::Open(const char *url)
{
    //参数设置
    AVDictionary *opts = NULL;
    //设置rtsp流已tcp协议打开
    av_dict_set(&opts, "rtsp_transport", "tcp", 0);

    //网络延时时间
    av_dict_set(&opts, "max_delay", "5000", 0);

    mux.lock();
    int re = avformat_open_input(
        &ic,
        url,
        0,  // 0表示自动选择解封器
        &opts //参数设置,比如rtsp的延时时间
    );
    if (re != 0)
    {
        mux.unlock();
        char buf[1024] = { 0 };
        av_strerror(re, buf, sizeof(buf) - 1);
        cout << "open " << url << " failed! :" << buf << endl;
        return false;
    }
    cout << "open " << url << " success! " << endl;

    //获取流信息
    re = avformat_find_stream_info(ic, 0);

    //总时长 毫秒
    int totalMs = ic->duration / (AV_TIME_BASE / 1000);
    cout << "totalMs = " << totalMs << endl;

    //打印视频流详细信息
    av_dump_format(ic, 0, url, 0);

    //获取视频流
    videoStream = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
    AVStream *as = ic->streams[videoStream];

    cout << "=======================================================" << endl;
    cout << videoStream << "视频信息" << endl;
    cout << "codec_id = " << as->codecpar->codec_id << endl;
    cout << "format = " << as->codecpar->format << endl;
    cout << "width=" << as->codecpar->width << endl;
    cout << "height=" << as->codecpar->height << endl;
    //帧率 fps 分数转换
    cout << "video fps = " << r2d(as->avg_frame_rate) << endl;

    cout << "=======================================================" << endl;
    cout << audioStream << "音频信息" << endl;
    //获取音频流
    audioStream = av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
    as = ic->streams[audioStream];
    cout << "codec_id = " << as->codecpar->codec_id << endl;
    cout << "format = " << as->codecpar->format << endl;
    cout << "sample_rate = " << as->codecpar->sample_rate << endl;
    //AVSampleFormat;
    cout << "channels = " << as->codecpar->channels << endl;
    //一帧数据?? 单通道样本数
    cout << "frame_size = " << as->codecpar->frame_size << endl;
    //1024 * 2 * 2 = 4096  fps = sample_rate/frame_size
    mux.unlock();

    return true;
}

AVPacket *XDemux::Read()
{
    mux.lock();
    if (!ic) //容错
    {
        mux.unlock();
        return 0;
    }
    AVPacket *pkt = av_packet_alloc();
    //读取一帧,并分配空间
    int re = av_read_frame(ic, pkt);
    if (re != 0)
    {
        mux.unlock();
        av_packet_free(&pkt);
        return 0;
    }
    //pts转换为毫秒
    pkt->pts = pkt->pts*(1000 * (r2d(ic->streams[pkt->stream_index]->time_base)));
    pkt->dts = pkt->dts*(1000 * (r2d(ic->streams[pkt->stream_index]->time_base)));
    mux.unlock();
    cout << pkt->pts << " "<<flush;
    return pkt;
}

XDemux::XDemux()
{
    static bool isFirst = true;
    static std::mutex dmux;
    dmux.lock();
    if (isFirst)
    {
        //初始化封装库
        av_register_all();

        //初始化网络库 (可以打开rtsp rtmp http 协议的流媒体视频)
        avformat_network_init();
        isFirst = false;
    }
    dmux.unlock();
}

XDemux::~XDemux()
{

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值