美文网首页
Mac 下OpenGL FFmpeg 播放视频

Mac 下OpenGL FFmpeg 播放视频

作者: 贼噶人 | 来源:发表于2020-01-15 15:30 被阅读0次
    //
    //  main.c
    //  OpenGL
    //
    //  Created by gang.zhou on 2020/1/13.
    //  Copyright © 2020 gang.zhou. All rights reserved.
    //
    
    #include <stdio.h>
    #include <glad/glad.h>
    #include <GLFW/glfw3.h>
    #include <libavformat/avformat.h>
    #include <libavutil/avutil.h>
    #include <libavutil/imgutils.h>
    #include <libavcodec/avcodec.h>
    #include <libavdevice/avdevice.h>
    #include <libavfilter/avfilter.h>
    #include <libswscale/swscale.h>
    #include <libswresample/swresample.h>
    #include <pthread.h>
    #include <unistd.h>
    #include <SDL2/SDL.h>
    
    Uint8 * myStream = NULL;
    SDL_atomic_t myLen = {0};
    SDL_atomic_t hasAudioAtomic = {0};
    
    void sdlAudioCallback (void *userdata, Uint8 * stream,
                                        const int len){
        if(!SDL_AtomicGet(&hasAudioAtomic)){
             memset(stream, 0, len);
        }
        else{
            myStream = stream;
            SDL_AtomicSet(&myLen, len);
        }
    }
    
    int main(const int argc, const char * argv[]) {
        if(SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER)){
            printf("SDL_Init error:%s\n",SDL_GetError());
        }
        if(GLFW_TRUE == glfwInit()){
            GLFWwindow* window = glfwCreateWindow(160 * 4 * 1.5, 90 * 4 * 1.5, "Hello", NULL, NULL);
            if(NULL != window){
                glfwMakeContextCurrent(window);
                gladLoadGL();
                glViewport(0, 0, 640 * 1.5, 360 * 1.5);
    
                //顶点Sharder
                const GLuint vertexShader =  glCreateShader(GL_VERTEX_SHADER);
                const GLchar* vertexSource = "attribute vec2 aTexCoord;\nattribute vec3 aPos;\n varying vec2 aCoord;\n void main(){\n gl_Position = vec4(aPos,1.0);\n aCoord = aTexCoord;\n}\n";
                glShaderSource(vertexShader, 1, &vertexSource, NULL);
                glCompileShader(vertexShader);
                GLint success;
                glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
                if(!success){
                    GLchar infoLog[1024] = {0};
                    glGetShaderInfoLog(vertexShader, 1024, NULL, infoLog);
                    printf("vertexShader %s \n",infoLog);
                }
                const GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
                const GLchar* fragmentSource = "mat3 matrix = mat3(1.164,1.164,1.164,0,-0.213,2.112,1.793,-0.533,0);\n vec3 yuv;\n varying vec2 aCoord;\n uniform sampler2D texture ;\nvoid main(){\n yuv = texture2D(texture,aCoord).rgb ;\n gl_FragColor = vec4(yuv,1.0);\n }\n";
                glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
                glCompileShader(fragmentShader);
                glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
                if(!success){
                    GLchar infoLog[1024] = {0};
                    glGetShaderInfoLog(fragmentShader, 1024, NULL, infoLog);
                    printf("fragmentShader %s \n",infoLog);
                }
                GLuint shaderProgram =  glCreateProgram();
                glAttachShader(shaderProgram, vertexShader);
                glAttachShader(shaderProgram, fragmentShader);
                glLinkProgram(shaderProgram);
                glDeleteShader(vertexShader);
                glDeleteShader(fragmentShader);
                glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
                if(!success){
                    GLchar infoLog[1024] = {0};
                    glGetProgramInfoLog(shaderProgram, 1024, NULL, infoLog);
                    printf("%s \n",infoLog);
                }
                const GLint aPosLocation =  glGetAttribLocation(shaderProgram, "aPos");
                const GLint aTexCoordLocation =  glGetAttribLocation(shaderProgram, "aTexCoord");
                const float vertices[] = {
                    -1.0f,-1.0f,0,0.0f,1.0f,
                    1.0f,-1.0f,0,1.0f,1.0f,
                    1.0f,1.0f,0,1.0f,0.0f,
                    -1.0f,1.0f,0,0.0f,0.0f
                };
                const GLint indices[] = {
                    0, 1, 3,
                    1, 2, 3
                };
                
                GLuint VAO;
                glGenVertexArraysAPPLE(1, &VAO);
                glBindVertexArrayAPPLE(VAO);
                
                GLuint VBO;
                glGenBuffers(1, &VBO);
                glBindBuffer(GL_ARRAY_BUFFER, VBO);
                glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
                
                GLuint EBO;
                glGenBuffers(1, &EBO);
                glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
                glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
                
                glVertexAttribPointer(aPosLocation, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
                glEnableVertexAttribArray(aPosLocation);
                glVertexAttribPointer(aTexCoordLocation, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
                glEnableVertexAttribArray(aTexCoordLocation);
                
                GLuint texture;
                glGenTextures(1, &texture);
                glActiveTexture(GL_TEXTURE0);
                glBindTexture(GL_TEXTURE_2D, texture);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                
                avformat_network_init();
                AVFormatContext* avFormatContext = avformat_alloc_context();
                if(NULL != avFormatContext){
                    if(!avformat_open_input(&avFormatContext, "http://mytianh5.oss-cn-beijing.aliyuncs.com/website/video/zaojiaoji.mp4", NULL, NULL)){
                        if(avformat_find_stream_info(avFormatContext, NULL) >= 0){
                            AVCodecParameters *videoCodecParmeters = NULL;
                            AVRational videoAVRational = {1,50};
                            AVCodecParameters *audioCodecParmeters = NULL;
                            for (int index = 0;index < avFormatContext->nb_streams; index++) {
                                AVCodecParameters* codecParmeters = avFormatContext->streams[index]->codecpar;
                                if(codecParmeters->codec_type == AVMEDIA_TYPE_VIDEO
                                   &&  NULL == videoCodecParmeters){
                                    videoCodecParmeters = codecParmeters;
                                    videoAVRational = avFormatContext->streams[index]->time_base;
                                } else if(codecParmeters->codec_type == AVMEDIA_TYPE_AUDIO
                                   && NULL == audioCodecParmeters){
                                    audioCodecParmeters = codecParmeters;
                                    
                                }
                            }
                            if(NULL != videoCodecParmeters && NULL != audioCodecParmeters){
                                AVCodec* videoCodec =  avcodec_find_decoder(videoCodecParmeters->codec_id);
                                AVCodec* audioCodec =  avcodec_find_decoder(audioCodecParmeters->codec_id);
                                AVCodecContext* avCodecContext = avcodec_alloc_context3(videoCodec);
                                AVCodecContext* avAudioCodecContext = avcodec_alloc_context3(audioCodec);
                                avcodec_parameters_to_context(avAudioCodecContext, audioCodecParmeters);
                                avcodec_parameters_to_context(avCodecContext, videoCodecParmeters);
                            
                                struct SwsContext *sws_context = sws_getContext(avCodecContext->width, avCodecContext->height, avCodecContext->pix_fmt, avCodecContext->width, avCodecContext->height, AV_PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL);
                        
                                struct SwrContext* swrContext =  swr_alloc();
                                swr_alloc_set_opts(swrContext, AV_CH_LAYOUT_MONO, AV_SAMPLE_FMT_S16, avAudioCodecContext->sample_rate, av_get_default_channel_layout(avAudioCodecContext->channels), avAudioCodecContext->sample_fmt, avAudioCodecContext->sample_rate, 0, NULL);
                                swr_init(swrContext);
                                int out_buffer_size = av_samples_get_buffer_size(NULL,av_get_channel_layout_nb_channels(AV_CH_LAYOUT_MONO) , 1024, AV_SAMPLE_FMT_S16, 1);
                                uint8_t* out_buffer = (uint8_t*)av_malloc(out_buffer_size);
                                SDL_AudioSpec audioSpec;
                                audioSpec.freq = avAudioCodecContext->sample_rate;
                                audioSpec.format = AUDIO_S16;
                                audioSpec.channels = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_MONO);
                                audioSpec.samples = 1024;
                                audioSpec.callback = sdlAudioCallback;
                                SDL_OpenAudio(&audioSpec, NULL);
                                SDL_PauseAudio(0);
                                if(!avcodec_open2(avCodecContext, videoCodec, NULL) && !avcodec_open2(avAudioCodecContext, audioCodec, NULL)){
                                    AVPacket *pkt = av_packet_alloc();
                                    AVFrame *fra = av_frame_alloc();
                                    uint8_t *pointers[4];
                                    int linesizes[4];
                                    av_image_alloc(pointers, linesizes, avCodecContext->width, avCodecContext->height, AV_PIX_FMT_RGB24, 1);
                                    while(!glfwWindowShouldClose(window)
                                          && !av_read_frame(avFormatContext, pkt)){
                                        if(pkt->stream_index == 0){
                                            if(!avcodec_send_packet(avCodecContext, pkt)){
                                                while (!avcodec_receive_frame(avCodecContext, fra)) {
                                                    sws_scale(sws_context, (const uint8_t * const *)fra->data, fra->linesize, 0, fra->height, pointers, linesizes);
                                                    glClearColor(1, 0, 0, 1);
                                                    glClear(GL_COLOR_BUFFER_BIT);
                                                    glBindTexture(GL_TEXTURE_2D, texture);
                                                    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fra->width, fra->height, 0, GL_RGB, GL_UNSIGNED_BYTE,pointers[0]);
                                                    av_frame_unref(fra);
                                                    glUseProgram(shaderProgram);
                                                    glBindVertexArrayAPPLE(VAO);
                                                    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0);
                                                    glfwSwapBuffers(window);
                                                    glfwPollEvents();
                                                }
                                            }
                                        } else {
                                            if(!avcodec_send_packet(avAudioCodecContext, pkt)){
                                                while (!avcodec_receive_frame(avAudioCodecContext, fra)) {
                                                    swr_convert(swrContext, &out_buffer, out_buffer_size, (const uint8_t**)fra->data, fra->nb_samples);
                                                    av_frame_unref(fra);
                                                    SDL_AtomicSet(&hasAudioAtomic, 1);
                                                    while (0 >= SDL_AtomicGet(&myLen)) {
                                                        
                                                    }
                                                    memcpy(myStream, out_buffer
                                                           , SDL_AtomicGet(&myLen));
                                                    SDL_AtomicSet(&myLen, 0);
                                                }
                                            }
                                        }
                                        av_packet_unref(pkt);
                                    }
                                    av_free(pointers[0]);
                                    av_packet_free(&pkt);
                                    av_frame_free(&fra);
                                    avcodec_close(avCodecContext);
                                    avcodec_free_context(&avCodecContext);
                                    avcodec_close(avAudioCodecContext);
                                    avcodec_free_context(&avAudioCodecContext);
                                    sws_freeContext(sws_context);
                                    av_free(out_buffer);
                                    swr_free(&swrContext);
                                }
                            }
                        }
                    }
                    avformat_free_context(avFormatContext);
                }
                glDeleteVertexArraysAPPLE(1, &VAO);
                glDeleteBuffers(1, &VBO);
                glDeleteBuffers(1, &EBO);
            }
            glfwDestroyWindow(window);
        }
        glfwTerminate();
        return 0;
    }
    
    
    
    屏幕快照 2020-01-15 下午3.29.55.png

    相关文章

      网友评论

          本文标题:Mac 下OpenGL FFmpeg 播放视频

          本文链接:https://www.haomeiwen.com/subject/dgptzctx.html