用QT开发Android投屏软件,添加录屏功能

实现录屏功能,需要将Android设备通过Socket发送到客户端的AVPacket数据保存成文件。
在前面的文章中讲过界面如何通过OpenGL绘制AVPacket.
简单回顾下:Demuxer线程不断的读取视频socket链路上的数据,以AVPacket对象的形式交给解码器,解码器遍历PacketSink列表,PacketSink按照各自的实现使用AVPacket数据。我们继承PacketSink类,分别实现
RecoderVideoSink和RecoderAudioSink

class RecoderVideoSink:public PacketSink{
public:
    RecoderVideoSink(RecorderThread *handler);
    ~RecoderVideoSink();

    virtual bool open(AVCodecContext *ctx);
    virtual void close();
    virtual bool push(AVPacket *packet);
    //virtual void disable();
private:
    RecorderThread *recorder;

};
class RecoderAudioSink:public PacketSink{
public:
    RecoderAudioSink(RecorderThread *handler);
    ~RecoderAudioSink();

    virtual bool open(AVCodecContext *ctx);
    virtual void close();
    virtual bool push(AVPacket *packet);
    //virtual void disable();
private:
    RecorderThread *recorder;
};

将实现的这两个Sink,加入到Decoder的Sink列表,这样在解码过程中AVPacket会复制过来。
录屏功能新创建一个线程,线程的优先级可是设低一些,把宝贵的CPU资源优先让给其它线程。下面是部分代码

//创建待输出的文件
bool RecorderThread::openOutputFile()
{
    const char *format_name = Utils::getFormatName(this->recordFormat);
    assert(format_name);
    const AVOutputFormat *format = findMuxer(format_name);
    if (!format) {
        qDebug()<<"Could not find muxer";
        return false;
    }

    this->ctx = avformat_alloc_context();
    if (!this->ctx) {
        return false;
    }
    AVStream *stream = avformat_new_stream(this->ctx,videoCtx->codec);
    if (!stream) {
        return false;
    }

    int r = avcodec_parameters_from_context(stream->codecpar, videoCtx);
    if (r < 0) {
        return false;
    }

    this->videoStream.index = stream->index;

    int ret = avio_open(&this->ctx->pb, this->fileName.toUtf8().data(),
                        AVIO_FLAG_WRITE);
    if (ret < 0) {
        qDebug()<<"Failed to open output file: "<<fileName;
        avformat_free_context(this->ctx);
        return false;
    }
    this->ctx->oformat = (AVOutputFormat *) format;

    av_dict_set(&this->ctx->metadata, "comment",
                "Power By Linkedbyte ",1.0);
    qDebug()<<QString("Recording started to %1 file: %2").arg(format_name).arg(fileName);
    return true;
}
//写入视频文件头信息
bool RecorderThread::processHeader()
{
    this->mutex.lock();

    while (!this->stopped && this->videoQueue.empty())
    {
        this->cond.wait(&this->mutex);
    }


    AVPacket *videoPkt = NULL;
    if (!this->videoQueue.empty()) {
        videoPkt = this->videoQueue.back();
        this->videoQueue.pop();
    }

    AVPacket *audioPkt = NULL;
    if (!this->audioQueue.empty()) {
        audioPkt = this->audioQueue.back();
        this->audioQueue.pop();
    }

    this->mutex.unlock();

    int ret = false;
    bool ok = false;

    if (videoPkt) {
        if (videoPkt->pts != AV_NOPTS_VALUE) {
            qDebug()<<"The first video packet is not a config packet";
            goto end;
        }
        assert(this->videoStream.index >= 0);
        AVStream *vStream =
            this->ctx->streams[this->videoStream.index];
        ok = setExtradata(vStream, videoPkt);
        if (!ok) {
            goto end;
        }
    }

    if (audioPkt) {
        if (audioPkt->pts != AV_NOPTS_VALUE) {
            goto end;
        }

        assert(this->audioStream.index >= 0);
        AVStream *audio_stream =
            this->ctx->streams[this->audioStream.index];
        ok = setExtradata(audio_stream, audioPkt);
        if (!ok) {
            goto end;
        }
    }

    ok = avformat_write_header(this->ctx, NULL) >= 0;
    if (!ok) {
        goto end;
    }

    ret = true;

end:
    if (videoPkt) {
        av_packet_free(&videoPkt);
    }
    if (audioPkt) {
        av_packet_free(&audioPkt);
    }

    return ret;
}

效果图:

在这里插入图片描述

QQ 2276769057

https://github.com/linkedbyte/tomobile

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
录屏投屏是一种将Android设备上的屏幕内容实时显示到其他设备上的技术。在Android开发中,可以使用Java编程语言来实现录屏投屏功能。 首先,需要使用Android提供的MediaProjection类来获取用户的屏幕截图。 通过MediaProjection类提供的createVirtualDisplay方法,可以创建一个虚拟的显示屏幕,并设置屏幕的宽度、高度和像素密度等参数。然后,再通过该虚拟显示屏幕和MediaProjection类的createCaptureSession方法创建一个屏幕捕获会话。 捕获会话创建成功后,可以获取屏幕内容的Surface对象,并将其与屏幕捕获会话绑定。接下来,通过MediaRecorder类来进行屏幕录制和编码工作。可以设置录制参数,如视频编码格式、比特率和帧率等。 录制和编码完成后,可以将屏幕内容通过网络传输到其他设备上。可以使用Socket等网络通信方式,将屏幕数据实时发送给其他设备,并在接收端进行解码和显示。 除了使用编程方式实现录屏投屏功能,还有一些第三方库和工具可供使用,如Screen Recorder、Mobizen和AirDroid等。这些工具和库可以简化开发过程,并提供更多高级功能,如实时截图、画面编辑和音频传输等。 总而言之,通过Android开发中的Java编程语言,可以实现录屏投屏功能,将设备的屏幕内容实时显示到其他设备上。这对于教育、演示和远程协助等场景都有重要的应用价值。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值