Skip to content

Latest commit

 

History

History
296 lines (232 loc) · 12.1 KB

20180906.md

File metadata and controls

296 lines (232 loc) · 12.1 KB

20180906-第六期

本期内容主要包括

  1. 摄像机坐标系求解(郑雨薇)
  2. 弗洛伊德算法简介(许云华)
  3. 线程状态图(线程生命周期)(张艳强)
  4. gl中的纹理映射(冯树勋)
  5. 纹理贴图学习(陈伟)
  6. 服务器负载均衡(张辰)
  7. 双线性差值(许佳佳)
  8. HashMap简介(江丁魁)
  9. 总结本期知识点

摄像机坐标系求解

要定义一个摄像机,需要摄像机在世界坐标的位置,它观察的方向(z轴反方向),指向右侧的向量(x)轴,以及上轴(y轴) 。

摄像机位置

xujicheng

使用一个三维向量来表示位置的坐标,glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);

z轴方向

摄像机观察的反方向,即用观察目标指向摄像机位置即可。

xujicheng

glm::vec3 cameraTarget = glm::vec3(0.0f, 0.0f, 0.0f); glm::vec3 cameraDirection = glm::normalize(cameraPos - cameraTarget);

弗洛伊德算法简介

待续(未收到内容)

进程和线程的区别

  • 进程(process),指的是一个正在运行中的可执行文件。每一个进程都拥有独立的虚拟内存空间和系统资源,包括端口权限等,且至少包含一个主线程和任意数量的辅助线程。另外,当一个进程的主线程退出时,这个进程就结束了;

  • 线程(thread),指的是一个独立的代码执行路径,也就是说线程是代码执行路径的最小分支(CPU调度的最小单位,不具有独立内存,多个线程共享进程的资源)。在 iOS 中,线程的底层实现是基于 POSIX threads API 的,也就是我们常说的 pthreads ;

  • 总结:进程是资源分配的基本单位,线程是调度的基本单位。进程包含线程,线程共用进程的资源

    更多信息请移步至我的博客,关于进程和线程的详细解释跳转

gl中的纹理映射

glGenTextures
纹理生成

glBindTexture
纹理绑定
GL_TEXTURE_2D 首次绑定后纹理成为2d纹理
GL_TEXTURE_CUBE_MAP 首次绑定后纹理成为3d纹理

glActiveTexture
纹理激活
至少有8个,查询GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS获取;从0开始

glGenerateMipmap
为当前激活纹理生成mip纹理
target 当前激活纹理的绑定类型,必须为GL_TEXTURE_2D或 GL_TEXTURE_CUBE_MAP

glTexParameter
参数类型:
GL_TEXTURE_MIN_FILTER 缩小情况的映射,可以指定mipmap,分为nearest和linear方式,一个是最近点,一个取临近四个点的线性插值
GL_TEXTURE_MAG_FILTER 放大情况的映射,分为nearest和linear方式
GL_TEXTURE_WRAP_S 纹理坐标映射模式,GL_CLAMP_TO_EDGE,GL_MIRRORED_REPEAT,GL_REPEAT,分别为边界裁剪,镜像重复和重复
GL_TEXTURE_WRAP_T 同GL_TEXTURE_WRAP_S

glTexImage2D
Level 指定mipmap级别
internalformat gpu中texture像素格式,GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA
format cpu中像素格式,必须和internalformat一致
type cpu中像素类型,GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4, and GL_UNSIGNED_SHORT_5_5_5_1
Data cpu中像素指针; 如果为空,gpu中会分配width x height的存储,但是处于未定义状态不可使用,通过glTexSubImage2D来初始化

glTexSubImage2D
xoffset, yoffset, width, height界定了更新的区域,但是不能超过gpu中纹理区域
format cpu中像素格式,必须和internalformat一致
type cpu中像素类型,GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4, and GL_UNSIGNED_SHORT_5_5_5_1
data 替代像素

