智能指针处理---bo

// sdltest1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
extern "C"
{
    #include <SDL.h>
    #include "libavutil/opt.h"
    #include "libavutil/channel_layout.h"
    #include "libavutil/common.h"
    #include "libavutil/imgutils.h"
    #include "libavutil/mathematics.h"
    #include "libavutil/samplefmt.h"
    #include "libavutil/time.h"
    #include "libavutil/fifo.h"
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    #include "libavformat/avio.h"
    #include "libavfilter/avfiltergraph.h"
    #include "libavfilter/avfilter.h"
    #include "libavfilter/buffersink.h"
    #include "libavfilter/buffersrc.h"
    #include "libswscale/swscale.h"
    #include "libswresample/swresample.h"
}
#include <memory>
#include <vector>
#include <windows.h>
#include <thread>
#include <mutex>
#include <queue>
#include <iostream>
#include "sdlplayer.h"

#pragma comment(lib, "avcodec.lib")

bool saveAsBitmap(AVFrame *pFrameRGB, int width, int height, int iFrame);


//int mymain();
//extern "C" _declspec(dllexport) int mymain();
int mymain(char* file);
//int _tmain(int argc, _TCHAR* argv[])
int main(int argc, char* argv[])
{
    printf("come this -->\n");
    if(argc!=2) {
        printf("Args count not right!\n");
        //return 0;
    }


    printf("%s \n",(char*)argv[1]);
    mymain((char*)argv[1]);
    //mymain();
    return 0;
}



AVInputFormat mFormat;
AVDictionary* iformat_opts;
using namespace std;
#define INBUF_SIZE 4096
int videoIndex;
#define DelayTime 5
void Init()
{
    av_register_all();
    avfilter_register_all();
    avformat_network_init();
    av_log_set_level(AV_LOG_ERROR);
}
AVFormatContext *ic = NULL;
int64_t lastReadPacktTime ;
std::shared_ptr <AVPacket> readPacketFromSource()
{
    std::shared_ptr<AVPacket> packet(static_cast<AVPacket*>(av_malloc(sizeof(AVPacket))), [&](AVPacket *p) { av_packet_free(&p); av_freep(&p);});
    av_init_packet(packet.get());
    lastReadPacktTime = av_gettime();
    int ret = av_read_frame(ic, packet.get());
    if(ret >= 0)
    {
        return packet;
    }
    else
    {
        return nullptr;
    }

}    
bool videoDecode(AVPacket* packet, AVFrame *frame)
{
    int gotFrame = 0;
    //videoIndex
    auto hr = avcodec_decode_video2(ic->streams[videoIndex]->codec, frame, &gotFrame, packet);
    if (hr >= 0 && gotFrame != 0)
    {
        return true;
    }
    return false;
}


int initVideoDecodeContext()
{    
    auto codecId = ic->streams[videoIndex]->codec->codec_id;
    auto codec = avcodec_find_decoder(codecId);
    if (!codec)
    {
        return -1;
    }

    int ret = avcodec_open2(ic->streams[videoIndex]->codec, codec, NULL);
    return ret;

}



static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize,
                     char *filename)
{
    FILE *f;
    int i;
    printf("filename = %s\n",filename);
    f = fopen(filename,"w");
    fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
    for (i = 0; i < ysize; i++)
        fwrite(buf + i * wrap, 1, xsize, f);
    fclose(f);
}

int gWidth = 0;
int gHeight = 0;

int linesize[5] = { 640,320,320,0,0 };



typedef struct  {
    //BYTE  buf[640*360*3/2+100];
    std::shared_ptr<BYTE> buf;
    BYTE*    data[3];
    int64_t  dts;
} DecodeFrame;

//queue<DecodeFrame*> queFrame;


queue<std::shared_ptr<DecodeFrame>> queFrame;

int playState = 1;
std::shared_ptr<CGSDLRender> sdlRender;
mutex g_lock;
int64_t lastDts=0;
unsigned long lastTime = 0;



void playFun(){
    
    for(;;){
        if(playState == 0) break;
        if (queFrame.size()>0){

            g_lock.lock();
            //DecodeFrame* dfr= queFrame.front();
            std::shared_ptr<DecodeFrame> dfr= queFrame.front();

            queFrame.pop();
            g_lock.unlock();
            auto diff = dfr->dts - lastDts;
            int duration = diff * 1000 /(ic->streams[videoIndex]->time_base.den
                        /ic->streams[videoIndex]->time_base.num);
            if(duration > DelayTime && duration < 1000){
                Sleep(duration );
            }

            std::cout<<"duration1: "<<duration<<endl;

            printf("packet->dts time =%d --->\n ", dfr->dts * 1000 / (ic->streams[videoIndex]->time_base.den
                / ic->streams[videoIndex]->time_base.num));

            sdlRender->Display((char**)dfr->data,linesize);
            lastDts = dfr->dts;
            unsigned long nowTime = GetTickCount();
            printf(" %ld cha  %ld\n",nowTime,nowTime-lastTime); //得到ms
            lastTime = nowTime;
            //delete dfr;
            
        }else{
            Sleep(150);
        }
    }
}


