//
// 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
网友评论