gsd_img_mpeg.c 10 KB

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