ffmpeg+D3D实现的MFC音视频播放器,支持录像、截图、音视频播放、码流信息显示等功能

news2024/11/17 7:39:03

一、简介

    本播放器是在vs2019 x86下开发,通过ffmpeg实现拉流解码功能,通过D3D实现视频的渲染功能。截图功能采用libjpeg实现,可以截取jpg图片,图片的默认保存路径是在C:\MYRecPath中。录像功能采用封装好的类Mp4Record实现,在Mp4Record类中主要还是采用ffmpeg的相关函数方法进行mp4视频的录制。音频的播放采用DirectSound实现,将ffmpeg解码后的音频数据存储到DirectSound的buffer中,再调用DirectSound的play实现对音频的播放功能。码流信息的显示,通过D3D的文本绘制实现。本播放器提供源码下载,直接下载请点击最后的下载链接。

二、界面展示

在这里插入图片描述

三、相关代码

开始播放

int CVideoPlayer::StartPlay(const char* sUrl)
{
    m_bStop = false;
    m_nVideoIndex = -1;
    m_nAudioIndex = -1;
    int i = 0, res = 0,  nValue = 0;
    char buf[64] = { 0 };
    m_bPlaying = false;
    AVStream* in_stream;
    

    _snprintf_s(m_sConnectUrl, sizeof(m_sConnectUrl), sizeof(m_sConnectUrl) - 1, "%s", sUrl);

    //av_register_all();
    avformat_network_init();

    AVDictionary* optionsDict = nullptr;

    av_dict_set(&optionsDict, "rtsp_transport", "tcp", 0);
    av_dict_set(&optionsDict, "stimeout", "5000000", 0);
    av_dict_set(&optionsDict, "buffer_size", "8192000", 0);
    av_dict_set(&optionsDict, "recv_buffer_size", "8192000", 0);

    m_lastReadPacktTime = av_gettime();
    m_pAVFmtCxt = avformat_alloc_context();
    m_pAVFmtCxt->interrupt_callback.opaque = this;
    m_pAVFmtCxt->interrupt_callback.callback = decodeInterruptCb;

    res = avformat_open_input(&m_pAVFmtCxt, m_sConnectUrl, NULL, &optionsDict);
    if (res < 0)
    {
        myprint("avformat_open_input fail: %d", res);
        return -1;
    }
    
    if (!m_pAVFmtCxt)
    {
        return -1;
    }

    m_pAVFmtCxt->probesize = 100 * 1024;    
    m_pAVFmtCxt->max_analyze_duration = 1 * AV_TIME_BASE; 

    res = avformat_find_stream_info(m_pAVFmtCxt, NULL);
    if (res < 0)
    {
        myprint("error %x in avformat_find_stream_info\n", res);
        return -1;
    }

    av_dump_format(m_pAVFmtCxt, 0, m_sConnectUrl, 0);

    for (i = 0; i < m_pAVFmtCxt->nb_streams; i++)
    {
        if (m_pAVFmtCxt->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            m_nVideoIndex = i;
        }
        else if (m_pAVFmtCxt->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
            m_nAudioIndex = i;
        }

        myprint("m_pAVFmtCxt->streams[i]->codec->codec_type:%d", m_pAVFmtCxt->streams[i]->codecpar->codec_type);

    }

    //videoindex not find
    if (m_nVideoIndex == -1)
    {
        myprint("can't find video stream.");
        return -1;
    }

    m_pCodec = avcodec_find_decoder(m_pAVFmtCxt->streams[m_nVideoIndex]->codecpar->codec_id);
    if (!m_pCodec)
    {
        myprint("video decoder not found\n");
        return -1;
    }
    if (m_bSupportAudio && m_nAudioIndex != -1)
    {
        myprint("start audio decoder \n");

        if (!m_pAudioCodecCxt)
            m_pAudioCodecCxt = avcodec_alloc_context3(NULL);
        auto pAudioCodecpar = m_pAVFmtCxt->streams[m_nAudioIndex]->codecpar;
        avcodec_parameters_to_context(m_pAudioCodecCxt, pAudioCodecpar);

        m_pAudioCodec = avcodec_find_decoder(pAudioCodecpar->codec_id);

        if (nullptr == m_pAudioCodec || nullptr == m_pAudioCodecCxt)
        {
            myprint("audio decoder not found\n");
            return -1;
        }

        m_pSwrContext = swr_alloc_set_opts(0,                                 
            av_get_default_channel_layout(m_channels_play),
            AV_SAMPLE_FMT_S16,                         
            m_nSampleRate,                     
            av_get_default_channel_layout(m_pAudioCodecCxt->channels),
            m_pAudioCodecCxt->sample_fmt,       
            m_pAudioCodecCxt->sample_rate,      
            0,
            0);
        auto ret = swr_init(m_pSwrContext);
        if (ret < 0)
        {
            myprint("Failed to swr_init(pSwrContext);");
            return -1;
        }

        if (InitDirectSound() == FALSE)
            m_bSupportAudio = false;
    }

    m_CodecId = m_pCodec->id;
    if(!m_pCodecCxt)
        m_pCodecCxt = avcodec_alloc_context3(NULL);
    avcodec_parameters_to_context(m_pCodecCxt, m_pAVFmtCxt->streams[m_nVideoIndex]->codecpar);
    if (m_pCodecCxt)
    {
        if (m_pCodecCxt->width == 0 || m_pCodecCxt->height == 0)
        {
            myprint("m_pCodecCxt->width:%d, m_pCodecCxt->height:%d", m_pCodecCxt->width, m_pCodecCxt->height);
            return -1;
        }
    }
    else
        return -1;

    AVCodecContext* temp_codecctx = m_pCodecCxt;
    memcpy(temp_codecctx, m_pCodecCxt, sizeof(m_pCodecCxt));
    if (m_pCodecCxt->codec_type == AVMEDIA_TYPE_VIDEO)
    {
        myprint("Soft Solution");
        avcodec_close(m_pCodecCxt);
        m_pCodecCxt = temp_codecctx;
        m_pCodecCxt->thread_count = 4;
        if (m_Dxva2D3DRender.InitD3DRender(m_showWnd, m_pCodecCxt->width, m_pCodecCxt->height) == false)
        {
            myprint("InitD3DRender fail");
        }
        m_pOutBuffer = (uint8_t*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, m_pCodecCxt->width, m_pCodecCxt->height, 1));
        if (nullptr == m_pOutBuffer)
            return -1;

        av_image_fill_arrays(m_pFrameBGR->data, m_pFrameBGR->linesize, m_pOutBuffer, AV_PIX_FMT_YUV420P, m_pCodecCxt->width, m_pCodecCxt->height, 1); //填充AVFrame数据缓冲
        m_pImgConvertCtx = sws_getContext(m_pCodecCxt->width, m_pCodecCxt->height, m_pCodecCxt->pix_fmt, m_pCodecCxt->width, m_pCodecCxt->height, AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR, NULL, NULL, NULL);
        if (nullptr == m_pImgConvertCtx)
            return -1;

      
        m_nActualWidth = m_pCodecCxt->width;
        m_nActualHeight = m_pCodecCxt->height;

        res = avcodec_open2(m_pCodecCxt, m_pCodec, NULL);
        if (res < 0)
        {
            myprint("avcodec_open2 video fail  error:%x", res);
            return -1;
        }
    }

    if (m_bSupportAudio && m_pAudioCodecCxt)
    {
        if (m_pAudioCodecCxt->codec_type == AVMEDIA_TYPE_AUDIO)
        {
            res = avcodec_open2(m_pAudioCodecCxt, m_pAudioCodec, NULL);
            if (res < 0)
            {
                myprint("avcodec_open2 audio fail  error:%x", res);
                avcodec_close(m_pAudioCodecCxt);
                return -1;
            }

            myprint("===Audio Message===");
            myprint(" bit_rate = %d ", m_pAudioCodecCxt->bit_rate);
            myprint(" sample_rate = %d ", m_pAudioCodecCxt->sample_rate);
            myprint(" channels = %d ", m_pAudioCodecCxt->channels);
            myprint(" code_name = %s ", m_pAudioCodecCxt->codec->name);
            myprint(" block_align = %d ", m_pAudioCodecCxt->block_align);
        }
    }

    m_pDecodeThread = (my_thread_t*)my_malloc(sizeof(my_thread_t));
    if (nullptr != m_pDecodeThread)
    {
        m_bDecodeThreadRun = true;
        res = my_thread_create(m_pDecodeThread, ThreadDecode, this);
        if (res == -1)
        {
            myprint("my_thread_create ThreadDecode failed  res:%x", res);
            return -1;
        }
    }

    return 0;
}

