gsd_img_mpeg.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. /*!
  2. \file gsd_img_mpeg.c
  3. \brief OGSF library - FFMPEG stuff
  4. GRASS OpenGL gsurf OGSF Library
  5. (C) 1999-2008 by the GRASS Development Team
  6. This program is free software under the
  7. GNU General Public License (>=v2).
  8. Read the file COPYING that comes with GRASS
  9. for details.
  10. \author Bill Brown USACERL, GMSL/University of Illinois
  11. \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
  12. */
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <grass/gis.h>
  16. #include <grass/glocale.h>
  17. #include <grass/ogsf.h>
  18. /* FFMPEG stuff */
  19. #ifdef HAVE_FFMPEG
  20. #include <avformat.h>
  21. /* 5 seconds stream duration */
  22. #define STREAM_DURATION 5.0
  23. #define STREAM_FRAME_RATE 25 /* 25 images/s */
  24. #define STREAM_NB_FRAMES ((int)(STREAM_DURATION * STREAM_FRAME_RATE))
  25. #define STREAM_PIX_FMT PIX_FMT_YUV420P /* default pix_fmt */
  26. AVFrame *picture, *tmp_picture;
  27. uint8_t *video_outbuf;
  28. int frame_count, video_outbuf_size;
  29. AVOutputFormat *fmt;
  30. AVFormatContext *oc;
  31. AVStream *video_st;
  32. /*!
  33. \brief Add a video output stream
  34. \param oc
  35. \param codec_id
  36. \param w
  37. \param h
  38. \return
  39. */
  40. static AVStream *add_video_stream(AVFormatContext * oc, int codec_id, int w,
  41. int h)
  42. {
  43. AVCodecContext *c;
  44. AVStream *st;
  45. st = av_new_stream(oc, 0);
  46. if (!st) {
  47. G_warning(_("Unable to allocate stream"));
  48. return NULL;
  49. }
  50. c = st->codec;
  51. c->codec_id = codec_id;
  52. c->codec_type = CODEC_TYPE_VIDEO;
  53. /* put sample parameters */
  54. c->bit_rate = 400000;
  55. /* resolution must be a multiple of two */
  56. c->width = w;
  57. c->height = h;
  58. /* time base: this is the fundamental unit of time (in seconds) in terms
  59. of which frame timestamps are represented. for fixed-fps content,
  60. timebase should be 1/framerate and timestamp increments should be
  61. identically 1. */
  62. c->time_base.den = STREAM_FRAME_RATE;
  63. c->time_base.num = 1;
  64. c->gop_size = 12; /* emit one intra frame every twelve frames at most */
  65. c->pix_fmt = STREAM_PIX_FMT;
  66. if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
  67. /* just for testing, we also add B frames */
  68. c->max_b_frames = 2;
  69. }
  70. if (c->codec_id == CODEC_ID_MPEG1VIDEO) {
  71. /* Needed to avoid using macroblocks in which some coeffs overflow.
  72. This does not happen with normal video, it just happens here as
  73. the motion of the chroma plane does not match the luma plane. */
  74. c->mb_decision = 2;
  75. }
  76. /* some formats want stream headers to be separate */
  77. if (!strcmp(oc->oformat->name, "mp4") || !strcmp(oc->oformat->name, "mov")
  78. || !strcmp(oc->oformat->name, "3gp"))
  79. c->flags |= CODEC_FLAG_GLOBAL_HEADER;
  80. c->flags |= CODEC_FLAG_QSCALE;
  81. c->global_quality = st->quality = FF_QP2LAMBDA * 10;
  82. return st;
  83. }
  84. /*!
  85. \brief Allocate picture
  86. \param pix_fmt
  87. \param width picture width
  88. \param height picture height
  89. \return pointer to AVFrame struct
  90. \return NULL on failure
  91. */
  92. static AVFrame *alloc_picture(int pix_fmt, int width, int height)
  93. {
  94. AVFrame *picture;
  95. uint8_t *picture_buf;
  96. int size;
  97. picture = avcodec_alloc_frame();
  98. if (!picture)
  99. return NULL;
  100. size = avpicture_get_size(pix_fmt, width, height);
  101. picture_buf = av_malloc(size);
  102. if (!picture_buf) {
  103. av_free(picture);
  104. return NULL;
  105. }
  106. avpicture_fill((AVPicture *) picture, picture_buf,
  107. pix_fmt, width, height);
  108. return picture;
  109. }
  110. /*!
  111. \brief Open video
  112. \param oc
  113. \param st
  114. */
  115. static void open_video(AVFormatContext * oc, AVStream * st)
  116. {
  117. AVCodec *codec;
  118. AVCodecContext *c;
  119. c = st->codec;
  120. /* find the video encoder */
  121. codec = avcodec_find_encoder(c->codec_id);
  122. if (!codec) {
  123. G_warning(_("Video codec not found"));
  124. return;
  125. }
  126. /* open the codec */
  127. if (avcodec_open(c, codec) < 0) {
  128. G_warning(_("Unable to open codec"));
  129. return;
  130. }
  131. video_outbuf = NULL;
  132. if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
  133. /* allocate output buffer */
  134. /* XXX: API change will be done */
  135. /* buffers passed into lav* can be allocated any way you prefer,
  136. as long as they're aligned enough for the architecture, and
  137. they're freed appropriately (such as using av_free for buffers
  138. allocated with av_malloc) */
  139. video_outbuf_size = 200000;
  140. video_outbuf = av_malloc(video_outbuf_size);
  141. }
  142. /* allocate the encoded raw picture */
  143. picture = alloc_picture(c->pix_fmt, c->width, c->height);
  144. if (!picture) {
  145. G_warning(_("Unable to allocate picture"));
  146. return;
  147. }
  148. /* if the output format is not YUV420P, then a temporary YUV420P
  149. picture is needed too. It is then converted to the required
  150. output format */
  151. tmp_picture = NULL;
  152. if (c->pix_fmt != PIX_FMT_YUV420P) {
  153. tmp_picture = alloc_picture(PIX_FMT_YUV420P, c->width, c->height);
  154. if (!tmp_picture) {
  155. G_warning(_("Unable to allocate temporary picture"));
  156. return;
  157. }
  158. }
  159. }
  160. /*!
  161. \brief Write video frame
  162. \param oc
  163. \param st
  164. */
  165. static void write_video_frame(AVFormatContext * oc, AVStream * st)
  166. {
  167. int out_size, ret;
  168. AVCodecContext *c;
  169. c = st->codec;
  170. if (oc->oformat->flags & AVFMT_RAWPICTURE) {
  171. /* raw video case. The API will change slightly in the near
  172. future for that */
  173. AVPacket pkt;
  174. av_init_packet(&pkt);
  175. pkt.flags |= PKT_FLAG_KEY;
  176. pkt.stream_index = st->index;
  177. pkt.data = (uint8_t *) picture;
  178. pkt.size = sizeof(AVPicture);
  179. ret = av_write_frame(oc, &pkt);
  180. }
  181. else {
  182. /* encode the image */
  183. out_size =
  184. avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture);
  185. /* if zero size, it means the image was buffered */
  186. if (out_size > 0) {
  187. AVPacket pkt;
  188. av_init_packet(&pkt);
  189. pkt.pts =
  190. av_rescale_q(c->coded_frame->pts, c->time_base,
  191. st->time_base);
  192. if (c->coded_frame->key_frame)
  193. pkt.flags |= PKT_FLAG_KEY;
  194. pkt.stream_index = st->index;
  195. pkt.data = video_outbuf;
  196. pkt.size = out_size;
  197. /* write the compressed frame in the media file */
  198. ret = av_write_frame(oc, &pkt);
  199. }
  200. else {
  201. ret = 0;
  202. }
  203. }
  204. if (ret != 0) {
  205. G_warning(_("Error while writing video frame"));
  206. return;
  207. }
  208. frame_count++;
  209. }
  210. /*!
  211. \brief Close video
  212. \param oc [unused]
  213. \param st
  214. */
  215. static void close_video(AVFormatContext * oc, AVStream * st)
  216. {
  217. avcodec_close(st->codec);
  218. av_free(picture->data[0]);
  219. av_free(picture);
  220. if (tmp_picture) {
  221. av_free(tmp_picture->data[0]);
  222. av_free(tmp_picture);
  223. }
  224. av_free(video_outbuf);
  225. }
  226. #endif
  227. /*!
  228. \brief Initialize FAME setup mpeg defaults and open file for writing
  229. \param filename file name
  230. \return -1 on failure
  231. \return 0 on success
  232. */
  233. int gsd_init_mpeg(const char *filename)
  234. {
  235. #ifdef HAVE_FFMPEG
  236. GLuint l, r, b, t;
  237. GLint tmp[4];
  238. glGetIntegerv(GL_VIEWPORT, tmp);
  239. l = tmp[0];
  240. r = tmp[0] + tmp[2] - 1;
  241. b = tmp[1];
  242. t = tmp[1] + tmp[3] - 1;
  243. G_verbose_message(_("Opening MPEG stream <%s>..."), filename);
  244. /* initialize libavcodec, and register all codecs and formats */
  245. av_register_all();
  246. /* auto detect the output format from the name. default is mpeg. */
  247. fmt = guess_format(NULL, filename, NULL);
  248. if (!fmt) {
  249. G_warning(_("Unable to deduce output format from file extension: using MPEG"));
  250. fmt = guess_format("mpeg", NULL, NULL);
  251. }
  252. if (!fmt) {
  253. G_warning(_("Unable to find suitable output format"));
  254. return (-1);
  255. }
  256. /* allocate the output media context */
  257. oc = av_alloc_format_context();
  258. if (!oc) {
  259. G_warning(_("Out of memory"));
  260. return (-1);
  261. }
  262. oc->oformat = fmt;
  263. snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
  264. /* if you want to hardcode the codec (eg #ifdef USE_XVID)
  265. this may be the place to do it (?????) */
  266. #ifdef USE_XVID
  267. fmt->video_codec = CODEC_ID_XVID;
  268. #endif
  269. video_st = NULL;
  270. if (fmt->video_codec != CODEC_ID_NONE) {
  271. video_st =
  272. add_video_stream(oc, fmt->video_codec, (r - l + 1), (t - b + 1));
  273. }
  274. /* set the output parameters (must be done even if no parameters). */
  275. if (av_set_parameters(oc, NULL) < 0) {
  276. G_warning(_("Invalid output format parameters"));
  277. return (-1);
  278. }
  279. dump_format(oc, 0, filename, 1);
  280. /* now that all the parameters are set, we can open the audio and
  281. video codecs and allocate the necessary encode buffers */
  282. if (video_st)
  283. open_video(oc, video_st);
  284. /* open the output file, if needed */
  285. if (!(fmt->flags & AVFMT_NOFILE)) {
  286. if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) {
  287. G_warning(_("Unable to open <%s>"), filename);
  288. return (-1);
  289. }
  290. }
  291. /* write the stream header, if any */
  292. av_write_header(oc);
  293. #else
  294. G_warning(_("NVIZ has not been built with MPEG output support"));
  295. return (-1);
  296. #endif
  297. return (0);
  298. }
  299. /*!
  300. \brief Get RGB pixbuf and convert to YUV 4:2:0
  301. Image and write to mpeg stream
  302. \return 0
  303. */
  304. int gsd_write_mpegframe(void)
  305. {
  306. #ifdef HAVE_FFMPEG
  307. unsigned int xsize, ysize;
  308. int x, y, xy, xy_uv;
  309. int yy, uu, vv;
  310. unsigned char *pixbuf;
  311. gsd_getimage(&pixbuf, &xsize, &ysize);
  312. xy = xy_uv = 0;
  313. for (y = ysize - 1; y >= 0; y--) {
  314. for (x = 0; x < xsize; x++) {
  315. unsigned char r = pixbuf[(y * xsize + x) * 4 + 0];
  316. unsigned char g = pixbuf[(y * xsize + x) * 4 + 1];
  317. unsigned char b = pixbuf[(y * xsize + x) * 4 + 2];
  318. yy = (0.257 * r) + (0.504 * g) + (0.098 * b) + 16;;
  319. vv = (0.439 * r) - (0.368 * g) - (0.071 * b) + 128;
  320. uu = -(0.148 * r) - (0.291 * g) + (0.439 * b) + 128;
  321. fflush(stdout);
  322. picture->data[0][xy] = yy;
  323. if ((x % 2) && (y % 2)) {
  324. picture->data[1][xy_uv] = uu;
  325. picture->data[2][xy_uv] = vv;
  326. xy_uv++;
  327. }
  328. xy++;
  329. }
  330. }
  331. G_free(pixbuf);
  332. write_video_frame(oc, video_st);
  333. #endif
  334. return (0);
  335. }
  336. /*!
  337. \brief Close the mpeg, free buffer, and close file
  338. \return 0
  339. */
  340. int gsd_close_mpeg(void)
  341. {
  342. #ifdef HAVE_FFMPEG
  343. int i;
  344. close_video(oc, video_st);
  345. /* write the trailer, if any */
  346. av_write_trailer(oc);
  347. /* free the streams */
  348. for (i = 0; i < oc->nb_streams; i++) {
  349. av_freep(&oc->streams[i]->codec);
  350. av_freep(&oc->streams[i]);
  351. }
  352. if (!(fmt->flags & AVFMT_NOFILE)) {
  353. /* close the output file */
  354. #if (LIBAVFORMAT_VERSION_INT>>16) < 52
  355. url_fclose(&oc->pb);
  356. #else
  357. url_fclose(oc->pb);
  358. #endif
  359. }
  360. /* free the stream */
  361. av_free(oc);
  362. G_debug(3, "Closed MPEG stream");
  363. #endif
  364. return (0);
  365. }