glPixelStorei
影响像素对齐
GL_PACK_ALIGNMENT 影响gpu到cpu的像素传输,可选1,2,4,8
GL_UNPACK_ALIGNMENT 影响cpu到gpu的像素传输,可选1,2,4,8;上述glTexImage2D,glTexSubImage2D需要谨慎设置该参数

glCopyTexImage2D
同glTexImage2D,但是像素数据部分指向当前的framebuffer。
width 2d纹理至少64像素,3d纹理至少16像素
Height 2d纹理至少64像素,3d纹理至少16像素

glCopyTexSubImage2D
同glTexSubImage2D,但是像素数据部分指向当前的framebuffer。

glCompressedTexImage2D
扩展接口,压缩纹理格式需要查询GL_NUM_COMPRESSED_TEXTURE_FORMATS, GL_COMPRESSED_TEXTURE_FORMATS
width 2d纹理至少64像素,3d纹理至少16像素
height 2d纹理至少64像素,3d纹理至少16像素
internalformat 指定压缩数据的格式
imageSize 指定压缩数据的大小
data 压缩数据的指针

glCompressedTexSubImage2D
参数解释同glCompressedTexImage2D
其中xoffset, yoffset, width, height界定了更新的区域, 但是不能超过gpu中纹理区域; width, height没有最小限制

纹理贴图学习

SDL简介

SDL(Simple DirectMedia Layer)是一套跨平台多媒体开发库,由C语言写成。SDL提供了数种控制声音、图像、输出入的函数,让开发者使用同一套代码就可以开发出跨平台的应用。例如图像是封装的OpenGL或者Direct3D,音频也是封装了各个平台的底层音频接口如OpenSL。直接移植SDL到各个平台上,可以很便利地开发出播放器,但灵活性不够,可以参考,自行实现视频、音频播放以及音视频同步。

SDL实现视频播放
//  SDL_ffmpeg_demo
//
//  Created by cw on 2018/9/3.
//  Copyright © 2018年 cw. All rights reserved.
//

#include <stdio.h>

extern "C"{
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>
#include <libavutil/imgutils.h>
#include <libavresample/avresample.h>
#include <libswscale/swscale.h>
#include <SDL2/SDL.h>
}