停止播放

void CVideoPlayer::StopPlay()
{
    m_bPlaying = false;
    m_CaptureAudio.SetGrabAudioFrames(FALSE, NULL);
    m_CaptureAudio.Close();

    m_bStopAudio = true;
    while (!m_AudioPlayQue.empty())
    {
        m_AudioPlayQue.pop();
    }
    while (!m_AudioTalkQue.empty())
    {
        EnterCriticalSection(&m_talklock);
        m_AudioTalkQue.pop();
        LeaveCriticalSection(&m_talklock);
    }

    m_bDecodeThreadRun = false;

    if (m_pDecodeThread)
    {
        my_thread_join(m_pDecodeThread);
        my_free(m_pDecodeThread);
        m_pDecodeThread = nullptr;
    }

    if (m_pAudioPlayThread) {
        SetEvent(m_event);
        if (m_pAudioPlayThread->handle) {
            my_thread_join(m_pAudioPlayThread);
            m_pAudioPlayThread->handle = nullptr;
        }
    }

    if (m_pDSBuffer8)
    {
        m_pDSBuffer8->Stop();
        m_pDSBuffer8->Restore();
    }

    m_Dxva2D3DRender.UnitD3DRender();

    if (m_pCodecCxt)
    {
        avcodec_close(m_pCodecCxt);
    }

    if (m_pAudioCodecCxt)
    {
        avcodec_close(m_pAudioCodecCxt);
    }

    if (m_pSwrContext)
    {
        swr_free(&m_pSwrContext);
        m_pSwrContext = nullptr;
    }

    if (m_pAVFmtCxt) {
        avformat_close_input(&m_pAVFmtCxt);
        avformat_free_context(m_pAVFmtCxt);
        m_pAVFmtCxt = nullptr;
    }

}

