ffmpeg+sdl教程----编写一个简单的播放器2(输出视频到屏幕)

来源:http://blog.csdn.net/mu399/article/details/5814859

下面完整代码,在vc2005下编译通过。可以看到,程序运行后视频播放出来了,但是由于没有加入播放延迟,视频简直跑疯了,为视频加入延迟将在教程五中实现,目前可以简单地让程序在播放完一帧后,sleep若干秒,改善一下运行状况。

[cpp] view plaincopy

  1. // ffmpegExe.cpp: 主项目文件。
  2. #include "stdafx.h"
  3. #include "libavformat/avformat.h"
  4. #include "libswscale/swscale.h"
  5. //#include <windows.h>
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <math.h>
  10. #include <SDL/SDL.h>
  11. #ifdef main
  12. #undef main
  13. #endif
  14. #define SDL_AUDIO_BUFFER_SIZE 1024
  15. static int sws_flags = SWS_BICUBIC;
  16. int main(int argc, char *argv[])
  17. {
  18. AVFormatContext *pFormatCtx;
  19. int i, videoStream(-1);
  20. AVCodecContext *pCodecCtx;
  21. AVCodec *pCodec;
  22. AVFrame *pFrame;
  23. AVPacket packet;
  24. int frameFinished;
  25. float aspect_ratio;
  26. AVCodecContext *aCodecCtx;
  27. SDL_Overlay *bmp;
  28. SDL_Surface *screen;
  29. SDL_Rect rect;
  30. SDL_Event event;
  31. if(argc < 2)
  32. {
  33. fprintf(stderr, "Usage: test /n");
  34. exit(1);
  35. }
  36. av_register_all();
  37. pFormatCtx = av_alloc_format_context();
  38. if (!pFormatCtx) {
  39. fprintf(stderr, "Memory error/n");
  40. exit(1);
  41. }
  42. if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)
  43. return -1; // Couldn‘t open file
  44. if(av_find_stream_info(pFormatCtx)<0)
  45. return -1; // Couldn‘t find stream information
  46. // Dump information about file onto standard error
  47. dump_format(pFormatCtx, 0, argv[1], 0);
  48. // Find the first video stream
  49. for(i=0; i<pFormatCtx->nb_streams; i++)
  50. {
  51. if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO && videoStream<0)
  52. {
  53. videoStream=i;
  54. }
  55. }
  56. if(videoStream==-1)
  57. return -1; // Didn‘t find a video stream
  58. // Get a pointer to the codec context for the video stream
  59. pCodecCtx=pFormatCtx->streams[videoStream]->codec;
  60. pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
  61. if(pCodec==NULL)
  62. {
  63. fprintf(stderr, "Unsupported codec!/n");
  64. return -1; // Codec not found
  65. }
  66. // Open codec
  67. if(avcodec_open(pCodecCtx, pCodec)<0)
  68. return -1; // Could not open codec
  69. // Allocate video frame
  70. pFrame=avcodec_alloc_frame();
  71. uint8_t *buffer;
  72. int numBytes;
  73. // Determine required buffer size and allocate buffer
  74. numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,
  75. pCodecCtx->height);
  76. buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
  77. if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER))
  78. {
  79. fprintf(stderr, "Could not initialize SDL - %s/n", SDL_GetError());
  80. exit(1);
  81. }
  82. #ifndef __DARWIN__
  83. screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);
  84. #else
  85. screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 24, 0);
  86. #endif
  87. if(!screen)
  88. {
  89. fprintf(stderr, "SDL: could not set video mode - exiting/n");
  90. exit(1);
  91. }
  92. bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height,
  93. SDL_YV12_OVERLAY, screen);
  94. static struct SwsContext *img_convert_ctx;
  95. if (img_convert_ctx == NULL)
  96. {
  97. img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
  98. pCodecCtx->pix_fmt,
  99. pCodecCtx->width, pCodecCtx->height,
  100. PIX_FMT_YUV420P,
  101. sws_flags, NULL, NULL, NULL);
  102. if (img_convert_ctx == NULL)
  103. {
  104. fprintf(stderr, "Cannot initialize the conversion context/n");
  105. exit(1);
  106. }
  107. }
  108. i=0;
  109. while(av_read_frame(pFormatCtx, &packet)>=0)
  110. {
  111. // Is this a packet from the video stream?
  112. if(packet.stream_index==videoStream)
  113. {
  114. // Decode video frame
  115. avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,
  116. packet.data, packet.size);
  117. // Did we get a video frame?
  118. if(frameFinished)
  119. {
  120. // Convert the image from its native format to RGB
  121. /*sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize,
  122. 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);*/
  123. // Save the frame to disk
  124. /*if(++i<=5)
  125. SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);*/
  126. SDL_LockYUVOverlay(bmp);
  127. AVPicture pict;
  128. pict.data[0] = bmp->pixels[0];
  129. pict.data[1] = bmp->pixels[2];
  130. pict.data[2] = bmp->pixels[1];
  131. pict.linesize[0] = bmp->pitches[0];
  132. pict.linesize[1] = bmp->pitches[2];
  133. pict.linesize[2] = bmp->pitches[1];
  134. // Convert the image into YUV format that SDL uses
  135. /*img_convert(&pict, PIX_FMT_YUV420P,
  136. (AVPicture *)pFrame, pCodecCtx->pix_fmt,
  137. pCodecCtx->width, pCodecCtx->height);*/
  138. sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize,
  139. 0, pCodecCtx->height, pict.data, pict.linesize);
  140. SDL_UnlockYUVOverlay(bmp);
  141. rect.x = 0;
  142. rect.y = 0;
  143. rect.w = pCodecCtx->width;
  144. rect.h = pCodecCtx->height;
  145. SDL_DisplayYUVOverlay(bmp, &rect);
  146. //Sleep(60);
  147. }
  148. }
  149. // Free the packet that was allocated by av_read_frame
  150. av_free_packet(&packet);
  151. SDL_PollEvent(&event);
  152. switch(event.type)
  153. {
  154. case SDL_QUIT:
  155. SDL_Quit();
  156. exit(0);
  157. break;
  158. default: break;
  159. }
  160. };
  161. // Free the RGB image
  162. av_free(buffer);
  163. //av_free(pFrameRGB);
  164. // Free the YUV frame
  165. av_free(pFrame);
  166. // Close the codec
  167. avcodec_close(pCodecCtx);
  168. // Close the video file
  169. av_close_input_file(pFormatCtx);
  170. return 0;
  171. }
