ffmpeg + sdl player console

{

#include <iostream>
extern "C"
{
#include <SDL.h>
}


static Uint8 *pAudio_chunk;
static Uint32 audio_len;
static Uint8 *pAudio_pos;
void fill_audio_buffer(void *userdata, Uint8 * stream, int len)
{
    SDL_memset(stream, 0, len);
    // 判断是否有读到数据
    if (audio_len == 0)
        return;

    len = (len > audio_len ? audio_len : len);
    SDL_MixAudio(stream, pAudio_pos, len, SDL_MIX_MAXVOLUME);
    pAudio_pos += len;
    audio_len -= len;
}

int playAudio(const char *file)
{
    /*** 初始化SDL ***/
    if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER))
    {
        printf("Initialize SDL failed: %s\n", SDL_GetError());
        return -1;
    }
    /****************/

    /*** 初始化初始化SDL_AudioSpec结构体 ***/
    SDL_AudioSpec audioSpec;

    // 音频数据的采样率。常用的有48000,44100等
    audioSpec.freq = 48000;

    // 音频数据的格式
    audioSpec.format = AUDIO_F32LSB;

    // 声道数。例如单声道取值为1,立体声取值为2
    audioSpec.channels = 2;

    // 设置静音的值
    audioSpec.silence = 0;

    // 音频缓冲区中的采样个数,要求必须是2的n次方
    audioSpec.samples = 1024;

    // 填充音频缓冲区的回调函数
    audioSpec.callback = fill_audio_buffer;
    /************************************/

    // 打开音频设备
    if (SDL_OpenAudio(&audioSpec, nullptr) < 0)
    {
        printf("Can not open audio!");
        return -1;
    }

    FILE *pAudioFile = fopen(file, "rb+");
    if (pAudioFile == nullptr)
    {
        printf("Can not open audio file!");
        return -1;
    }

    int pcm_buffer_size = 48000;
    char *pcm_buffer = (char *)malloc(pcm_buffer_size);
    int data_count = 0;

    SDL_PauseAudio(0);

    for (;;)
    {
        // 循环播放
        if (fread(pcm_buffer, 1, pcm_buffer_size, pAudioFile) != pcm_buffer_size)
        {
            fseek(pAudioFile, 0, SEEK_SET);
            fread(pcm_buffer, 1, pcm_buffer_size, pAudioFile);
            data_count = 0;
        }
        printf("Playing %10d Bytes data.\n", data_count);
        data_count += pcm_buffer_size;

        pAudio_chunk = (Uint8 *)pcm_buffer;
        audio_len = pcm_buffer_size;
        pAudio_pos = pAudio_chunk;

        while (audio_len > 0)
            SDL_Delay(0);
    }
    free(pcm_buffer);
    SDL_Quit();
}


//=======================================
const int bpp = 12;

//int screen_w=500,screen_h=500;
//const int pixel_w=680,pixel_h=180;
int screen_w = 640, screen_h = 360;
const int pixel_w = 960, pixel_h = 544;//这里必须与原视频的宽高像素匹配

unsigned char buffer[pixel_w*pixel_h*bpp / 8];

//Refresh Event
#define REFRESH_EVENT  (SDL_USEREVENT + 1)
//Break
#define BREAK_EVENT  (SDL_USEREVENT + 2)

int thread_exit = 0;

int refresh_video(void *opaque) {
    thread_exit = 0;
    while (thread_exit == 0) {
        SDL_Event event;
        event.type = REFRESH_EVENT;//自定义的事件
        SDL_PushEvent(&event);
        SDL_Delay(40);
    }
    thread_exit = 0;
    //Break
    SDL_Event event;
    event.type = BREAK_EVENT;//自定义的事件
    SDL_PushEvent(&event);
    return 0;
}