解码线程

void CVideoPlayer::DecodeAndShow()
{
    if (m_pAVFmtCxt == nullptr || m_pCodecCxt == nullptr)
        return;

    AVPacket pkt = { 0 };
    m_bPlaying = true;
    uint8_t* pBuffer;
    bool bEnoughSpace = true;
    int nTimeCnt = 0;
    int res = 0;
    struct SwsContext* img_convert_ctx = nullptr;
    int nRectDrawWait = 0;
    bool bRecordLastIFrame = false;
    int num_av_read_frame_err = 0;
    int num_stream_index_err = 0;
    uint8_t * outData[2] = {0};
    outData[0] = (uint8_t*)av_malloc(1152 * 8);
    outData[1] = (uint8_t*)av_malloc(1152 * 8);

    uint8_t* pktdata;
    int pktsize;
    int len = 0;
    bool bPushAudioToQueue = false;
    m_bStopAudio = false;
    CRect ShowRect;

    AVFrame* pAvFrame = av_frame_alloc();
    if (nullptr == pAvFrame)
        return;

    AVFrame* pFrameRGB = av_frame_alloc();
    if (nullptr == pFrameRGB)
        return;

    int numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, m_pCodecCxt->width, m_pCodecCxt->height, 1);
    pBuffer = (uint8_t*)av_malloc(numBytes);
    if (nullptr == pBuffer)
        return;

    av_image_fill_arrays(pFrameRGB->data,pFrameRGB->linesize, pBuffer, AV_PIX_FMT_RGB24, m_pCodecCxt->width, m_pCodecCxt->height, 1);
    img_convert_ctx = sws_getCachedContext(img_convert_ctx, m_pCodecCxt->width, m_pCodecCxt->height,
        m_pCodecCxt->pix_fmt, m_pCodecCxt->width, m_pCodecCxt->height, AV_PIX_FMT_RGB24, SWS_FAST_BILINEAR/*SWS_BICUBIC*/, NULL, NULL, NULL);


    //Audio
    if (m_bSupportAudio && m_pAudioPlayThread)
    {
        res = my_thread_create(m_pAudioPlayThread, ThreadAudioPlay, this);
        if (res < 0)
            myprint("my_thread_create ThreadAudioPlay fail");
    }

    while (m_bDecodeThreadRun && !m_bQuit)
    {
        if (m_bPause)
        {
            Sleep(100);
            continue;
        }

        {
            if (m_bReconnect)
            {
                myprint("bReConnect = true, break");
                break;
            }
        }

        m_lastReadPacktTime = av_gettime();
        if (av_read_frame(m_pAVFmtCxt, &pkt) >= 0)
        {
            num_av_read_frame_err = 0;

            if (pkt.stream_index == m_nVideoIndex || pkt.stream_index == m_nAudioIndex)
            {
                if (m_bRecord)//Record
                {
                    if (nTimeCnt != 0 || (!bRecordLastIFrame && pkt.flags == AV_PKT_FLAG_KEY)) {
                        if (m_sRecPath[0] != '\0' && nTimeCnt++ % 200 == 0)
                        {
                            bEnoughSpace = CheckRemainSpace(m_sRecPath);
                            if (bEnoughSpace == true)
                            {
                                myprint("bEnoughSpace = true");
                            }
                            else
                                myprint("bEnoughSpace = false");
                        }

                        m_nRecordCurrentTime = time(NULL);
                        if ((m_nRecordCurrentTime - m_nRecordStartTime) >= (m_nRecordTime * 60))
                        {
                            myprint("Record Finsh!");
                            stopRecord();
                        }
                        else if (bEnoughSpace == false)
                        {
                            myprint("bEnoughSpace == false");
                            stopRecord();
                        }
                        else
                        {
                            AVPacket* pPkt = av_packet_clone(&pkt);
                            m_mp4Recorder.saveOneFrame(*pPkt, m_CodecId);
                            av_packet_free(&pPkt);
                        }
                    }
                    bRecordLastIFrame = pkt.flags == AV_PKT_FLAG_KEY;
                }
                else
                    nTimeCnt = 0;
            }

            
            if (pkt.stream_index == m_nVideoIndex)
            {
                num_stream_index_err = 0;
                nTimeCnt = 0;

                if (pkt.flags == 1)
                    bPushAudioToQueue = true;
                if (nullptr == m_pCodecCxt || nullptr == pAvFrame) {
                    myprint("m_pCodecCxt == NULL || pAvFrame == NULL");
                    break;
                }
                int gotvframe = 0;
                auto sd_ret = avcodec_send_packet(m_pCodecCxt, &pkt);
                if (sd_ret != 0 && sd_ret != AVERROR(EAGAIN)) {
                    myprint("avcodec_send_packet err, rt=%d", sd_ret);
                    enableReConnect();
                }
                else {
                    while (gotvframe == 0 && !m_bQuit) {
                        gotvframe = avcodec_receive_frame(m_pCodecCxt, pAvFrame);
                        if (gotvframe == 0)
                        {
                            try
                            {
                                GetShowRectSize(&ShowRect);
                            }
                            catch (const std::exception&)
                            {
                                myprint("GetClientRect throw, error");
                                break;
                            }

                            m_nCurPKSize = pkt.size;   
                            SetStreamInfoToD3d();

                            if (pAvFrame->width != m_nActualWidth || pAvFrame->height != m_nActualHeight)
                            {
                                myprint("video size change reconnect...");
                                enableReConnect();
                                m_nActualWidth = pAvFrame->width;
                                m_nActualHeight = pAvFrame->height;
                                av_packet_unref(&pkt);
                                continue;
                            }

                            if (m_pImgConvertCtx && m_pFrameBGR && m_pOutBuffer && pAvFrame)
                            {
                                sws_scale(m_pImgConvertCtx, (const uint8_t* const*)pAvFrame->data, pAvFrame->linesize, 0,
                                    m_pCodecCxt->height, m_pFrameBGR->data, m_pFrameBGR->linesize);

                                {                                    
                                    try
                                    {
                                        int re = 5;
                                        for (int i = 0; m_bPlaying && re == 5 && i < 10; ++i) {     // LockRect失败时重复尝试,最多10次
                                            re = m_Dxva2D3DRender.D3DSoftDisplayFrame(m_pOutBuffer, pAvFrame->width, pAvFrame->height, ShowRect);
                                            Sleep(1);
                                        }
                                    }
                                    catch (int re)
                                    {
                                        myprint("m_Dxva2D3DRender.InitD3DRender again");
                                        if (m_Dxva2D3DRender.InitD3DRender(m_showWnd, m_pCodecCxt->width, m_pCodecCxt->height) == false)
                                        {
                                            myprint("m_Dxva2D3DRender.InitD3DRender again fail");
                                            av_packet_unref(&pkt);
                                            continue;
                                        }
                                    }
                                }                                
                            }
                            if (m_bCapture /*&& pkt.flags == 1*/ && img_convert_ctx)
                            {
                                sws_scale(img_convert_ctx, (const uint8_t* const*)pAvFrame->data, 
                                         pAvFrame->linesize, 0, m_pCodecCxt->height,
                                    pFrameRGB->data, pFrameRGB->linesize);
                                SaveIFrameImage(pFrameRGB->data[0], m_pCodecCxt->width, m_pCodecCxt->height);
                                m_bCapture = false;
                            }
                            
                        }
                    }
                }
            }
            else if (pkt.stream_index == m_nAudioIndex)
            {
                num_stream_index_err = 0;
                if (m_bSupportAudio) {
                    pktdata = pkt.data;
                    pktsize = pkt.size;

                    if (pktsize > 0)
                    {
                        int gotframe = 0;
                        if (nullptr == m_pAudioCodecCxt || nullptr == pAvFrame) {
                            myprint("m_pAudioCodecCxt == NULL || pAvFrame == NULL");
                            break;
                        }
                        len = avcodec_send_packet(m_pAudioCodecCxt, &pkt);
                        if (len != 0 && len != AVERROR(EAGAIN))
                        {
                            pktsize = 0;
                            myprint("avcodec_send_packet len < 0");
                            break;
                        }
                        auto data_size = av_get_bytes_per_sample(m_pAudioCodecCxt->sample_fmt); 
                        if (data_size < 0) {
                            myprint("Failed to calculate data size\n");
                            break;
                        }
                        while (gotframe == 0 && !m_bQuit) {
                            gotframe = avcodec_receive_frame(m_pAudioCodecCxt, pAvFrame);
                            if (!gotframe)
                            {

                                if (bPushAudioToQueue == true && m_bEnableAudio && !m_bStopAudio)
                                {
                                    audio_frame_t audioFrame;
                                    numBytes = av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);
                                    auto dstNbSamples = av_rescale_rnd(pAvFrame->nb_samples,
                                        m_src_sample_rate,
                                        pAvFrame->sample_rate,
                                        AV_ROUND_ZERO);
                                      
                                    int data_size = 0;
                                    try
                                    {
                                        auto nb = swr_convert(m_pSwrContext,
                                            (uint8_t**)outData,
                                            dstNbSamples,
                                            (const uint8_t**)pAvFrame->data,
                                            pAvFrame->nb_samples);
                                        data_size = av_samples_get_buffer_size(nullptr, m_channels_play, nb, AV_SAMPLE_FMT_S16, 1);
                                    }
                                    catch (const std::exception&)
                                    {
                                        m_bSupportAudio = false;
                                        myprint("swr_convert throw err, set m_bSupportAudio false");
                                        continue;
                                    }
                                    
                                    int copy_size = 0; 
                                    int copy_ptr = 0;                              
                                    for (int isub = data_size; isub > 0; isub -= copy_size) {
                                        if (isub > m_audio_buffer_notify_size) {
                                            copy_size = m_audio_buffer_notify_size;
                                            copy_ptr = data_size - isub;
                                        }
                                        else
                                            copy_size = isub;
                                        audioFrame.data_size = copy_size;
                                        memcpy(audioFrame.data, outData[0] + copy_ptr, copy_size);
                                        EnterCriticalSection(&m_lock);
                                        m_AudioPlayQue.push(audioFrame);
                                        LeaveCriticalSection(&m_lock);
                                    }
                                }

                            }
                        }
                    }
                }
            }
            else if (++num_stream_index_err > 20) {
                myprint("pkt.stream_index unfind, %d",pkt.stream_index);
                enableReConnect();
            }

            av_packet_unref(&pkt);
        }
        else {
            if (++num_av_read_frame_err > 10) {
                myprint("num_av_read_frame_err is more than 10");
                enableReConnect();
            }
        }
    }
    if (m_bDecodeThreadRun) {
        myprint("m_bDecodeThreadRun is true");
        enableReConnect();
    }

    if (pAvFrame)
        av_free(pAvFrame);

    if (pFrameRGB)
        av_free(pFrameRGB);

    if (pBuffer)
        av_free(pBuffer);

    if (img_convert_ctx)
        sws_freeContext(img_convert_ctx);

    if (outData[0] && outData[1])
    {
        av_free(outData[0]);
        av_free(outData[1]);
        outData[0] = 0;
        outData[1] = 0;
    }
}

