1

#include "stdafx.h"
#include <stdio.h>
#include  "directSound.h"
#include "decodeUnit.h"
#include "d3dhead.h"


#pragma comment(lib, "d3d9.lib")  
extern  HWND gd3wnd;


void DecodeUnit::Init()
{
    av_register_all();
    avfilter_register_all();
    avformat_network_init();
    av_log_set_level(AV_LOG_ERROR);
    ic = NULL;
}

std::shared_ptr <AVPacket> DecodeUnit::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 DecodeUnit::videoDecode(AVPacket* packet, AVFrame *frame)
{
    int gotFrame = 0;
    //videoIndex
    auto hr = avcodec_decode_video2(ic->streams[videoIndex]->codec, frame, &gotFrame, packet);

    int pmt = ic->streams[videoIndex]->codec->pix_fmt;
    if (hr >= 0 && gotFrame != 0)
    {
        return true;
    }
    return false;
}

int DecodeUnit::initVideoDecodeContext()
{
    if (videoIndex < 0) return -1;

    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;

}


int DecodeUnit::initAudioDecodeContext()
{
    if (audioIndex < 0) return -1;
    auto codecId = ic->streams[audioIndex]->codec->codec_id;
    auto codec = avcodec_find_decoder(codecId);
    if (!codec)
    {
        return -1;
    }

    int ret = avcodec_open2(ic->streams[audioIndex]->codec, codec, NULL);
    if (ret < 0) return ret;

    if (ic->streams[audioIndex]->codec->sample_fmt != AV_SAMPLE_FMT_S16)
    {
        swr = swr_alloc();
        av_opt_set_int(swr, "in_channel_layout", ic->streams[audioIndex]->codec->channel_layout, 0);
        av_opt_set_int(swr, "out_channel_layout", ic->streams[audioIndex]->codec->channel_layout, 0);
        av_opt_set_int(swr, "in_sample_rate", ic->streams[audioIndex]->codec->sample_rate, 0);
        av_opt_set_int(swr, "out_sample_rate", ic->streams[audioIndex]->codec->sample_rate, 0);
        av_opt_set_sample_fmt(swr, "in_sample_fmt", ic->streams[audioIndex]->codec->sample_fmt, 0);
        av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
        swr_init(swr);
    }
    return ret;
}


bool DecodeUnit::audioDecode(AVPacket* packet, AVFrame *frame)
{
    int gotFrame = 0;
    auto hr = avcodec_decode_audio4(ic->streams[audioIndex]->codec, frame, &gotFrame, packet);
    if (hr >= 0 && gotFrame != 0)
    {
        return true;
    }
    return false;
}