时间: 2024-10-11 11:08:32

ffmpeg+sdl教程----编写一个简单的播放器2(输出视频到屏幕)的相关文章

ffmpeg+sdl教程----编写一个简单的播放器5(同步视频到音频)

来源:http://blog.csdn.net/mu399/article/details/5816566 个人认为,这这部分教程的新增代码量虽然不是最多的,难度却是最大的,重复看了多次才明白,因为有两个问题的困扰,搞得还不清楚: 1.音频和视频既然都有各自的时间戳,各自按各自的时间戳来播放不就行了,为什么还需要同步呢? 2.如果要把视频同步到音频,怎么同步?或者说以什么标准来同步? 第一个问题的答案可能是,一是音频和视频的开始播放的时间是不一样,二是播放每帧音频或视频时可能必须把解码数据,视频

ffmpeg+sdl教程----编写一个简单的播放器3(为视频加入音频)

来源:http://blog.csdn.net/mu399/article/details/5814901 上个教程实现了视频的简单播放,但那是个哑巴电影,完全没有声音. 这个教程第一次用到了SDL的线程,涉及到了两个线程间的同步协调,有几个地方需要特别留意,SDL_OpenAudio库函数会打开音频设备(0是恢 复,其他的是暂停),SDL_PauseAudio库函数可以暂停或者恢复audio_callback函数的执行,程序中的这行代码 “SDL_PauseAudio(0);”执行后,让aud

