bsfeeder_framesize_impl.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /*
  2. * Copyright (c) 2018, Chips&Media
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright notice,
  11. * this list of conditions and the following disclaimer in the documentation
  12. * and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  15. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  16. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  17. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  18. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  19. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  20. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  21. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  23. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #include <time.h>
  26. #include "main_helper.h"
  27. #include "libavformat/avformat.h"
  28. static BOOL initFFmpeg;
  29. typedef struct FeederFrameContext {
  30. AVFormatContext* avContext;
  31. BOOL isFirstPacket;
  32. Uint32 videoIndex;
  33. Uint8* tempBuffer;
  34. Uint32 tempRdPtr;
  35. Uint32 tempWrPtr;
  36. } FeederFrameContext;
  37. void* BSFeederFrameSize_Create(const char* path)
  38. {
  39. /*lint -esym(438, avContext) */
  40. FeederFrameContext* ffmpegReader = NULL;
  41. AVFormatContext* avContext = NULL;
  42. AVCodecContext* codec = NULL;
  43. AVInputFormat* fmt = NULL;
  44. Int32 error;
  45. Int32 videoIndex;
  46. jdi_lock();
  47. if (initFFmpeg == FALSE) {
  48. av_register_all();
  49. initFFmpeg = TRUE;
  50. }
  51. jdi_unlock();
  52. if ((avContext=avformat_alloc_context()) == NULL) {
  53. return NULL;
  54. }
  55. avContext->flags |= CODEC_FLAG_TRUNCATED;
  56. if ((error=avformat_open_input(&avContext, path, fmt, NULL))) {
  57. JLOG(ERR, "%s:%d failed to av_open_input_file error(%d), %s\n",
  58. __FILE__, __LINE__, error, path);
  59. goto __failed_to_end;
  60. }
  61. if ((error=avformat_find_stream_info(avContext, NULL)) < 0) {
  62. JLOG(ERR, "%s:%d failed to avformat_find_stream_info. error(%d)\n",
  63. __FUNCTION__, __LINE__, error);
  64. goto __failed_to_end;
  65. }
  66. videoIndex = av_find_best_stream(avContext, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
  67. if (videoIndex < 0) {
  68. JLOG(ERR, "%s:%d failed to av_find_best_stream.\n", __FUNCTION__, __LINE__);
  69. goto __failed_to_end;
  70. }
  71. codec = avContext->streams[videoIndex]->codec;
  72. if (codec->codec_id != AV_CODEC_ID_MJPEG) {
  73. JLOG(ERR, "%s:%d Not supported codec_id: %d\n", __FUNCTION__, __LINE__, codec->codec_id);
  74. goto __failed_to_end;
  75. }
  76. if ((ffmpegReader=(FeederFrameContext*)malloc(sizeof(FeederFrameContext))) == NULL)
  77. goto __failed_to_end;
  78. ffmpegReader->avContext = avContext;
  79. ffmpegReader->videoIndex = videoIndex;
  80. ffmpegReader->isFirstPacket = TRUE;
  81. ffmpegReader->tempBuffer = NULL;
  82. ffmpegReader->tempRdPtr = 0;
  83. ffmpegReader->tempWrPtr = 0;
  84. return (void*)ffmpegReader;
  85. __failed_to_end:
  86. if (avContext) {
  87. avformat_free_context(avContext);
  88. avContext = NULL;
  89. }
  90. if (ffmpegReader) {
  91. free(ffmpegReader);
  92. }
  93. return NULL;
  94. /*lint +esym(438, avContext) */
  95. }
  96. BOOL BSFeederFrameSize_Destroy(
  97. void* feeder
  98. )
  99. {
  100. FeederFrameContext* ctx = (FeederFrameContext*)feeder;
  101. if (ctx == NULL) {
  102. JLOG(ERR, "%s:%d Invalid handle\n", __FUNCTION__, __LINE__);
  103. return FALSE;
  104. }
  105. if (ctx->avContext)
  106. avformat_close_input(&ctx->avContext);
  107. free(ctx);
  108. return TRUE;
  109. }
  110. Int32 BSFeederFrameSize_Act(void* feeder, BSChunk* packet)
  111. {
  112. FeederFrameContext* ffmpegReader = (FeederFrameContext*)feeder;
  113. AVFormatContext* avFormatContext = ffmpegReader->avContext;
  114. AVPacket avpacket;
  115. Int32 error;
  116. Uint8* ptr;
  117. Uint32 size;
  118. Int32 packetSize = -1;
  119. if (ffmpegReader->tempBuffer) {
  120. goto __consume_tempBuffer;
  121. }
  122. av_init_packet(&avpacket);
  123. while (TRUE) {
  124. error = av_read_frame(avFormatContext, &avpacket);
  125. if (error < 0) {
  126. if (error == AVERROR_EOF || avFormatContext->pb->eof_reached == TRUE) {
  127. packet->eos = TRUE;
  128. return 0;
  129. }
  130. else {
  131. JLOG(ERR, "%s:%d failed to av_read_frame error(0x%08x)\n",
  132. __FUNCTION__, __LINE__, error);
  133. goto __end_read;
  134. }
  135. }
  136. if (avpacket.stream_index != ffmpegReader->videoIndex)
  137. continue;
  138. break;
  139. }
  140. if (avpacket.size == 0)
  141. return 0;
  142. if (avpacket.size >= (signed)packet->size )
  143. {
  144. JLOG(ERR, "one packet size(%d) is bigger than STREAM_BUF_SIZE(%d)\n", avpacket.size, packet->size);
  145. return -1;
  146. }
  147. memset(packet->data, 0x00, packet->size);
  148. ptr = avpacket.data;
  149. size = avpacket.size;
  150. memcpy((char*)packet->data, ptr, size);
  151. packetSize = size;
  152. if (avFormatContext->pb->eof_reached && avFormatContext->packet_buffer == NULL) {
  153. packet->eos = TRUE;
  154. }
  155. __end_read:
  156. av_free_packet(&avpacket);
  157. return packetSize;
  158. __consume_tempBuffer:
  159. if (ffmpegReader->tempBuffer != NULL) {
  160. memcpy(packet->data, ffmpegReader->tempBuffer, ffmpegReader->tempWrPtr);
  161. packetSize = ffmpegReader->tempWrPtr;
  162. free(ffmpegReader->tempBuffer);
  163. ffmpegReader->tempBuffer = NULL;
  164. ffmpegReader->tempWrPtr = 0;
  165. ffmpegReader->tempRdPtr = 0;
  166. }
  167. return packetSize;
  168. }
  169. BOOL BSFeederFrameSize_Rewind(
  170. void* feeder
  171. )
  172. {
  173. FeederFrameContext* ffmpegReader = (FeederFrameContext*)feeder;
  174. AVFormatContext* avFormatContext = ffmpegReader->avContext;
  175. Int32 ret;
  176. if ((ret=av_seek_frame(avFormatContext, ffmpegReader->videoIndex, 0, 0)) < 0) {
  177. JLOG(ERR, "%s:%d Failed to av_seek_frame:(ret:%d)\n", __FUNCTION__, __LINE__, ret);
  178. return FALSE;
  179. }
  180. return TRUE;
  181. }