You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

254 lines
8.3KB

  1. /*
  2. * MxPEG clip file demuxer
  3. * Copyright (c) 2010 Anatoly Nenashev
  4. *
  5. * This file is part of Libav.
  6. *
  7. * Libav is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * Libav is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with Libav; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include "libavutil/channel_layout.h"
  22. #include "libavutil/internal.h"
  23. #include "libavutil/intreadwrite.h"
  24. #include "libavcodec/mjpeg.h"
  25. #include "avformat.h"
  26. #include "internal.h"
  27. #include "avio.h"
  28. #define DEFAULT_PACKET_SIZE 1024
  29. #define OVERREAD_SIZE 3
  30. typedef struct MXGContext {
  31. uint8_t *buffer;
  32. uint8_t *buffer_ptr;
  33. uint8_t *soi_ptr;
  34. unsigned int buffer_size;
  35. int64_t dts;
  36. unsigned int cache_size;
  37. } MXGContext;
  38. static int mxg_read_header(AVFormatContext *s)
  39. {
  40. AVStream *video_st, *audio_st;
  41. MXGContext *mxg = s->priv_data;
  42. /* video parameters will be extracted from the compressed bitstream */
  43. video_st = avformat_new_stream(s, NULL);
  44. if (!video_st)
  45. return AVERROR(ENOMEM);
  46. video_st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
  47. video_st->codecpar->codec_id = AV_CODEC_ID_MXPEG;
  48. avpriv_set_pts_info(video_st, 64, 1, 1000000);
  49. audio_st = avformat_new_stream(s, NULL);
  50. if (!audio_st)
  51. return AVERROR(ENOMEM);
  52. audio_st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
  53. audio_st->codecpar->codec_id = AV_CODEC_ID_PCM_ALAW;
  54. audio_st->codecpar->channels = 1;
  55. audio_st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
  56. audio_st->codecpar->sample_rate = 8000;
  57. audio_st->codecpar->bits_per_coded_sample = 8;
  58. audio_st->codecpar->block_align = 1;
  59. avpriv_set_pts_info(audio_st, 64, 1, 1000000);
  60. mxg->soi_ptr = mxg->buffer_ptr = mxg->buffer = 0;
  61. mxg->buffer_size = 0;
  62. mxg->dts = AV_NOPTS_VALUE;
  63. mxg->cache_size = 0;
  64. return 0;
  65. }
  66. static uint8_t* mxg_find_startmarker(uint8_t *p, uint8_t *end)
  67. {
  68. for (; p < end - 3; p += 4) {
  69. uint32_t x = *(uint32_t*)p;
  70. if (x & (~(x+0x01010101)) & 0x80808080) {
  71. if (p[0] == 0xff) {
  72. return p;
  73. } else if (p[1] == 0xff) {
  74. return p+1;
  75. } else if (p[2] == 0xff) {
  76. return p+2;
  77. } else if (p[3] == 0xff) {
  78. return p+3;
  79. }
  80. }
  81. }
  82. for (; p < end; ++p) {
  83. if (*p == 0xff) return p;
  84. }
  85. return end;
  86. }
  87. static int mxg_update_cache(AVFormatContext *s, unsigned int cache_size)
  88. {
  89. MXGContext *mxg = s->priv_data;
  90. unsigned int current_pos = mxg->buffer_ptr - mxg->buffer;
  91. unsigned int soi_pos;
  92. int ret;
  93. /* reallocate internal buffer */
  94. if (current_pos > current_pos + cache_size)
  95. return AVERROR(ENOMEM);
  96. if (mxg->soi_ptr) soi_pos = mxg->soi_ptr - mxg->buffer;
  97. mxg->buffer = av_fast_realloc(mxg->buffer, &mxg->buffer_size,
  98. current_pos + cache_size +
  99. AV_INPUT_BUFFER_PADDING_SIZE);
  100. if (!mxg->buffer)
  101. return AVERROR(ENOMEM);
  102. mxg->buffer_ptr = mxg->buffer + current_pos;
  103. if (mxg->soi_ptr) mxg->soi_ptr = mxg->buffer + soi_pos;
  104. /* get data */
  105. ret = avio_read(s->pb, mxg->buffer_ptr + mxg->cache_size,
  106. cache_size - mxg->cache_size);
  107. if (ret < 0)
  108. return ret;
  109. mxg->cache_size += ret;
  110. return ret;
  111. }
  112. static int mxg_read_packet(AVFormatContext *s, AVPacket *pkt)
  113. {
  114. int ret;
  115. unsigned int size;
  116. uint8_t *startmarker_ptr, *end, *search_end, marker;
  117. MXGContext *mxg = s->priv_data;
  118. while (!s->pb->eof_reached && !s->pb->error){
  119. if (mxg->cache_size <= OVERREAD_SIZE) {
  120. /* update internal buffer */
  121. ret = mxg_update_cache(s, DEFAULT_PACKET_SIZE + OVERREAD_SIZE);
  122. if (ret < 0)
  123. return ret;
  124. }
  125. end = mxg->buffer_ptr + mxg->cache_size;
  126. /* find start marker - 0xff */
  127. if (mxg->cache_size > OVERREAD_SIZE) {
  128. search_end = end - OVERREAD_SIZE;
  129. startmarker_ptr = mxg_find_startmarker(mxg->buffer_ptr, search_end);
  130. } else {
  131. search_end = end;
  132. startmarker_ptr = mxg_find_startmarker(mxg->buffer_ptr, search_end);
  133. if (startmarker_ptr >= search_end - 1 ||
  134. *(startmarker_ptr + 1) != EOI) break;
  135. }
  136. if (startmarker_ptr != search_end) { /* start marker found */
  137. marker = *(startmarker_ptr + 1);
  138. mxg->buffer_ptr = startmarker_ptr + 2;
  139. mxg->cache_size = end - mxg->buffer_ptr;
  140. if (marker == SOI) {
  141. mxg->soi_ptr = startmarker_ptr;
  142. } else if (marker == EOI) {
  143. if (!mxg->soi_ptr) {
  144. av_log(s, AV_LOG_WARNING, "Found EOI before SOI, skipping\n");
  145. continue;
  146. }
  147. pkt->pts = pkt->dts = mxg->dts;
  148. pkt->stream_index = 0;
  149. pkt->buf = NULL;
  150. pkt->size = mxg->buffer_ptr - mxg->soi_ptr;
  151. pkt->data = mxg->soi_ptr;
  152. if (mxg->soi_ptr - mxg->buffer > mxg->cache_size) {
  153. if (mxg->cache_size > 0) {
  154. memcpy(mxg->buffer, mxg->buffer_ptr, mxg->cache_size);
  155. }
  156. mxg->buffer_ptr = mxg->buffer;
  157. }
  158. mxg->soi_ptr = 0;
  159. return pkt->size;
  160. } else if ( (SOF0 <= marker && marker <= SOF15) ||
  161. (SOS <= marker && marker <= COM) ) {
  162. /* all other markers that start marker segment also contain
  163. length value (see specification for JPEG Annex B.1) */
  164. size = AV_RB16(mxg->buffer_ptr);
  165. if (size < 2)
  166. return AVERROR(EINVAL);
  167. if (mxg->cache_size < size) {
  168. ret = mxg_update_cache(s, size);
  169. if (ret < 0)
  170. return ret;
  171. startmarker_ptr = mxg->buffer_ptr - 2;
  172. mxg->cache_size = 0;
  173. } else {
  174. mxg->cache_size -= size;
  175. }
  176. mxg->buffer_ptr += size;
  177. if (marker == APP13 && size >= 16) { /* audio data */
  178. /* time (GMT) of first sample in usec since 1970, little-endian */
  179. pkt->pts = pkt->dts = AV_RL64(startmarker_ptr + 8);
  180. pkt->stream_index = 1;
  181. pkt->buf = NULL;
  182. pkt->size = size - 14;
  183. pkt->data = startmarker_ptr + 16;
  184. if (startmarker_ptr - mxg->buffer > mxg->cache_size) {
  185. if (mxg->cache_size > 0) {
  186. memcpy(mxg->buffer, mxg->buffer_ptr, mxg->cache_size);
  187. }
  188. mxg->buffer_ptr = mxg->buffer;
  189. }
  190. return pkt->size;
  191. } else if (marker == COM && size >= 18 &&
  192. !strncmp(startmarker_ptr + 4, "MXF", 3)) {
  193. /* time (GMT) of video frame in usec since 1970, little-endian */
  194. mxg->dts = AV_RL64(startmarker_ptr + 12);
  195. }
  196. }
  197. } else {
  198. /* start marker not found */
  199. mxg->buffer_ptr = search_end;
  200. mxg->cache_size = OVERREAD_SIZE;
  201. }
  202. }
  203. return AVERROR_EOF;
  204. }
  205. static int mxg_close(struct AVFormatContext *s)
  206. {
  207. MXGContext *mxg = s->priv_data;
  208. av_freep(&mxg->buffer);
  209. return 0;
  210. }
  211. AVInputFormat ff_mxg_demuxer = {
  212. .name = "mxg",
  213. .long_name = NULL_IF_CONFIG_SMALL("MxPEG clip"),
  214. .priv_data_size = sizeof(MXGContext),
  215. .read_header = mxg_read_header,
  216. .read_packet = mxg_read_packet,
  217. .read_close = mxg_close,
  218. .extensions = "mxg",
  219. };