// gcc -o testDrone2_video testDrone2_video.c -lavcodec -lavformat -lswscale -lSDL2
// g++ -o testDrone2_video testDrone2_video.c -lavcodec -lavformat -lswscale -lSDL2

#ifdef __cplusplus
extern "C" {
#endif

#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"

#ifdef __cplusplus
}
#endif

#include "SDL2/SDL.h"

int main(int argc, char* argv[]) {
  
  // 3.0. Initializes the video subsystem *must be done before anything other!!
  if (SDL_Init(SDL_INIT_VIDEO) < 0) {
    fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
    return -1;
  }
  
  // prepare variables
  // decoding
  char              *drone_addr = "http://192.168.1.1:5555";
  AVFormatContext   *pFormatCtx = NULL;
  AVCodecContext    *pCodecCtx;
  AVCodec           *pCodec;
  AVPacket          packet;
  AVFrame           *pFrame;
  int               terminate, frameDecoded;
  
  // converting
  AVFrame           *pFrame_YUV420P;
  uint8_t           *buffer_YUV420P;
  struct SwsContext *pConvertCtx_YUV420P;
  
  AVFrame           *pFrame_BGR24;
  uint8_t           *buffer_BGR24;
  struct SwsContext *pConvertCtx_BGR24;
  
  // displaying
  SDL_Window        *pWindow1;
  SDL_Renderer      *pRenderer1;
  SDL_Texture       *bmpTex1;
  uint8_t           *pixels1;
  int               pitch1, size1;
  
  SDL_Window        *pWindow2;
  SDL_Renderer      *pRenderer2;
  SDL_Texture       *bmpTex2;
  uint8_t           *pixels2;
  int               pitch2, size2;
  
  // SDL event handling
  SDL_Event         event;
    
  // 1.1 Register all formats and codecs
  av_register_all();
  avcodec_register_all();
  avformat_network_init();
  
  // 1.2. Open video file
  while(avformat_open_input(&pFormatCtx, drone_addr, NULL, NULL) != 0)
    printf("Could not open the video file\nRetrying...\n");
  
  // 1.3. Retrieve stream information
  avformat_find_stream_info(pFormatCtx, NULL);
  // Dump information about file to standard output
  av_dump_format(pFormatCtx, 0, drone_addr, 0);
  
  // 1.4. Get a pointer to the codec context for the video stream
  // and find the decoder for the video stream
  pCodecCtx = pFormatCtx->streams[0]->codec;
  pCodec    = avcodec_find_decoder(pCodecCtx->codec_id);
  
  // 1.5. Open Codec
  avcodec_open2(pCodecCtx, pCodec, NULL); 
  
  
  // 2.1.1. Prepare format conversion for diplaying with SDL
  // Allocate an AVFrame structure
  pFrame_YUV420P = avcodec_alloc_frame();
  if(pFrame_YUV420P == NULL) {
    fprintf(stderr, "Could not allocate pFrame_YUV420P\n");
    return -1;
  }
  // Determine required buffer size and allocate buffer
  buffer_YUV420P = (uint8_t *)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, 
                                            pCodecCtx->width, pCodecCtx->height));  
  // Assign buffer to image planes
  avpicture_fill((AVPicture *)pFrame_YUV420P, buffer_YUV420P, 
                      PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
  // format conversion context
  pConvertCtx_YUV420P = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, 
                                       pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, 
                                       SWS_SPLINE, NULL, NULL, NULL);
  
  // 2.2.1. Prepare format conversion for OpenCV
  // Allocate an AVFrame structure
  pFrame_BGR24 = avcodec_alloc_frame();
  if(pFrame_BGR24 == NULL) {
    fprintf(stderr, "Could not allocate pFrame_YUV420P\n");
    return -1;
  }
  // Determine required buffer size and allocate buffer
  buffer_BGR24 = (uint8_t *)av_malloc(avpicture_get_size(PIX_FMT_BGR24, 
                                            pCodecCtx->width, pCodecCtx->height));  
  // Assign buffer to image planes
  avpicture_fill((AVPicture *)pFrame_BGR24, buffer_BGR24, 
                      PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height);
  // format conversion context
  pConvertCtx_BGR24 = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, 
                                     pCodecCtx->width, pCodecCtx->height, PIX_FMT_BGR24, 
                                     SWS_SPLINE, NULL, NULL, NULL);
  
  // 3.1.1 prepare SDL for YUV
  // allocate window, renderer, texture
  pWindow1    = SDL_CreateWindow( "YUV", 0, 0, pCodecCtx->width, pCodecCtx->height, SDL_WINDOW_SHOWN);  
  pRenderer1  = SDL_CreateRenderer(pWindow1, -1, SDL_RENDERER_ACCELERATED);
  bmpTex1     = SDL_CreateTexture(pRenderer1, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, pCodecCtx->width, pCodecCtx->height);
  size1       = pCodecCtx->width * pCodecCtx->height;
  if(pWindow1==NULL | pRenderer1==NULL | bmpTex1==NULL) {
    fprintf(stderr, "Could not open window1\n%s\n", SDL_GetError());
    return -1;
  }
  
  // 3.2.1 prepare SDL for BGR
  // allocate window, renderer, texture
  pWindow2    = SDL_CreateWindow( "BGR", pCodecCtx->width+5, 0, pCodecCtx->width, pCodecCtx->height, SDL_WINDOW_SHOWN);  
  pRenderer2  = SDL_CreateRenderer(pWindow2, -1, SDL_RENDERER_ACCELERATED);
  bmpTex2     = SDL_CreateTexture(pRenderer2, SDL_PIXELFORMAT_BGR24, SDL_TEXTUREACCESS_STREAMING, pCodecCtx->width, pCodecCtx->height);
  size2       = pCodecCtx->width * pCodecCtx->height * 3;
  if(pWindow2==NULL | pRenderer2==NULL | bmpTex2==NULL) {
    fprintf(stderr, "Could not open window2\n%s\n", SDL_GetError());
    return -1;
  }
  
  // 1.6. get video frames
  pFrame = avcodec_alloc_frame();
  terminate = 0;
  while(!terminate) {
    // read frame
    if(av_read_frame(pFormatCtx, &packet)<0) {
      fprintf(stderr, "Could not read frame!\n");
      continue;
    }
    
    // decode the frame
    if(avcodec_decode_video2(pCodecCtx, pFrame, &frameDecoded, &packet) < 0) {
      fprintf(stderr, "Could not decode frame!\n");
      continue;
    }
    
    if (frameDecoded) {
      // 2.1.2. convert frame to YUV for Displaying
        sws_scale(pConvertCtx_YUV420P, (const uint8_t * const*)pFrame->data, pFrame->linesize, 0,
                  pCodecCtx->height,   pFrame_YUV420P->data, pFrame_YUV420P->linesize);
      // 2.2.2. convert frame to GRAYSCALE [or BGR] for OpenCV
        sws_scale(pConvertCtx_BGR24,   (const uint8_t * const*)pFrame->data, pFrame->linesize, 0,
                  pCodecCtx->height,   pFrame_BGR24->data,   pFrame_BGR24->linesize);

// 3.1.2. copy converted YUV to SDL 2.0 texture
      SDL_LockTexture(bmpTex1, NULL, (void **)&pixels1, &pitch1);
     memcpy(pixels1,             pFrame_YUV420P->data[0], size1  );
     memcpy(pixels1 + size1,     pFrame_YUV420P->data[2], size1/4);
   memcpy(pixels1 + size1*5/4, pFrame_YUV420P->data[1], size1/4);
      SDL_UnlockTexture(bmpTex1);
      SDL_UpdateTexture(bmpTex1, NULL, pixels1, pitch1);
      // refresh screen
      SDL_RenderClear(pRenderer1);
      SDL_RenderCopy(pRenderer1, bmpTex1, NULL, NULL);
      SDL_RenderPresent(pRenderer1);
      
      // 3.2.2. copy converted BGR to SDL 2.0 texture
      SDL_LockTexture(bmpTex2, NULL, (void **)&pixels2, &pitch2);
     memcpy(pixels2,             pFrame_BGR24->data[0], size2);
      SDL_UnlockTexture(bmpTex2);
      SDL_UpdateTexture(bmpTex2, NULL, pixels2, pitch2);
      // refresh screen
      SDL_RenderClear(pRenderer2);
      SDL_RenderCopy(pRenderer2, bmpTex2, NULL, NULL);
      SDL_RenderPresent(pRenderer2);
    }
    
    SDL_PollEvent(&event);
    switch (event.type) {
      case SDL_KEYDOWN:
        terminate = 1;
        break;
    }
  }
  
  // release
  // *note SDL objects have to be freed before closing avcodec.
  // otherwise it causes segmentation fault for some reason.
  SDL_DestroyTexture(bmpTex1);
  SDL_DestroyTexture(bmpTex2);
  
  SDL_DestroyRenderer(pRenderer1);
  SDL_DestroyRenderer(pRenderer2);
  
  SDL_DestroyWindow(pWindow1);
  SDL_DestroyWindow(pWindow2);
  
  av_free(pFrame_YUV420P);
  av_free(buffer_YUV420P);
  sws_freeContext(pConvertCtx_YUV420P);
  
  av_free(pFrame_BGR24);
  av_free(buffer_BGR24);
  sws_freeContext(pConvertCtx_BGR24);
  
  av_free(pFrame);
  avcodec_close(pCodecCtx); // <- before freeing this, all other objects, allocated after this, must be freed
  avformat_close_input(&pFormatCtx);
  
  SDL_Quit();
  
  return 0;
  
}

