bsfeeder_framesize_impl.c 6.6 KB

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