int main(int argc, char* argv[])
{
    AVFormatContext *pFormatContext;
    AVCodec *pCodec;
    AVCodecContext *pCodecContext;
    AVCodecParameters *pCodecParams;
    AVFrame *pFrame, *pFrameYUV;
    AVPacket *packet;
    struct SwsContext *img_convert_ctx;
    SDL_Window *screen;
    SDL_Renderer *sdlRenderer;
    SDL_Texture *sdlTexture;
    SDL_Rect sdlRect;
    unsigned char *out_buffer;
    int videoIndex = -1;
    int screen_w, screen_h;

    char filepath[]="/Users/cw/Desktop/ios/SDL_ffmpeg_demo/SDL_ffmpeg_demo/bigbuckbunny_480x272.h264";

    pFormatContext = avformat_alloc_context();
    if (avformat_open_input(&pFormatContext, filepath, nullptr, nullptr)!=0) {
        printf("could not open input stream. \n");
        return -1;
    }
    if (avformat_find_stream_info(pFormatContext, nullptr)<0) {
        printf("could not find stream information. \n");
        return -1;
    }
    for (int i=0; i<pFormatContext->nb_streams; ++i) {
        if (pFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoIndex = i;
            break;
        }
    }
    if (videoIndex == -1) {
        printf("could not find video stream. \n");
        return -1;
    }
    pCodecParams = pFormatContext->streams[videoIndex]->codecpar;
    pCodec = avcodec_find_decoder(pCodecParams->codec_id);
    if (pCodec == nullptr) {
        printf("could not find video codec. \n");
        return -1;
    }
    pCodecContext = avcodec_alloc_context3(pCodec);
    avcodec_parameters_to_context(pCodecContext, pCodecParams);
    if (avcodec_open2(pCodecContext, pCodec, nullptr)<0) {
        printf("could not open video codec");
        return -1;
    }
    pFrame = av_frame_alloc();
    pFrameYUV = av_frame_alloc();
    out_buffer = (unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecParams->width, pCodecParams->height, 1));
    av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, out_buffer, AV_PIX_FMT_YUV420P, pCodecParams->width, pCodecParams->height, 1);
    packet = (AVPacket *)av_malloc(sizeof(AVPacket));

    printf("--------------File Info begin ------------\n");
    av_dump_format(pFormatContext, videoIndex, filepath, 0);
    printf("--------------File Info end---------------\n");

    img_convert_ctx = sws_getContext(pCodecParams->width, pCodecParams->height, pCodecContext->pix_fmt, pCodecParams->width, pCodecParams->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, nullptr, nullptr, nullptr);

    //SDL init begin
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
        printf("could not init sdl, %s ", SDL_GetError());
        return -1;
    }
    screen_w = pCodecParams->width;
    screen_h = pCodecParams->height;
    screen = SDL_CreateWindow("My First SDL2 demo", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_w, screen_h, SDL_WINDOW_OPENGL);
    if (!screen) {
        printf("could not create sdl window %s.\n", SDL_GetError());
        return -1;
    }
    sdlRenderer = SDL_CreateRenderer(screen, -1, 0);
    sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, screen_w, screen_h);
    sdlRect.x = 0;
    sdlRect.y = 0;
    sdlRect.w = screen_w;
    sdlRect.h = screen_h;
    //SDL init end

    while (av_read_frame(pFormatContext, packet)==0) {
        //video
        if (packet->stream_index == videoIndex) {
            int ret = avcodec_send_packet(pCodecContext, packet);
            if (ret !=0) {
                printf("avcodec_send_packet error. \n");
                return -1;
            }
            int got_picture = avcodec_receive_frame(pCodecContext, pFrame);
            if (got_picture == 0) {
                sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecParams->height, pFrameYUV->data, pFrameYUV->linesize);
                //SDL
                SDL_UpdateYUVTexture(sdlTexture, &sdlRect, pFrameYUV->data[0], pFrameYUV->linesize[0], pFrameYUV->data[1], pFrameYUV->linesize[1], pFrameYUV->data[2], pFrameYUV->linesize[2]);
                SDL_RenderClear(sdlRenderer);
                SDL_RenderCopy(sdlRenderer, sdlTexture, nullptr, &sdlRect);
                SDL_RenderPresent(sdlRenderer);
                SDL_Delay(40);
            }
        }
        av_packet_unref(packet);
    }

    sws_freeContext(img_convert_ctx);
    SDL_Quit();
    av_frame_free(&pFrameYUV);
    av_frame_free(&pFrame);
    avcodec_close(pCodecContext);
    avformat_close_input(&pFormatContext);
//    avcodec_parameters_free(&pCodecParams);
    return 0;
}

SDL实现音频播放

服务器负载均衡

待补(未收到内容)

双线性差值

线性插值

假设我们已知坐标 (x0, y0) 与 (x1, y1),要得到 [x0, x1] 区间内某一位置 x 在直线上的值。根据图中所示,我们得到 这里写图片描述 由于 x 值已知,所以可以从公式得到 y 的值 这里写图片描述

这里写图片描述

双线性插值

效果

这里写图片描述

假如我们想得到未知函数 f 在点 P = (x, y) 的值,假设我们已知函数 f 在 Q11 = (x1, y1)、Q12 = (x1, y2), Q21 = (x2, y1) 以及 Q22 = (x2, y2) 四个点的值。首先在 x 方向进行线性插值,得到: 这里写图片描述

然后在 y 方向进行线性插值,得到: 这里写图片描述

最终结果: 这里写图片描述 这里写图片描述

HashMap简介

待补(未收到内容)

总结本期知识点

待补()