int mymain(char* file)
{
    int scan_all_pmts_set = 0;
    /* register all codecs, demux and protocols */
    Init();
    ic = avformat_alloc_context();
    int ret;
    if (!ic) {
        av_log(NULL, AV_LOG_FATAL, "Could not allocate context.\n");
        ret = AVERROR(ENOMEM);
        printf("alloc err %d\n",ret);
    }

    int err = avformat_open_input(&ic, "F://test.mp4", nullptr, nullptr);
    //int err = avformat_open_input(&ic, "F://3s.mp4", nullptr, nullptr);
    if (err < 0) {
        printf("open err err=%d\n",err);
    }
    printf("come 2\n");

    err = avformat_find_stream_info(ic, nullptr);
    printf("ic->nb_streams %d\n",ic->nb_streams);
    if(err<0){

    }else{
        for(int i=0;i<ic->nb_streams;i++){
            int type =  ic->streams[i]->codec->codec_type;
            printf("type = %d\n",type);
            if(type == AVMediaType::AVMEDIA_TYPE_VIDEO){
                videoIndex  = i;
                printf("videoIndex =%d \n",videoIndex);
            }
        }                                        
    }

    gWidth = ic->streams[videoIndex]->codec->width;
    gHeight = ic->streams[videoIndex]->codec->height;

    int ret1 =initVideoDecodeContext();
    printf("ret1 = %d\n",ret1);
    //std::shared_ptr<CGSDLRender>
        sdlRender =std::make_shared<CGSDLRender>();//???????
    ret = initVideoDecodeContext();
    if(ret < 0) return ret;
    sdlRender->InitVideo(0);

    sdlRender->CreateVideoSurface(gWidth, gHeight);
    AVRational time_base =ic->streams[videoIndex]->time_base;
    printf("num %d,den %d--\n",time_base.num,time_base.den);
    // to thi
    playState = 1;
    thread t1(playFun);
    t1.detach();
    int64_t lastDts=0;

    int w = gWidth;
    int h = gHeight;
    AVFrame * videoFrame = av_frame_alloc();
    for(int i=0;i<10000;i++){
        auto packet = readPacketFromSource();
        if(packet){
            if(packet->stream_index==videoIndex){
                
                if(videoDecode(packet.get(),videoFrame))
                {

                    printf("%d---\n",i);
                    //printf("%lld \n",videoFrame->pkt_pos );

                    //DecodeFrame* dfr=&arrFrame[decodeFrame];
                    //DecodeFrame* dfr = new DecodeFrame;
                    std::shared_ptr<DecodeFrame> dfr(static_cast<DecodeFrame*>( new DecodeFrame), [&](DecodeFrame *p) { delete p;});

                     std::shared_ptr<BYTE> tmpbuf (new BYTE[w * h * 3 / 2 + 100](), std::default_delete<BYTE[]>());
                     dfr->buf = tmpbuf;

                    memcpy(dfr->buf.get(),videoFrame->data[0],w*h);
                    memcpy(dfr->buf.get() + w * h, videoFrame->data[1], w * h / 4);
                    memcpy(dfr->buf.get() + w * h * 5 / 4, videoFrame->data[2], w * h / 4);
                    dfr->data[0] = dfr->buf.get();
                    dfr->data[1] = dfr->buf.get() + w * h;
                    dfr->data[2] = dfr->buf.get() + w * h * 5 / 4;
                    dfr->dts = packet->dts;


                    g_lock.lock();
                    queFrame.push(dfr);
                    g_lock.unlock();
                    printf("packet->dts time =%d <---\n ",dfr->dts*1000/(ic->streams[videoIndex]->time_base.den
                    /ic->streams[videoIndex]->time_base.num));
                    if(queFrame.size()>30)
                            Sleep(100);

                }
            }
        }
        else{
            break;
        }
    }

    av_frame_free(&videoFrame);
    //playFun();
    Sleep(8000);
    playState = 0;
    Sleep(600);
    system("PAUSE");
    
    return 0;
}

 

posted @ 2021-09-30 15:17  cnchengv  阅读(27)  评论(0编辑  收藏  举报