int playVideo(const char *file)
{
    if (SDL_Init(SDL_INIT_VIDEO)) {
        printf("Could not initialize SDL - %s\n", SDL_GetError());
        return -1;
    }

    SDL_Window *screen;
    //SDL 2.0 Support for multiple windows
    screen = SDL_CreateWindow("Simplest Video Play SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
        screen_w, screen_h, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
    if (!screen) {
        printf("SDL: could not create window - exiting:%s\n", SDL_GetError());
        return -1;
    }
    SDL_Renderer* sdlRenderer = SDL_CreateRenderer(screen, -1, 0);

    Uint32 pixformat = 0;
    //IYUV: Y + U + V  (3 planes)
    //YV12: Y + V + U  (3 planes)
    pixformat = SDL_PIXELFORMAT_IYUV;

    SDL_Texture* sdlTexture = SDL_CreateTexture(sdlRenderer, pixformat, SDL_TEXTUREACCESS_STREAMING, pixel_w, pixel_h);

    FILE *fp = NULL;
    fp = fopen(file, "rb+");//只读(r)写(+)方式,打开一个二进制文件(b)

    if (fp == NULL) {
        printf("cannot open this file\n");
        return -1;
    }

    SDL_Rect sdlRect;

    SDL_Thread *refresh_thread = SDL_CreateThread(refresh_video, NULL, NULL);
    SDL_Event event;
    int player_state = 1;//0:表示暂定,1表示继续播放
    while (1) {
        //Wait
        SDL_WaitEvent(&event);
        if (event.type == REFRESH_EVENT && player_state == 1) {
            if (fread(buffer, 1, pixel_w*pixel_h*bpp / 8, fp) != pixel_w * pixel_h*bpp / 8) {
                // Loop
                fseek(fp, 0, SEEK_SET);
                fread(buffer, 1, pixel_w*pixel_h*bpp / 8, fp);
            }

            SDL_UpdateTexture(sdlTexture, NULL, buffer, pixel_w);

            //FIX: If window is resize
            sdlRect.x = 0;
            sdlRect.y = 0;
            sdlRect.w = screen_w;
            sdlRect.h = screen_h;

            SDL_RenderClear(sdlRenderer);
            SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, &sdlRect);
            SDL_RenderPresent(sdlRenderer);

        }
        else if (event.type == SDL_WINDOWEVENT) {
            //获得窗口拉伸变化事件
            SDL_GetWindowSize(screen, &screen_w, &screen_h);//获得窗口宽和高
        }
        else if (event.type == SDL_QUIT) {
            thread_exit = 1;
        }
        else if (event.type == BREAK_EVENT) {
            break;
        }
        else if (event.key.keysym.scancode == SDL_SCANCODE_SPACE && event.key.state == SDL_PRESSED)//按空格键,暂停或者播放
        {
            SDL_Delay(40);
            player_state = (player_state == 1) ? 0 : 1;
            printf("player_state=%d\n", player_state);
        }
        else if (event.key.keysym.scancode == SDL_SCANCODE_ESCAPE && event.key.state == SDL_PRESSED)//按Esc键,退出播放
        {
            SDL_Delay(40);
            break;
            //SDL_Quit();
        }
        //printf("event.key.keysym.scancode=%d\n", event.key.keysym.scancode);

    }
    SDL_Quit();
    return 0;
}

