container.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. // SPDX-License-Identifier: LGPL-2.1 OR BSD-3-Clause
  2. //--=========================================================================--
  3. // This file is a part of VPU Reference API project
  4. //-----------------------------------------------------------------------------
  5. //
  6. // This confidential and proprietary software may be used only
  7. // as authorized by a licensing agreement from Chips&Media Inc.
  8. // In the event of publication, the following notice is applicable:
  9. //
  10. // (C) COPYRIGHT 2006 - 2013 CHIPS&MEDIA INC.
  11. // ALL RIGHTS RESERVED
  12. //
  13. // The entire notice above must be reproduced on all authorized
  14. // copies.
  15. //
  16. //--=========================================================================--
  17. #include <stdio.h>
  18. #include "main_helper.h"
  19. /* make container */
  20. #if 0//def SUPPORT_FFMPEG_DEMUX
  21. #include <libavformat/avformat.h>
  22. #include <libavcodec/avcodec.h>
  23. /* add a video output stream */
  24. static AVStream *add_stream(AVFormatContext *oc, int codec_id, EncConfigParam encConfig, int gopSize)
  25. {
  26. AVCodecContext *c;
  27. AVStream *st;
  28. st = avformat_new_stream(oc, 0);
  29. if (!st) {
  30. VLOG(ERR, "Could not alloc stream\n");
  31. return 0;
  32. }
  33. st->id = oc->nb_streams-1;
  34. c = st->codec;
  35. c->codec_id = codec_id;
  36. c->codec_type = AVMEDIA_TYPE_VIDEO;
  37. /* put sample parameters */
  38. c->bit_rate = encConfig.kbps * 1000;
  39. /* resolution must be a multiple of two */
  40. c->width = (encConfig.rotAngle==90||encConfig.rotAngle ==270)?encConfig.picHeight:encConfig.picWidth;
  41. c->height = (encConfig.rotAngle==90||encConfig.rotAngle ==270)?encConfig.picWidth:encConfig.picHeight;
  42. /* time base: this is the fundamental unit of time (in seconds) in terms
  43. of which frame timestamps are represented. for fixed-fps content,
  44. timebase should be 1/framerate and timestamp increments should be
  45. identically 1. */
  46. c->time_base.den = encConfig.container_frame_rate;
  47. c->time_base.num = 1;
  48. c->gop_size = gopSize; /* emit one intra frame every (gop_size)frames at most */
  49. c->pix_fmt = PIX_FMT_YUV420P;
  50. if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
  51. /* just for testing, we also add B frames */
  52. c->max_b_frames = 2;
  53. }
  54. if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO){
  55. /* Needed to avoid using macroblocks in which some coeffs overflow.
  56. This does not happen with normal video, it just happens here as
  57. the motion of the chroma plane does not match the luma plane. */
  58. c->mb_decision=2;
  59. }
  60. // some formats want stream headers to be separate
  61. if(oc->oformat->flags & AVFMT_GLOBALHEADER)
  62. c->flags |= CODEC_FLAG_GLOBAL_HEADER;
  63. return st;
  64. }
  65. static int write_video_frame(AVFormatContext *oc, AVStream *st, unsigned char *addr, int size, int picType)
  66. {
  67. int ret;
  68. static struct SwsContext *img_convert_ctx;
  69. /* if zero size, it means the image was buffered */
  70. if (size > 0) {
  71. AVPacket pkt;
  72. av_init_packet(&pkt);
  73. if (picType == 0) //I Frame
  74. pkt.flags |= AV_PKT_FLAG_KEY;
  75. pkt.stream_index= st->index;
  76. pkt.data= addr;
  77. pkt.size= size;
  78. /* write the compressed frame in the media file */
  79. ret = av_interleaved_write_frame(oc, &pkt);
  80. }
  81. else
  82. ret = 0;
  83. if (ret != 0) {
  84. VLOG(ERR, "Error while writing video frame\n");
  85. return 0;
  86. }
  87. return 1;
  88. }
  89. /*
  90. * make a file and write a container's header part
  91. * must set -> en_container, container_frame_rate, gopSize, kbps, rotAngle, picHeight, picWidth,
  92. * stdMode and bitstreamFileName in struct EncConfigParam
  93. */
  94. int container_init(EncConfigParam encConfig,
  95. AVOutputFormat **fmt,
  96. AVFormatContext **oc,
  97. AVStream **video_st,
  98. int gopSize)
  99. {
  100. int stdMode = encConfig.stdMode;
  101. char *filename = encConfig.bitstreamFileName;
  102. unsigned int i;
  103. if (encConfig.ringBufferEnable == 1)
  104. {
  105. VLOG(ERR, "not supported format\n");
  106. return 0;
  107. }
  108. /* initialize libavcodec, and register all codecs and formats */
  109. av_register_all();
  110. /* allocate the output media context */
  111. if (avformat_open_input(oc, filename, NULL, NULL) < 0) {
  112. fprintf(stderr, "failed to avformat_open_input\n");
  113. return 0;
  114. }
  115. *fmt = (*oc)->oformat;
  116. if (stdMode == 0)
  117. (*fmt)->video_codec = AV_CODEC_ID_MPEG4;
  118. else if (stdMode == 1)
  119. (*fmt)->video_codec = AV_CODEC_ID_H263;
  120. else if (stdMode == 2)
  121. (*fmt)->video_codec = AV_CODEC_ID_H264;
  122. else
  123. VLOG(ERR, "unknown codec type = 0x%x\n", stdMode);
  124. (*oc)->video_codec_id = (*fmt)->video_codec;
  125. (*oc)->audio_codec_id = (*fmt)->audio_codec;
  126. /* add the audio and video streams using the default format codecs
  127. and initialize the codecs */
  128. *video_st = add_stream(*oc, (int)(*fmt)->video_codec, encConfig, gopSize);
  129. av_dump_format(*oc, 0, filename, 1);
  130. /* open the output file, if needed */
  131. if (avio_open(&(*oc)->pb, filename, AVIO_FLAG_WRITE) < 0) {
  132. VLOG(ERR, "Could not open '%s'\n", filename);
  133. for(i=0; i<(*oc)->nb_streams; i++) {
  134. av_freep(&(*oc)->streams[i]->codec);
  135. av_freep(&(*oc)->streams[i]);
  136. }
  137. /* free the stream */
  138. av_free(*oc);
  139. return 0;
  140. }
  141. /* write the stream header, if any */
  142. if (avformat_write_header(*oc, NULL) < 0) {
  143. VLOG(ERR, "Could not write header for output file (incorrect codec paramters ?)\n");
  144. /* free the streams */
  145. for(i=0; i<(*oc)->nb_streams; i++) {
  146. av_freep(&(*oc)->streams[i]->codec);
  147. av_freep(&(*oc)->streams[i]);
  148. }
  149. /* close the output file */
  150. avio_close((*oc)->pb);
  151. /* free the stream */
  152. av_free(*oc);
  153. *oc = NULL;
  154. return 0;
  155. }
  156. return 1;
  157. }
  158. /*
  159. * save the header data to temp_buf(header_buf). (instead of ReadBsResetBufHelper)
  160. */
  161. int container_copy_header_from_bitstream_buffer(const Uint32 core_idx,
  162. const PhysicalAddress bitstream,
  163. const int size,
  164. const int endian,
  165. char *buf,
  166. int *pos)
  167. {
  168. vdi_read_memory(core_idx, bitstream, (unsigned char *)(buf+(*pos)), size, endian);
  169. *pos += size;
  170. //to check memory boundary
  171. if (*pos >= CONTAINER_HEADER_SIZE)
  172. {
  173. VLOG(ERR, "exceed header buffer, header buffer size[%d]\n", *pos);
  174. return 0;
  175. }
  176. return 1;
  177. }
  178. /*
  179. * write the Element stream data with syntax header to the container file
  180. */
  181. int container_write_es(const Uint32 core_idx,
  182. const PhysicalAddress bitstream,
  183. const int size,
  184. const int endian,
  185. AVFormatContext *oc,
  186. AVStream *st,
  187. char *header_buffer,
  188. int *header_pos,
  189. int format,
  190. int picType)
  191. {
  192. unsigned char *buf = osal_malloc(size);
  193. if (!buf)
  194. {
  195. VLOG(ERR, "fail to allocate bitstream buffer\n");
  196. return 0;
  197. }
  198. vdi_read_memory(core_idx, bitstream, buf, size, endian);
  199. //video data = write only 1 SPS & PPS data in the file,
  200. //JPEG = copy jpeg header to every chunk in the file
  201. if (*header_pos)//I Frame || MJPEG
  202. {
  203. unsigned char *buf2 = osal_malloc(size + *header_pos);
  204. osal_memcpy(buf2, header_buffer, *header_pos);
  205. osal_memcpy(buf2 + *header_pos, buf, size);
  206. write_video_frame(oc, st, buf2,size + *header_pos, picType);
  207. osal_free(buf2);
  208. //to write a header to the first chunk just one time in container except JPEG
  209. if ( format != 8 ) //(format != MJPEG)
  210. *header_pos = 0;
  211. }
  212. else
  213. write_video_frame(oc, st, buf, size, picType);
  214. osal_free(buf);
  215. return 1;
  216. }
  217. int container_deinit(AVFormatContext *oc)
  218. {
  219. unsigned int i;
  220. if (!oc || !oc->pb)
  221. return 0;
  222. /* write the trailer, if any. the trailer must be written
  223. * before you close the CodecContexts open when you wrote the
  224. * header; otherwise write_trailer may try to use memory that
  225. * was freed on av_codec_close() */
  226. av_write_trailer(oc);
  227. /* free the streams */
  228. for(i=0; i<oc->nb_streams; i++) {
  229. av_freep(&oc->streams[i]->codec);
  230. av_freep(&oc->streams[i]);
  231. }
  232. /* close the output file */
  233. avio_close(oc->pb);
  234. /* free the stream */
  235. av_free(oc);
  236. return 1;
  237. }
  238. #endif /* SUPPORT_FFMPEG_DEMUX */