四、相关下载

链接: 可执行程序下载

链接: 源码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2242033.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot 之 整合springdoc2.6 (swagger 3)

版本 springboot 3.3.5 jdk 17 springdoc 2.6.0 依赖pom <dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId><version>2.6.0</version> </dependency>注解对比…

ADS学习笔记 5. 微带天线设计

基于ADS2023 update2 参考书籍&#xff1a;卢益锋老师《ADS射频电路设计与仿真学习笔记》 更多笔记&#xff1a;ADS学习笔记 1. 功率放大器设计ADS学习笔记 2. 低噪声放大器设计ADS学习笔记 3. 功分器设计ADS学习笔记 4. 微带分支定向耦合器设计 目录 0、设计指标 1、微带…

TypeORM在Node.js中的高级应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 TypeORM在Node.js中的高级应用 TypeORM在Node.js中的高级应用 TypeORM在Node.js中的高级应用 引言 TypeORM 基本概念 1. 实体&am…

【软件测试】一个简单的自动化Java程序编写

文章目录 自动化自动化概念回归测试常见面试题 自动化测试金字塔 Web 自动化测试驱动 Selenium一个简单的自动化示例安装 selenium 库使⽤selenium编写代码 自动化 自动化概念 自动的代替人的行为完成操作。自动化在生活中处处可见 生活中的自动化可以减少人力的消耗&#x…