ffmpeg+sdl教程----编写一个简单的播放器4(让程序更模块化)

来源:http://blog.csdn.net/mu399/article/details/5815444 音频和视频之间的同步,再那之前需要先做一些准备工作. 为了让程序更模块化,便于扩展,需要把原来main函数中的各个功能模块代码分离出来放在相应的函数中.该教程和上个教程相比代码量和难度都增加很多,比上个教程使用了更多的线程,一定要理解清楚各个函数和数据结构之间的关联以及线程之间如何协同工作. [c-sharp] view plaincopy // ffmpegExe.cpp: 主项目文件.

ffmpeg+sdl教程----编写一个简单的播放器6(其他的时钟同步方式)

来源:http://blog.csdn.net/mu399/article/details/5818384 在理解上一个教程的基础上,这篇教程就稍微容易理解些了,不外乎多加了两种同步方式,同步音频到视频,同步音频视频到外部时钟. 这篇教程主要是新增了不少新变量,is->video_current_pts用于保存当前视频帧的时间戳(以秒为单位),只在 video_refresh_timer函数中播放一帧视频前改变,is->video_current_pts_time单位为毫秒,在 stream_

ffmpeg+sdl教程----编写一个简单的播放器7(处理快进快退命令)

来源:http://blog.csdn.net/mu399/article/details/5818970 这篇教程例子中的程序,让右方向按键为快进10秒,上方向按键为快进60秒,左方向按键为快退10秒,上方向按键为快退60秒,程序中的 av_seek_frame函数可能是用错了,或者函数本身的问题导致按上和右都没反应;按左和下让画面暂停,声音在很短区间内不停播放,这时再按右和下 才正常. [cpp] view plaincopy #include "libavformat/avformat.h

可视化程序设计基础(三)——一个简单的播放器(并不)

本次的作业是制作一个简单的播放器,功能仅限于播放视频和音频,虽说是简单的播放器,但其中还是有很多细节需要注意的. 问题一:布局 本来这个问题不应该是一个问题了,之前老师讲过的Stackpanel和Grid等对于布局一个播放器来说绰绰有余,但上次上课老师提到的NavigationView令我十分感兴趣,这是一个uwp应用程序中随处可见的一种布局,节省了开发者很多的时间. 所以我就着手于建立这个NavigationView了,首先我看了一下XAML Controls Gallery,然而其中关于Na

[SimplePlayer] 实现一个简单的播放器

简单的播放器需要实现一个最基本的功能:播放视频文件. 实现这个功能需要包含以下几个步骤: 从视频文件中提取视频图像 在屏幕上显示视频图像 视频帧的同步,也就是保证视频图像在合适的时间在屏幕上显示 从视频文件中提取音频 向音频设备输出音频 音频同步,也就是保证合适的时间输出合适的音频 多线程处理 音视频同步 本实现是通过ffmpeg来实现音视频的提取,通过sdl2来实现音视频的输出,版本如下: libavutil 56. 19.100 / 56. 19.100 libavcodec 58. 23.

qt实现一个简单的播放器

ui界面设计如下: 2.代码结构 3.dialog.cpp #include "dialog.h" #include "ui_dialog.h" #include<QStringList> #include<QDebug> Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); ui->lb_dis->

Android开发6:Service的使用(简单音乐播放器的实现)

前言 啦啦啦~各位好久不见啦~博主最近比较忙,而且最近一次实验也是刚刚结束~ 好了不废话了,直接进入我们这次的内容~ 在这篇博文里我们将学习Service(服务)的相关知识,学会使用 Service 进行后台工作, 学会使用 Service 与 Activity 进行通信,并在此知识基础上学会使用 MediaPlayer和简单的多线程编程.使用 Handle 更新 UI,并设计成功一个简单的音乐播放器. 是不是很高大上呢~一起来学习~ 基础知识 Service作为Android四大组件之一,在每