sdl2.0示例的更多相关文章

  1. SDL2.0 VLC ubuntu安装和黑屏问题

    开发环境安装: 1,执行:"sudo apt-get build-dep libsdl1.2",确定依赖库都装全了. sdl2.0没有正式发布到ubuntu,使用下面方法安装: h ...

  2. Win7 64位 MinGW环境测试SDL2.0.3

    下载MinGW版的文件 http://www.libsdl.org/release/SDL2-devel-2.0.3-mingw.tar.gz 解压放到mysys下面 运行Makefile mysys ...

  3. win8.1下golang+sdl2.0环境搭建

    sdl2.0的golang绑定我是使用的这个,但是它的官方介绍里面只有linux以及OSX系统的说明,没有windows的,在我的mbp上弄好以后就考虑在win下也搭建一个开发环境,这样就能比较方便的 ...

  4. SDL2.0学习

    http://www.ffmpeg.org/download.html http://doc.okbase.net/leixiaohua1020/archive/110977.html  //视频 h ...

  5. [原]如何在Android用FFmpeg+SDL2.0解码图像线程

    关于如何在Android上用FFmpeg+SDL2.0解码显示图像参考[原]如何在Android用FFmpeg+SDL2.0解码显示图像 ,关于如何在Android使用FFmpeg+SDL2.0解码声 ...

  6. [原]如何在Android用FFmpeg+SDL2.0解码声音

    关于如何在Android上用FFmpeg+SDL2.0解码显示图像参考[原]如何在Android用FFmpeg+SDL2.0解码显示图像 ,本文是基于上述文章和[原]零基础学习视频解码之解码声音 来移 ...

  7. [原]如何在Android用FFmpeg+SDL2.0解码显示图像

    如何在Android上使用FFmpeg解码图像参考文章[原]如何在Android用FFmpeg解码图像 ,如何在Android上使用SDL2.0来显示图像参考[原]零基础学习SDL开发之在Androi ...

  8. SDL2.0的SDL_Event事件处理

    SDL_Event事件集合 SDL_AudioDeviceEvent SDL_ControllerAxisEvent SDL_ControllerButtonEvent SDL_ControllerD ...

  9. SDL2.0的几何图行绘画

    SDL2.0的几何图形绘画 通过SDL_Window.SDL_Renderer.SDL_Texture三者实现了简单的几何图形绘画. 包括了SDL_RenderDrawPoint.SDL_Render ...