【云岚到家】-day10-2-冷热处理及统计

【云岚到家】-day10-2-冷热处理及统计 3.7 历史订单3.7.1 冷热分离方案1&#xff09;冷热分离需求2&#xff09;分布式数据库3&#xff09;冷热分离方案 3.7.2 订单同步1&#xff09;创建历史订单数据库2&#xff09;订单同步3&#xff09;测试订单同步4&#xff09;小结 3.7.3…

Python学习------第八天

函数 函数的传入参数 掌握函数返回值的作用 掌握函数返回值的定义语法 函数的嵌套调用&#xff1a; 函数的局部变量和全局变量 局部变量的作用&#xff1a;在函数体内部&#xff0c;临时保存数据&#xff0c;即当函数调用完成后&#xff0c;则销毁局部变量。 money 5000000 n…

新人如何做好项目管理?|京东零售技术人成长

“管理是一种实践&#xff0c;其本质不在于知&#xff0c;而在于行”——彼得德鲁克 作为一名初入职场的校招生&#xff0c;你是否有过这样的疑问&#xff1a;项目经理究竟扮演着怎样的角色&#xff1f;是老板的传声筒&#xff0c;单纯地传达上级的指令&#xff1f;还是团队的…

MySQL社区版的启动与连接

1.启动&#xff1a; 注意&#xff1a;MySQL是默认开机自启的 方式一&#xff1a; 1.WinR 的命令行中直接输入services.msc 2.在服务中找到数据库名称&#xff0c;然后鼠标右键点击启动 方式二&#xff1a; 1.在开始选项中搜索“cmd”命令提示符&#xff0c;使用管理员身份运行 …

