zoukankan      html  css  js  c++  java
  • 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
    ", 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.
    ", 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
    ", 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
    ", 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
    ");
            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
    ", 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
    ", 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
    ", 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
    ", 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
    ");
            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.
    ", 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
    ", 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
    ", 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;
    }

    }

  • 相关阅读:
    JAVA SkipList 跳表 的原理和使用例子
    TreeMap、HashMap、ConcurrentSkipListMap之性能比较
    CompletionService 和ExecutorService的区别和用法
    1. java.util.concurrent
    JAVA Concurrent包 中的并发集合类
    并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法
    Objective-C中 ==、isEqual、isEqualToString判断字符串相等
    设置UIButton的文字显示位置、字体的大小、字体的颜色
    9个完整android开源app项目
    android 开源项目集合
  • 原文地址:https://www.cnblogs.com/YZFHKMS-X/p/13258510.html
Copyright © 2011-2022 走看看