随机推荐

  1. motan源码分析四:客户端调用服务

    在第一章中,我们分析了服务的发布与注册,本章中将简单的分析一下客户端调用服务的代码及流程,本文将以spring加载的方式进行分析. 1.在DemoRpcClient类的main()方法中加载类: Ap ...

  2. Zend框架2入门(一) (转)

    By Rob Allen, www.akrabat.com 修订0.1.2文件版权所有? 2011本教程的目的是给创建一个简单的数据库的介绍使用Zend Framework 2驱动的应用程序使用模型 ...

  3. Java虚拟机内存区域堆(heap)的管理

    在上一节中Java 出现内存溢出的定位以及解决方案 中对于Java虚拟机栈以及方法区的内存出现的异常以及处理方式进行了解析,由于Java虚拟机对于堆的管理十分复杂,并且Java虚拟机中最基本的内存区域 ...

  4. VS2008 动态库和静态库的生成和加载

    第一:动态库和静态库的生成: 1) 新建一个生成dll工程: 文件->新建->项目->Win32->Win32控制台应用程序 输入项目名称:dllTest ,项目路径:D:\V ...

  5. shell 中条件判断

    if 中的 -z 到 -d 的意思 2011-09-05 10:30 [ -a FILE ] 如果 FILE 存在则为真. [ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真. [  ...

  6. 跟我一起学PCL打印语言(一)

    引言 本人从事打印机开发和打印驱动开发的相关工作,深感资料特别是中文资料的匮乏和不成系统,对新入门的从事该行业的人来说,门槛很高.在这里一方面是将开发中遇到的相关知识点整理出来,另一方面也能够促进自己 ...

  7. Java基础知识强化74:正则表达式之分割功能 (扩展练习)

    1. 看程序写结果:(面试题考过) package cn.itcast_03; /* * 分割功能练习 */ public class RegexDemo2 { public static void ...

  8. NYOJ 980 格子刷油漆 动态规划

    这道题目状态转移方程比较复杂,刚开始以为没这么多情况,看了好多大牛的博客再加上与同学讨论才看懂,写下心得. 因为起点不固定,所以我们一个一个来考虑,先从角上考虑,设三个数组来表示分别为D,A,Sum, ...

  9. FineUI页面级别的参数配置

    Theme: 控件主题,目前支持三种主题风格(blue/gray/access,默认值:blue) Language: 控件语言(en/zh_CN/zh_TW/...,默认值:zh_CN) FormM ...

  10. “The SQL Server license agreenment cannot be located for the selected edition.”MSSQL安装问题

    今天老邹又来吐槽了.今天不和IE7较劲了.说点别的吧. 我呢什么软件都喜欢装最新版的,这部刚出来windows 8.1就赶紧装上了,随后就用上了vs2013.前天看到新闻说微软已经发布了sql ser ...