FFmpeg 4.3 音视频-多路H265监控录放C++开发十四,总结编码过程,从摄像头获得数据后,转成AVFrame,然后再次转成AVPacket,

也就是将摄像头采集到的YUV 的数据换成 AVFrame&#xff0c;然后再次转成 AVPacket&#xff0c;那么这AVPakcet数据要怎么办呢&#xff1f;分为三种情况&#xff1a; 一种是将AVPacket存储成h264文件&#xff0c;由于h264编码器在将avframe变成avpacket的时候就是按照h264的格…

TCP(下):三次握手四次挥手 动态控制

欢迎浏览高耳机的博客 希望我们彼此都有更好的收获 感谢三连支持! TCP(上)&#xff1a;成熟可靠的传输层协议-CSDN博客 &#x1f95d;在上篇博客中&#xff0c;我们针对TCP的特性,报文结构,连接过程以及相对于其他协议的区别进行了探讨&#xff0c;提供了初步的理解和概览。本…

24 年第十届数维杯国际数模竞赛赛题浅析

本次万众瞩目的数维杯国际大学生数学建模赛题已正式出炉&#xff0c;无论是赛题难度还是认可度&#xff0c;该比赛都是数模届的独一档&#xff0c;含金量极高&#xff0c;可以用于综测加分、保研、简历添彩等各方面。考虑到大家解题实属不易&#xff0c;为了帮助大家取得好成绩…

