mxg.c
Go to the documentation of this file.
1 /*
2  * MxPEG clip file demuxer
3  * Copyright (c) 2010 Anatoly Nenashev
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg 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  * FFmpeg 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 FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
23 #include "libavutil/intreadwrite.h"
24 #include "libavcodec/mjpeg.h"
25 #include "avformat.h"
26 #include "internal.h"
27 #include "avio.h"
28 
29 #define DEFAULT_PACKET_SIZE 1024
30 #define OVERREAD_SIZE 3
31 
32 typedef struct MXGContext {
36  unsigned int buffer_size;
37  int64_t dts;
38  unsigned int cache_size;
39 } MXGContext;
40 
42 {
43  AVStream *video_st, *audio_st;
44  MXGContext *mxg = s->priv_data;
45 
46  /* video parameters will be extracted from the compressed bitstream */
47  video_st = avformat_new_stream(s, NULL);
48  if (!video_st)
49  return AVERROR(ENOMEM);
50  video_st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
51  video_st->codec->codec_id = AV_CODEC_ID_MXPEG;
52  avpriv_set_pts_info(video_st, 64, 1, 1000000);
53 
54  audio_st = avformat_new_stream(s, NULL);
55  if (!audio_st)
56  return AVERROR(ENOMEM);
57  audio_st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
58  audio_st->codec->codec_id = AV_CODEC_ID_PCM_ALAW;
59  audio_st->codec->channels = 1;
61  audio_st->codec->sample_rate = 8000;
62  audio_st->codec->bits_per_coded_sample = 8;
63  audio_st->codec->block_align = 1;
64  avpriv_set_pts_info(audio_st, 64, 1, 1000000);
65 
66  mxg->soi_ptr = mxg->buffer_ptr = mxg->buffer = 0;
67  mxg->buffer_size = 0;
68  mxg->dts = AV_NOPTS_VALUE;
69  mxg->cache_size = 0;
70 
71  return 0;
72 }
73 
75 {
76  for (; p < end - 3; p += 4) {
77  uint32_t x = *(uint32_t*)p;
78 
79  if (x & (~(x+0x01010101)) & 0x80808080) {
80  if (p[0] == 0xff) {
81  return p;
82  } else if (p[1] == 0xff) {
83  return p+1;
84  } else if (p[2] == 0xff) {
85  return p+2;
86  } else if (p[3] == 0xff) {
87  return p+3;
88  }
89  }
90  }
91 
92  for (; p < end; ++p) {
93  if (*p == 0xff) return p;
94  }
95 
96  return end;
97 }
98 
99 static int mxg_update_cache(AVFormatContext *s, unsigned int cache_size)
100 {
101  MXGContext *mxg = s->priv_data;
102  unsigned int current_pos = mxg->buffer_ptr - mxg->buffer;
103  unsigned int soi_pos;
104  uint8_t *buffer;
105  int ret;
106 
107  /* reallocate internal buffer */
108  if (current_pos > current_pos + cache_size)
109  return AVERROR(ENOMEM);
110  soi_pos = mxg->soi_ptr - mxg->buffer;
111  buffer = av_fast_realloc(mxg->buffer, &mxg->buffer_size,
112  current_pos + cache_size +
114  if (!buffer)
115  return AVERROR(ENOMEM);
116  mxg->buffer = buffer;
117  mxg->buffer_ptr = mxg->buffer + current_pos;
118  if (mxg->soi_ptr) mxg->soi_ptr = mxg->buffer + soi_pos;
119 
120  /* get data */
121  ret = avio_read(s->pb, mxg->buffer_ptr + mxg->cache_size,
122  cache_size - mxg->cache_size);
123  if (ret < 0)
124  return ret;
125 
126  mxg->cache_size += ret;
127 
128  return ret;
129 }
130 
132 {
133  int ret;
134  unsigned int size;
135  uint8_t *startmarker_ptr, *end, *search_end, marker;
136  MXGContext *mxg = s->priv_data;
137 
138  while (!url_feof(s->pb) && !s->pb->error){
139  if (mxg->cache_size <= OVERREAD_SIZE) {
140  /* update internal buffer */
142  if (ret < 0)
143  return ret;
144  }
145  end = mxg->buffer_ptr + mxg->cache_size;
146 
147  /* find start marker - 0xff */
148  if (mxg->cache_size > OVERREAD_SIZE) {
149  search_end = end - OVERREAD_SIZE;
150  startmarker_ptr = mxg_find_startmarker(mxg->buffer_ptr, search_end);
151  } else {
152  search_end = end;
153  startmarker_ptr = mxg_find_startmarker(mxg->buffer_ptr, search_end);
154  if (startmarker_ptr >= search_end - 1 ||
155  *(startmarker_ptr + 1) != EOI) break;
156  }
157 
158  if (startmarker_ptr != search_end) { /* start marker found */
159  marker = *(startmarker_ptr + 1);
160  mxg->buffer_ptr = startmarker_ptr + 2;
161  mxg->cache_size = end - mxg->buffer_ptr;
162 
163  if (marker == SOI) {
164  mxg->soi_ptr = startmarker_ptr;
165  } else if (marker == EOI) {
166  if (!mxg->soi_ptr) {
167  av_log(s, AV_LOG_WARNING, "Found EOI before SOI, skipping\n");
168  continue;
169  }
170 
171  pkt->pts = pkt->dts = mxg->dts;
172  pkt->stream_index = 0;
173 #if FF_API_DESTRUCT_PACKET
174  pkt->destruct = NULL;
175 #endif
176  pkt->buf = NULL;
177  pkt->size = mxg->buffer_ptr - mxg->soi_ptr;
178  pkt->data = mxg->soi_ptr;
179 
180  if (mxg->soi_ptr - mxg->buffer > mxg->cache_size) {
181  if (mxg->cache_size > 0) {
182  memcpy(mxg->buffer, mxg->buffer_ptr, mxg->cache_size);
183  }
184 
185  mxg->buffer_ptr = mxg->buffer;
186  }
187  mxg->soi_ptr = 0;
188 
189  return pkt->size;
190  } else if ( (SOF0 <= marker && marker <= SOF15) ||
191  (SOS <= marker && marker <= COM) ) {
192  /* all other markers that start marker segment also contain
193  length value (see specification for JPEG Annex B.1) */
194  size = AV_RB16(mxg->buffer_ptr);
195  if (size < 2)
196  return AVERROR(EINVAL);
197 
198  if (mxg->cache_size < size) {
199  ret = mxg_update_cache(s, size);
200  if (ret < 0)
201  return ret;
202  startmarker_ptr = mxg->buffer_ptr - 2;
203  mxg->cache_size = 0;
204  } else {
205  mxg->cache_size -= size;
206  }
207 
208  mxg->buffer_ptr += size;
209 
210  if (marker == APP13 && size >= 16) { /* audio data */
211  /* time (GMT) of first sample in usec since 1970, little-endian */
212  pkt->pts = pkt->dts = AV_RL64(startmarker_ptr + 8);
213  pkt->stream_index = 1;
214 #if FF_API_DESTRUCT_PACKET
215  pkt->destruct = NULL;
216 #endif
217  pkt->buf = NULL;
218  pkt->size = size - 14;
219  pkt->data = startmarker_ptr + 16;
220 
221  if (startmarker_ptr - mxg->buffer > mxg->cache_size) {
222  if (mxg->cache_size > 0) {
223  memcpy(mxg->buffer, mxg->buffer_ptr, mxg->cache_size);
224  }
225  mxg->buffer_ptr = mxg->buffer;
226  }
227 
228  return pkt->size;
229  } else if (marker == COM && size >= 18 &&
230  !strncmp(startmarker_ptr + 4, "MXF", 3)) {
231  /* time (GMT) of video frame in usec since 1970, little-endian */
232  mxg->dts = AV_RL64(startmarker_ptr + 12);
233  }
234  }
235  } else {
236  /* start marker not found */
237  mxg->buffer_ptr = search_end;
238  mxg->cache_size = OVERREAD_SIZE;
239  }
240  }
241 
242  return AVERROR_EOF;
243 }
244 
245 static int mxg_close(struct AVFormatContext *s)
246 {
247  MXGContext *mxg = s->priv_data;
248  av_freep(&mxg->buffer);
249  return 0;
250 }
251 
253  .name = "mxg",
254  .long_name = NULL_IF_CONFIG_SMALL("MxPEG clip"),
255  .priv_data_size = sizeof(MXGContext),
259  .extensions = "mxg",
260 };
Definition: mjpeg.h:115
const char * s
Definition: avisynth_c.h:668
Buffered I/O operations.
static uint8_t * mxg_find_startmarker(uint8_t *p, uint8_t *end)
Definition: mxg.c:74
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
Definition: mjpeg.h:74
MJPEG encoder and decoder.
int block_align
number of bytes per packet if constant and known or 0 Used by some WAV based audio codecs...
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
Format I/O context.
Definition: avformat.h:944
#define AV_RL64
uint8_t
static AVPacket pkt
Definition: demuxing.c:56
end end
Definition: mjpeg.h:96
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
uint8_t * data
#define AVERROR_EOF
End of file.
Definition: error.h:55
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:145
unsigned int cache_size
Definition: mxg.c:38
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
uint8_t * buffer
Definition: mxg.c:33
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:478
Discrete Time axis x
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given block if it is not large enough, otherwise do nothing.
#define AV_RB16
Definition: mjpeg.h:43
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
AVBufferRef * buf
A reference to the reference-counted buffer where the packet data is stored.
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
uint8_t * soi_ptr
Definition: mxg.c:35
int size
uint64_t channel_layout
Audio channel layout.
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:662
static int mxg_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: mxg.c:131
#define FF_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
struct MXGContext MXGContext
audio channel layout utility functions
int64_t dts
Definition: mxg.c:37
Definition: mjpeg.h:76
ret
Definition: avfilter.c:821
uint8_t * buffer_ptr
Definition: mxg.c:34
#define DEFAULT_PACKET_SIZE
Definition: mxg.c:29
AVInputFormat ff_mxg_demuxer
Definition: mxg.c:252
static int mxg_update_cache(AVFormatContext *s, unsigned int cache_size)
Definition: mxg.c:99
Definition: mxg.c:32
#define OVERREAD_SIZE
Definition: mxg.c:30
int url_feof(AVIOContext *s)
feof() equivalent for AVIOContext.
Definition: aviobuf.c:280
Definition: mjpeg.h:75
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:517
Stream structure.
Definition: avformat.h:643
NULL
Definition: eval.c:55
enum AVMediaType codec_type
enum AVCodecID codec_id
int sample_rate
samples per second
AVIOContext * pb
I/O context.
Definition: avformat.h:977
static int read_packet(AVFormatContext *ctx, AVPacket *pkt)
Definition: libcdio.c:114
Definition: mjpeg.h:58
int error
contains the error code or 0 if no error happened
Definition: avio.h:102
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
Main libavformat public API header.
static int mxg_close(struct AVFormatContext *s)
Definition: mxg.c:245
int channels
number of audio channels
void * priv_data
Format private data.
Definition: avformat.h:964
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:461
unsigned int buffer_size
Definition: mxg.c:36
#define AV_CH_LAYOUT_MONO
This structure stores compressed data.
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:190
static int mxg_read_header(AVFormatContext *s)
Definition: mxg.c:41