ZBLOG

代码示例

下面是一个简单的示例代码,展示了如何使用FFmpeg和OpenGL进行视频解码和渲染:

#include <iostream>
#include <GL/glut.h>
#include <opencv2/opencv.hpp>
extern "C" {
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libswscale/swscale.h>
}

// 视频相关变量
AVFormatContext* formatCtx;
AVCodecContext* codecCtx;
AVFrame* frame;
int videoStreamIndex;
struct SwsContext* swsCtx;

// OpenGL窗口尺寸
int windowWidth = 800;
int windowHeight = 600;

// 纹理ID和大小
GLuint textureID;
int textureWidth, textureHeight;

void display() {
    glClear(GL_COLOR_BUFFER_BIT);
    
    // 使用纹理绘制图像
    glBindTexture(GL_TEXTURE_2D, textureID);
    glBegin(GL_QUADS);
        glTexCoord2f(0.0, 1.0); glVertex2f(-1.0, -1.0);
        glTexCoord2f(1.0, 1.0); glVertex2f(1.0, -1.0);
        glTexCoord2f(1.0, 0.0); glVertex2f(1.0, 1.0);
        glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, 1.0);
    glEnd();
    
    glutSwapBuffers();
}

void reshape(int width, int height) {
    windowWidth = width;
    windowHeight = height;
    
    glViewport(0, 0, windowWidth, windowHeight);
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(-1.0, 1.0, -1.0, 1.0);
    
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void decodeFrame(AVCodecContext* codecCtx, AVPacket* packet) {
    // 发送解码数据包到解码器
    avcodec_send_packet(codecCtx, packet);

    while (avcodec_receive_frame(codecCtx, frame) == 0) {
        // 格式转换
        sws_scale(swsCtx,
                  frame->data,
                  frame->linesize,
                  0,
                  codecCtx->height,
                  frame->data,
                  frame->linesize);

        // 更新纹理数据
        glBindTexture(GL_TEXTURE_2D, textureID);
        glTexSubImage2D(GL_TEXTURE_2D,
                        0,
                        0,
                        0,
                        textureWidth,
                        textureHeight,
                        GL_RGB,
                        GL_UNSIGNED_BYTE,
                        frame->data[0]);
        
        glutPostRedisplay();
    }
}

int main(int argc, char** argv) {
    if (argc < 2) {
        std::cout << "Please provide a video file." << std::endl;
        return -1;
    }
    
    // 初始化FFmpeg
    av_register_all();

    // 打开视频文件
    if (avformat_open_input(&formatCtx, argv[1], nullptr, nullptr) != 0) {
        std::cout << "Failed to open video file." << std::endl;
        return -1;
    }

    // 获取视频流信息
     if (avformat_find_stream_info(formatCtx, nullptr) < 0) {
         std::cout << "Failed to find stream information." << std::endl;
         return -1;
     }

    // 查找视频流
    for (int i = 0; i < formatCtx->nb_streams; i++) {
        if (formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoStreamIndex = i;
            break;
        }
    }

    // 获取解码器参数
    AVCodecParameters* codecParams = formatCtx->streams[videoStreamIndex]->codecpar;

    // 获取解码器
    AVCodec* codec = avcodec_find_decoder(codecParams->codec_id);
    
    // 打开解码器
     if (avcodec_open2(codecCtx, codec, nullptr) < 0) {
         std::cout << "Failed to open decoder." << std::endl;
         return -1;
     }

    // 分配帧对象内存
     frame = av_frame_alloc();

    // 创建OpenGL窗口
     glutInit(&argc, argv);
     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
     glutInitWindowSize(windowWidth, windowHeight);
     glutCreateWindow("Video Player");

    // 初始化OpenGL纹理
     glGenTextures(1, &textureID);
     
     glBindTexture(GL_TEXTURE_2D, textureID);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // 设置回调函数和窗口大小变化的回调函数
     glutDisplayFunc(display);
     glutReshapeFunc(reshape);

    // 设置格式转换上下文
   swsCtx = sws_getContext(codecParams->width,
                           codecParams->height,
                           static_cast<AVPixelFormat>(codecParams->format),
                           codecParams->width,
                           codecParams->height,
                           AV_PIX_FMT_RGB24,
                           SWS_BILINEAR,
                           nullptr,
                           nullptr,
                           nullptr);

    // 读取视频帧
     AVPacket packet;
     while (av_read_frame(formatCtx, &packet) >= 0) {
         if (packet.stream_index == videoStreamIndex) {
             decodeFrame(codecCtx, &packet);
         }
         
         av_packet_unref(&packet);
     }

    // 清理资源
     av_frame_free(&frame);
     avcodec_close(codecCtx);
     avformat_close_input(&formatCtx);

    return 0;
}

这只是一个简单的示例,实际的实现可能需要根据具体情况进行修改和扩展。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://sdn.0voice.com/?id=5084

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?