菲涅耳全息图

菲涅耳全息图&#xff1a;记录介质在物光波场的菲涅耳衍射区(物体到记录介质表面的距离在菲涅耳衍射区内)。 一、点源全息图的记录和再现 1.1 记录 设物光波和参考光波是从点源O(xo, yo, zo)和点源 R(xr, yr, zr)发出的球面波, 波长为λ1, 全息底片位于z0 的平面上, 与两个点源…

Pygame坦克大战游戏开发实验报告

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

微搭低代码入门05循环

目录 1 for 循环2 while 循环3 do...while 循环4 break 语句5 循环展示组件总结 在编程中&#xff0c;循环是一种非常强大的控制结构&#xff0c;它允许我们重复执行一段代码直到满足某个条件为止。在微搭中&#xff0c;我们一般用循环来处理我们数据库返回的结果。 在微搭中&a…

C++:基于红黑树封装map和set

目录 红黑树的修改 红黑树节点 红黑树结构 红黑树的迭代器 红黑树Insert函数 红黑树的默认成员函数 修改后完整的红黑树 set、map的模拟实现 set map 测试封装的set和map 红黑树的修改 想要用红黑树封装map和set&#xff0c;需要对之前实现的key-value红黑树进行修…

【深度学习基础 | 预备知识】数据预处理

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈PyTorch深度学习 ⌋ ⌋ ⌋ 深度学习 (DL, Deep Learning) 特指基于深层神经网络模型和方法的机器学习。它是在统计机器学习、人工神经网络等算法模型基础上&#xff0c;结合当代大数据和大算力的发展而发展出来的。深度学习最重…

前端面试笔试(四)

目录 一、数据结构算法等综合篇 1.线性探查法解决哈希冲突 2.请求分页系统中文件区和对换区 3.RADIUS认证协议&#xff0c;运行在哪个网络协议上 二、代码输出篇 1.res[1,2,100].map(parseInt) 如果我们想要输出为[1,2,100]&#xff0c;可以&#xff1a; 还可以换map里…

从零开始学习 sg200x 多核开发之 milkv-duo256 编译运行 sophpi

sophpi 是 算能官方针对 sg200x 系列的 SDK 仓库 https://github.com/sophgo/sophpi &#xff0c;支持 cv180x、cv81x、sg200x 系列的芯片。 SG2002 简介 SG2002 是面向边缘智能监控 IP 摄像机、智能猫眼门锁、可视门铃、居家智能等多项产品领域而推出的高性能、低功耗芯片&a…

【客户服务】互联网时代客户投诉处理金点子

互联网时代客户投诉新特点 客户投诉渠道广投诉的内容涉及到企业的各个方面客户维权意识越来越强负面效应很难管 卓越客户体验成为企业核心竞争力 移动互联网与社会化媒体背景下&#xff0c;客户的全方位感知、情感、卓越体验、高效需求成为驱动技术、应用、终端以及服务持续…

SQL 审核在 CloudQuery 的四大场景应用

数据库作为数据的核心载体&#xff0c;其安全性和稳定性对业务的影响至关重要。而在我们日常业务中&#xff0c;SQL 编写不当是引起数据库故障的一个重要原因&#xff0c;轻则影响数据库性能&#xff0c;重则可能直接导致「雪崩」。因此&#xff0c;SQL 审核作为 SQL 代码投入生…