int player(const char *audio, const char *video)
{
    /*** 初始化SDL ***/
    if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER))
    {
        printf("Initialize SDL failed: %s\n", SDL_GetError());
        return -1;
    }
    /****************/

    /*** 初始化初始化SDL_AudioSpec结构体 ***/
    SDL_AudioSpec audioSpec;

    // 音频数据的采样率。常用的有48000,44100等
    audioSpec.freq = 48000;

    // 音频数据的格式
    audioSpec.format = AUDIO_F32LSB;

    // 声道数。例如单声道取值为1,立体声取值为2
    audioSpec.channels = 2;

    // 设置静音的值
    audioSpec.silence = 0;

    // 音频缓冲区中的采样个数,要求必须是2的n次方
    audioSpec.samples = 1024;

    // 填充音频缓冲区的回调函数
    audioSpec.callback = fill_audio_buffer;
    /************************************/

    // 打开音频设备
    if (SDL_OpenAudio(&audioSpec, nullptr) < 0)
    {
        printf("Can not open audio!");
        return -1;
    }

    FILE *pAudioFile = fopen(audio, "rb+");
    if (pAudioFile == nullptr)
    {
        printf("Can not open audio file!");
        return -1;
    }

    int pcm_buffer_size = 48000;
    char *pcm_buffer = (char *)malloc(pcm_buffer_size);
    int data_count = 0;

    SDL_PauseAudio(0);


    //
    SDL_Window *screen;
    //SDL 2.0 Support for multiple windows
    screen = SDL_CreateWindow("Simplest Video Play SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
        screen_w, screen_h, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
    if (!screen) {
        printf("SDL: could not create window - exiting:%s\n", SDL_GetError());
        return -1;
    }
    SDL_Renderer* sdlRenderer = SDL_CreateRenderer(screen, -1, 0);

    Uint32 pixformat = 0;
    //IYUV: Y + U + V  (3 planes)
    //YV12: Y + V + U  (3 planes)
    pixformat = SDL_PIXELFORMAT_IYUV;

    SDL_Texture* sdlTexture = SDL_CreateTexture(sdlRenderer, pixformat, SDL_TEXTUREACCESS_STREAMING, pixel_w, pixel_h);

    FILE *fp = NULL;
    fp = fopen(video, "rb+");//只读(r)写(+)方式,打开一个二进制文件(b)

    if (fp == NULL) {
        printf("cannot open this file\n");
        return -1;
    }

    SDL_Rect sdlRect;

    SDL_Thread *refresh_thread = SDL_CreateThread(refresh_video, NULL, NULL);
    SDL_Event event;
    int player_state = 1;//0:表示暂定,1表示继续播放
    //



    for (;;)
    {
        // 循环播放
        if (fread(pcm_buffer, 1, pcm_buffer_size, pAudioFile) != pcm_buffer_size)
        {
            fseek(pAudioFile, 0, SEEK_SET);
            fread(pcm_buffer, 1, pcm_buffer_size, pAudioFile);
            data_count = 0;
        }
        printf("Playing %10d Bytes data.\n", data_count);
        data_count += pcm_buffer_size;

        pAudio_chunk = (Uint8 *)pcm_buffer;
        audio_len = pcm_buffer_size;
        pAudio_pos = pAudio_chunk;

        while (audio_len > 0)
            SDL_Delay(0);


        //Wait
        SDL_WaitEvent(&event);
        if (event.type == REFRESH_EVENT && player_state == 1) {
            if (fread(buffer, 1, pixel_w*pixel_h*bpp / 8, fp) != pixel_w * pixel_h*bpp / 8) {
                // Loop
                fseek(fp, 0, SEEK_SET);
                fread(buffer, 1, pixel_w*pixel_h*bpp / 8, fp);
            }

            SDL_UpdateTexture(sdlTexture, NULL, buffer, pixel_w);

            //FIX: If window is resize
            sdlRect.x = 0;
            sdlRect.y = 0;
            sdlRect.w = screen_w;
            sdlRect.h = screen_h;

            SDL_RenderClear(sdlRenderer);
            SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, &sdlRect);
            SDL_RenderPresent(sdlRenderer);

        }
        else if (event.type == SDL_WINDOWEVENT) {
            //获得窗口拉伸变化事件
            SDL_GetWindowSize(screen, &screen_w, &screen_h);//获得窗口宽和高
        }
        else if (event.type == SDL_QUIT) {
            thread_exit = 1;
        }
        else if (event.type == BREAK_EVENT) {
            break;
        }
        else if (event.key.keysym.scancode == SDL_SCANCODE_SPACE && event.key.state == SDL_PRESSED)//按空格键,暂停或者播放
        {
            SDL_Delay(40);
            player_state = (player_state == 1) ? 0 : 1;
            //printf("player_state=%d\n", player_state);
        }
        else if (event.key.keysym.scancode == SDL_SCANCODE_ESCAPE && event.key.state == SDL_PRESSED)//按Esc键,退出播放
        {
            SDL_Delay(40);
            break;
            //SDL_Quit();
        }
        //printf("event.key.keysym.scancode=%d\n", event.key.keysym.scancode);
    }
    free(pcm_buffer);
    SDL_Quit();
    return 0;
}


//int SDL_main(int argc, char *argv[])
int main(int argc, char *argv[])
{


    //playAudio("D:\\out0.pcm");

    //playVideo("D:\\out0.yuv");

    //player("D:\\out0.pcm", "D:\\out0.yuv");


    return 0;
}

 

}

posted @ 2020-07-07 00:03  YZFHKMS-X  阅读(194)  评论(0编辑  收藏  举报