#define MAX_AUDIOBUFF_LEN 192000*128
//BYTE* gAudioBuf[MAX_AUDIOBUFF_LEN];
BYTE gAudioBuf[MAX_AUDIOBUFF_LEN];
DWORD gAudioBufUsed = 0;
DWORD gAudioBufOffset = 0;
int DecodeUnit::InitMainExe(char* spath) {

    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.
");
        ret = AVERROR(ENOMEM);
        printf("alloc err %d
", ret);

    }
    /*
    if (!av_dict_get(iformat_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
    av_dict_set(&iformat_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
    scan_all_pmts_set = 1;
    }
    */
    int err = avformat_open_input(&ic, spath, nullptr, nullptr);
    if (err < 0) {
        printf("open err err=%d
", err);
    }
    printf("come 2
");

    ret = avformat_find_stream_info(ic, nullptr);
    if (ret < 0)
    {
        av_log(NULL, AV_LOG_ERROR, "Find input file stream inform failed
");
    }
    else
    {
        for (int i = 0; i < ic->nb_streams; i++)
        {
            if (ic->streams[i]->codec->codec_type == AVMediaType::AVMEDIA_TYPE_VIDEO)
            {
                videoIndex = i;
            }
            else if (ic->streams[i]->codec->codec_type == AVMediaType::AVMEDIA_TYPE_AUDIO)
            {
                audioIndex = i;
                initDsAudio(ic->streams[audioIndex]->codec->sample_rate, ic->streams[audioIndex]->codec->channels);
                //std::thread t(playDsAudio);
                //t.detach();
            }
        }
        //playState = CGPlayState::POpen;
        //av_log(NULL, AV_LOG_FATAL, "Open input file  %s success
", inputUrl.c_str());
    }

    
    int reta = initAudioDecodeContext();
    
    


    int ret1 = initVideoDecodeContext();
    printf("ret1  %d, reta %d
", ret1, reta);
    //std::shared_ptr<CGSDLRender> sdlRender = std::make_shared<CGSDLRender>();//???????

    if (videoIndex >= 0){ 
        int w = ic->streams[videoIndex]->codec->width;
        int h = ic->streams[videoIndex]->codec->height;

        InitD3D(gd3wnd);
        Build(w ,h);
    }
    //FILE* f = fopen("single.pcm", "wb+");



    

    //FILE* f = fopen("1.yuv", "wb+");
    //FILE* fr = fopen("1.yuv", "rb+");

    
    //playDsAudio();


    //fclose(f);
    //fclose(fr);

    //system("pause");
    return 0;
}

int DecodeUnit::MainExe(){

    /*
    FILE * fp;
    if ((fp = fopen("test0906.pcm", "wb+")) == NULL) {
        printf("cannot open this file
");
        return -1;
    }
    */
    AVFrame * videoFrame = av_frame_alloc();
    byte buffer[640 * 360 * 3 / 2];
    for (int i = 0; i <500; i++) {
        auto packet = readPacketFromSource();
        if (packet) {
            if (packet->stream_index == videoIndex) {
                //continue;
                if (videoDecode(packet.get(), videoFrame))
                {

        
                    int w = ic->streams[videoIndex]->codec->width;
                    int h = ic->streams[videoIndex]->codec->height;
                
                    AVFrame * frame = videoFrame;

                    AVPixelFormat a;
                    int iFormat = frame->format;

                    //int ret =fread(buffer, 1, 640*360*3/2, fr) ;

                    //if (0 == ret) break;

                    //Render(frame->linesize[0], h, frame->data[0]);
                    //Render(frame->linesize[0], h, frame->data[0], frame->data[1], frame->data[2]);
                    Render(frame->linesize[0], h, frame->data[0], frame->data[1], frame->data[2]);

                    //Render(640, 360, buffer, buffer + 640 * 360, buffer + 640 * 360+640*360/4);
                    //Render1(buffer);
                    int frame_size_y = frame->linesize[0] * frame->height;
                    //int frame_size_uv = ((frame->linesize[0] + 1) >> 1) * ((frame->height + 1) >> 1);
                    int frame_size_uv = frame->linesize[0] * frame->height / 4;
                    /*
                    int r1 = fwrite(frame->data[0], 1, frame_size_y, f);
                    int r2 = fwrite(frame->data[1], 1, frame_size_uv, f);
                    int r3 = fwrite(frame->data[2], 1, frame_size_uv, f);
                    */
                    double dt = (packet->dts - lastDts) * av_q2d(ic->streams[videoIndex]->time_base);

                    int dms = dt * 1000;
                    //if (dms<1000 & dms>0)  Sleep(dms);
                    //    SDL_Delay(dms);
                    printf("SDL_Delay %d 
", dms);

                    lastDts = packet->dts;
                }
            }
            if (packet->stream_index == audioIndex)
            {
                if (audioDecode(packet.get(), videoFrame))
                {

                    //-----------------
                    int dstNbChannels = 1;
                    int srcNbSamples = videoFrame->nb_samples;
                    int srcRate = ic->streams[audioIndex]->codec->sample_rate;
                    int dstRate = ic->streams[audioIndex]->codec->sample_rate;
                    int dstNbSamples = av_rescale_rnd(srcNbSamples, dstRate, srcRate, AV_ROUND_UP);
                    AVSampleFormat dst_sample_fmt = AV_SAMPLE_FMT_S16;

                    uint8_t** dst_data = nullptr;
                    int dstLinesize;
                    dstNbChannels = av_get_channel_layout_nb_channels(ic->streams[audioIndex]->codec->channel_layout);
                    dstNbChannels = dstNbChannels > 0 ? dstNbChannels : 1;
                    int ret = av_samples_alloc_array_and_samples(&dst_data, &dstLinesize, dstNbChannels, dstNbSamples, dst_sample_fmt, 0);

                    ret = swr_convert(swr, dst_data, dstNbSamples, (const uint8_t **)videoFrame->data, srcNbSamples);


                    //sdlRender->PlaySamples((BYTE*)dst_data[0], dstLinesize);
                    //PlaySamples((BYTE*)dst_data[0], dstLinesize);
                    printf("PlaySamples dstLinesize %d i %d
 ", dstLinesize, i);
                    //int r3 = fwrite((BYTE*)dst_data[0], 1, dstLinesize, fp);
                    if (gAudioBufUsed + dstLinesize > MAX_AUDIOBUFF_LEN){
                        //Sleep(300);
                        break;
                    }
                    memcpy((BYTE*)(gAudioBuf + gAudioBufUsed), (BYTE*)dst_data[0], dstLinesize);
                    gAudioBufUsed += dstLinesize;

                    //printf("write r3 =  %d
",  r3); 
                    int g = 0;

                }
            }



        }
        else {
            break;
        }
    }

    playDsAudio();

    av_frame_free(&videoFrame);
    //fclose(fp);
    return 0;
}

//明天可以同步---,to thi tha

 jni 里c调用java来处理音频的

 https://blog.csdn.net/qqqq245425070/article/details/90312692

audio里

#include "stdafx.h"

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <mmsystem.h>
#include <dsound.h>
#include "directSound.h"


#include "decodeUnit.h"

#define MAX_AUDIO_BUF 4 
#define BUFFERNOTIFYSIZE 192000 


//int sample_rate = 44100;    //PCM sample rate
//int channels = 2;            //PCM channel number
int bits_per_sample = 16;    //bits per sample


int i;

IDirectSound8 *m_pDS = 0;
IDirectSoundBuffer8 *m_pDSBuffer8 = NULL;    //used to manage sound buffers.
IDirectSoundBuffer *m_pDSBuffer = NULL;
IDirectSoundNotify8 *m_pDSNotify = 0;
DSBPOSITIONNOTIFY m_pDSPosNotify[MAX_AUDIO_BUF];
HANDLE m_event[MAX_AUDIO_BUF];


bool initDsAudio(int sample_rate, int channels){


    //sample_rate = 44100;
    //channels = 2;

    //SetConsoleTitle(TEXT("Simplest Audio Play DirectSound"));//Console Title
    //Init DirectSound
    if (FAILED(DirectSoundCreate8(NULL, &m_pDS, NULL)))
        return FALSE;

    //if (FAILED(m_pDS->SetCooperativeLevel(FindWindow(NULL, TEXT("Simplest Audio Play DirectSound")), DSSCL_NORMAL)))
    if (FAILED(m_pDS->SetCooperativeLevel(FindWindow(NULL, TEXT("testD3P")), DSSCL_NORMAL)))
        return FALSE;


    DSBUFFERDESC dsbd;
    memset(&dsbd, 0, sizeof(dsbd));
    dsbd.dwSize = sizeof(dsbd);
    dsbd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2;
    dsbd.dwBufferBytes = MAX_AUDIO_BUF*BUFFERNOTIFYSIZE;
    dsbd.lpwfxFormat = (WAVEFORMATEX*)malloc(sizeof(WAVEFORMATEX));
    dsbd.lpwfxFormat->wFormatTag = WAVE_FORMAT_PCM;
    /* format type */
    (dsbd.lpwfxFormat)->nChannels = channels;
    /* number of channels (i.e. mono, stereo...) */
    (dsbd.lpwfxFormat)->nSamplesPerSec = sample_rate;
    /* sample rate */
    (dsbd.lpwfxFormat)->nAvgBytesPerSec = sample_rate*(bits_per_sample / 8)*channels;
    /* for buffer estimation */
    (dsbd.lpwfxFormat)->nBlockAlign = (bits_per_sample / 8)*channels;
    /* block size of data */
    (dsbd.lpwfxFormat)->wBitsPerSample = bits_per_sample;
    /* number of bits per sample of mono data */
    (dsbd.lpwfxFormat)->cbSize = 0;

    //Creates a sound buffer object to manage audio samples. 
    HRESULT hr1;
    if (FAILED(m_pDS->CreateSoundBuffer(&dsbd, &m_pDSBuffer, NULL))) {
        return FALSE;
    }
    if (FAILED(m_pDSBuffer->QueryInterface(IID_IDirectSoundBuffer8, (LPVOID*)&m_pDSBuffer8))) {
        return FALSE;
    }
    //Get IDirectSoundNotify8
    if (FAILED(m_pDSBuffer8->QueryInterface(IID_IDirectSoundNotify, (LPVOID*)&m_pDSNotify))) {
        return FALSE;
    }
    for (i = 0; i<MAX_AUDIO_BUF; i++) {
        m_pDSPosNotify[i].dwOffset = i*BUFFERNOTIFYSIZE;
        m_event[i] = ::CreateEvent(NULL, false, false, NULL);
        m_pDSPosNotify[i].hEventNotify = m_event[i];
    }
    m_pDSNotify->SetNotificationPositions(MAX_AUDIO_BUF, m_pDSPosNotify);
    m_pDSNotify->Release();

    return -1;
}


extern DecodeUnit* gDu ;

    //Start Playing
    BOOL isPlaying = TRUE;
    LPVOID buf = NULL;
    DWORD  buf_len = 0;
    DWORD res = WAIT_OBJECT_0;
    DWORD offset = BUFFERNOTIFYSIZE;

#define MAX_AUDIOBUFF_LEN 192000*128
extern    BYTE gAudioBuf[MAX_AUDIOBUFF_LEN];
extern    DWORD gAudioBufUsed ;
extern  DWORD gAudioBufOffset ;

#define READ_FILE_LOOP 1024//19200*2
bool playDsAudio() {
    //----------------------------
    /*
    FILE * fp;
    //if ((fp = fopen("F:\NocturneNo2inEflat_44.1k_s16le.pcm", "rb")) == NULL) {
    if ((fp = fopen("test0906.pcm", "rb")) == NULL) {
        printf("cannot open this file
");
        return -1;
    }

    byte fbuf[READ_FILE_LOOP+1] = {0};
    while (1) {
        int ret = fread(fbuf, 1, READ_FILE_LOOP, fp);
        if (ret != READ_FILE_LOOP){
            fclose(fp);
            break;
        }
        memcpy((BYTE*)(gAudioBuf + gAudioBufUsed), (BYTE*)fbuf, READ_FILE_LOOP);
        gAudioBufUsed += READ_FILE_LOOP;

        //File End
        //Loop:
        
        //Close:
        //isPlaying=0;
    }

    


    */

    //-------------------------
    m_pDSBuffer8->SetCurrentPosition(0);
    m_pDSBuffer8->Play(0, 0, DSBPLAY_LOOPING);
    //Loop
    while (isPlaying) {
        if ((res >= WAIT_OBJECT_0) && (res <= WAIT_OBJECT_0 + 3)) {
            m_pDSBuffer8->Lock(offset, BUFFERNOTIFYSIZE, &buf, &buf_len, NULL, NULL, 0);
        /*    
            if (fread(buf, 1, buf_len, fp) != buf_len) {
                //File End
                //Loop:
                fseek(fp, 0, SEEK_SET);
                fread(buf, 1, buf_len, fp);
                //Close:
                //isPlaying=0;
            }
                */
            
            

            if (gAudioBufOffset >= gAudioBufUsed) break;

            memcpy(buf, gAudioBuf + gAudioBufOffset, buf_len);
            gAudioBufOffset += buf_len;
        
            offset += buf_len;
            offset %= (BUFFERNOTIFYSIZE * MAX_AUDIO_BUF);
            printf("this is %7d of buffer
", offset);
            m_pDSBuffer8->Unlock(buf, buf_len, NULL, 0);
        }
        res = WaitForMultipleObjects(MAX_AUDIO_BUF, m_event, FALSE, INFINITE);
    }

    return 0;
}