FFmpeg
movenchint.c
Go to the documentation of this file.
1 /*
2  * MOV, 3GP, MP4 muxer RTP hinting
3  * Copyright (c) 2010 Martin Storsjo
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 
22 #include "movenc.h"
23 #include "libavutil/intreadwrite.h"
24 #include "internal.h"
25 #include "rtpenc_chain.h"
26 #include "avio_internal.h"
27 #include "rtp.h"
28 
29 int ff_mov_init_hinting(AVFormatContext *s, int index, int src_index)
30 {
31  MOVMuxContext *mov = s->priv_data;
32  MOVTrack *track = &mov->tracks[index];
33  MOVTrack *src_track = &mov->tracks[src_index];
34  AVStream *src_st = s->streams[src_index];
35  int ret = AVERROR(ENOMEM);
36 
37  track->tag = MKTAG('r','t','p',' ');
38  track->src_track = src_index;
39 
40  track->par = avcodec_parameters_alloc();
41  if (!track->par)
42  goto fail;
44  track->par->codec_tag = track->tag;
45 
46  ret = ff_rtp_chain_mux_open(&track->rtp_ctx, s, src_st, NULL,
47  RTP_MAX_PACKET_SIZE, src_index);
48  if (ret < 0)
49  goto fail;
50 
51  /* Copy the RTP AVStream timebase back to the hint AVStream */
52  track->timescale = track->rtp_ctx->streams[0]->time_base.den;
53 
54  /* Mark the hinted track that packets written to it should be
55  * sent to this track for hinting. */
56  src_track->hint_track = index;
57  return 0;
58 fail:
60  "Unable to initialize hinting of stream %d\n", src_index);
62  /* Set a default timescale, to avoid crashes in av_dump_format */
63  track->timescale = 90000;
64  return ret;
65 }
66 
67 /**
68  * Remove the first sample from the sample queue.
69  */
70 static void sample_queue_pop(HintSampleQueue *queue)
71 {
72  if (queue->len <= 0)
73  return;
74  if (queue->samples[0].own_data)
75  av_freep(&queue->samples[0].data);
76  queue->len--;
77  memmove(queue->samples, queue->samples + 1, sizeof(HintSample)*queue->len);
78 }
79 
80 /**
81  * Empty the sample queue, releasing all memory.
82  */
84 {
85  int i;
86  for (i = 0; i < queue->len; i++)
87  if (queue->samples[i].own_data)
88  av_freep(&queue->samples[i].data);
89  av_freep(&queue->samples);
90  queue->len = 0;
91  queue->size = 0;
92 }
93 
94 /**
95  * Add a reference to the sample data to the sample queue. The data is
96  * not copied. sample_queue_retain should be called before pkt->data
97  * is reused/freed.
98  */
100  int sample)
101 {
102  /* No need to keep track of smaller samples, since describing them
103  * with immediates is more efficient. */
104  if (size <= 14)
105  return;
106  if (!queue->samples || queue->len >= queue->size) {
108  samples = av_realloc_array(queue->samples, queue->size + 10, sizeof(HintSample));
109  if (!samples)
110  return;
111  queue->size += 10;
112  queue->samples = samples;
113  }
114  queue->samples[queue->len].data = data;
115  queue->samples[queue->len].size = size;
116  queue->samples[queue->len].sample_number = sample;
117  queue->samples[queue->len].offset = 0;
118  queue->samples[queue->len].own_data = 0;
119  queue->len++;
120 }
121 
122 /**
123  * Make local copies of all referenced sample data in the queue.
124  */
126 {
127  int i;
128  for (i = 0; i < queue->len; ) {
129  HintSample *sample = &queue->samples[i];
130  if (!sample->own_data) {
131  uint8_t *ptr = av_malloc(sample->size);
132  if (!ptr) {
133  /* Unable to allocate memory for this one, remove it */
134  memmove(queue->samples + i, queue->samples + i + 1,
135  sizeof(HintSample)*(queue->len - i - 1));
136  queue->len--;
137  continue;
138  }
139  memcpy(ptr, sample->data, sample->size);
140  sample->data = ptr;
141  sample->own_data = 1;
142  }
143  i++;
144  }
145 }
146 
147 /**
148  * Find matches of needle[n_pos ->] within haystack. If a sufficiently
149  * large match is found, matching bytes before n_pos are included
150  * in the match, too (within the limits of the arrays).
151  *
152  * @param haystack buffer that may contain parts of needle
153  * @param h_len length of the haystack buffer
154  * @param needle buffer containing source data that have been used to
155  * construct haystack
156  * @param n_pos start position in needle used for looking for matches
157  * @param n_len length of the needle buffer
158  * @param match_h_offset_ptr offset of the first matching byte within haystack
159  * @param match_n_offset_ptr offset of the first matching byte within needle
160  * @param match_len_ptr length of the matched segment
161  * @return 0 if a match was found, < 0 if no match was found
162  */
163 static int match_segments(const uint8_t *haystack, int h_len,
164  const uint8_t *needle, int n_pos, int n_len,
165  int *match_h_offset_ptr, int *match_n_offset_ptr,
166  int *match_len_ptr)
167 {
168  int h_pos;
169  for (h_pos = 0; h_pos < h_len; h_pos++) {
170  int match_len = 0;
171  int match_h_pos, match_n_pos;
172 
173  /* Check how many bytes match at needle[n_pos] and haystack[h_pos] */
174  while (h_pos + match_len < h_len && n_pos + match_len < n_len &&
175  needle[n_pos + match_len] == haystack[h_pos + match_len])
176  match_len++;
177  if (match_len <= 8)
178  continue;
179 
180  /* If a sufficiently large match was found, try to expand
181  * the matched segment backwards. */
182  match_h_pos = h_pos;
183  match_n_pos = n_pos;
184  while (match_n_pos > 0 && match_h_pos > 0 &&
185  needle[match_n_pos - 1] == haystack[match_h_pos - 1]) {
186  match_n_pos--;
187  match_h_pos--;
188  match_len++;
189  }
190  if (match_len <= 14)
191  continue;
192  *match_h_offset_ptr = match_h_pos;
193  *match_n_offset_ptr = match_n_pos;
194  *match_len_ptr = match_len;
195  return 0;
196  }
197  return -1;
198 }
199 
200 /**
201  * Look for segments in samples in the sample queue matching the data
202  * in ptr. Samples not matching are removed from the queue. If a match
203  * is found, the next time it will look for matches starting from the
204  * end of the previous matched segment.
205  *
206  * @param data data to find matches for in the sample queue
207  * @param len length of the data buffer
208  * @param queue samples used for looking for matching segments
209  * @param pos the offset in data of the matched segment
210  * @param match_sample the number of the sample that contained the match
211  * @param match_offset the offset of the matched segment within the sample
212  * @param match_len the length of the matched segment
213  * @return 0 if a match was found, < 0 if no match was found
214  */
215 static int find_sample_match(const uint8_t *data, int len,
216  HintSampleQueue *queue, int *pos,
217  int *match_sample, int *match_offset,
218  int *match_len)
219 {
220  while (queue->len > 0) {
221  HintSample *sample = &queue->samples[0];
222  /* If looking for matches in a new sample, skip the first 5 bytes,
223  * since they often may be modified/removed in the output packet. */
224  if (sample->offset == 0 && sample->size > 5)
225  sample->offset = 5;
226 
227  if (match_segments(data, len, sample->data, sample->offset,
228  sample->size, pos, match_offset, match_len) == 0) {
229  *match_sample = sample->sample_number;
230  /* Next time, look for matches at this offset, with a little
231  * margin to this match. */
232  sample->offset = *match_offset + *match_len + 5;
233  if (sample->offset + 10 >= sample->size)
234  sample_queue_pop(queue); /* Not enough useful data left */
235  return 0;
236  }
237 
238  if (sample->offset < 10 && sample->size > 20) {
239  /* No match found from the start of the sample,
240  * try from the middle of the sample instead. */
241  sample->offset = sample->size/2;
242  } else {
243  /* No match for this sample, remove it */
244  sample_queue_pop(queue);
245  }
246  }
247  return -1;
248 }
249 
250 static void output_immediate(const uint8_t *data, int size,
251  AVIOContext *out, int *entries)
252 {
253  while (size > 0) {
254  int len = size;
255  if (len > 14)
256  len = 14;
257  avio_w8(out, 1); /* immediate constructor */
258  avio_w8(out, len); /* amount of valid data */
259  avio_write(out, data, len);
260  data += len;
261  size -= len;
262 
263  for (; len < 14; len++)
264  avio_w8(out, 0);
265 
266  (*entries)++;
267  }
268 }
269 
270 static void output_match(AVIOContext *out, int match_sample,
271  int match_offset, int match_len, int *entries)
272 {
273  avio_w8(out, 2); /* sample constructor */
274  avio_w8(out, 0); /* track reference */
275  avio_wb16(out, match_len);
276  avio_wb32(out, match_sample);
277  avio_wb32(out, match_offset);
278  avio_wb16(out, 1); /* bytes per block */
279  avio_wb16(out, 1); /* samples per block */
280  (*entries)++;
281 }
282 
283 static void describe_payload(const uint8_t *data, int size,
284  AVIOContext *out, int *entries,
285  HintSampleQueue *queue)
286 {
287  /* Describe the payload using different constructors */
288  while (size > 0) {
289  int match_sample, match_offset, match_len, pos;
290  if (find_sample_match(data, size, queue, &pos, &match_sample,
291  &match_offset, &match_len) < 0)
292  break;
293  output_immediate(data, pos, out, entries);
294  data += pos;
295  size -= pos;
296  output_match(out, match_sample, match_offset, match_len, entries);
297  data += match_len;
298  size -= match_len;
299  }
300  output_immediate(data, size, out, entries);
301 }
302 
303 /**
304  * Write an RTP hint (that may contain one or more RTP packets)
305  * for the packets in data. data contains one or more packets with a
306  * BE32 size header.
307  *
308  * @param out buffer where the hints are written
309  * @param data buffer containing RTP packets
310  * @param size the size of the data buffer
311  * @param trk the MOVTrack for the hint track
312  * @param dts pointer where the timestamp for the written RTP hint is stored
313  * @return the number of RTP packets in the written hint
314  */
316  int size, MOVTrack *trk, int64_t *dts)
317 {
318  int64_t curpos;
319  int64_t count_pos, entries_pos;
320  int count = 0, entries;
321 
322  count_pos = avio_tell(out);
323  /* RTPsample header */
324  avio_wb16(out, 0); /* packet count */
325  avio_wb16(out, 0); /* reserved */
326 
327  while (size > 4) {
328  uint32_t packet_len = AV_RB32(data);
329  uint16_t seq;
330  uint32_t ts;
331  int32_t ts_diff;
332 
333  data += 4;
334  size -= 4;
335  if (packet_len > size || packet_len <= 12)
336  break;
337  if (RTP_PT_IS_RTCP(data[1])) {
338  /* RTCP packet, just skip */
339  data += packet_len;
340  size -= packet_len;
341  continue;
342  }
343 
344  if (packet_len > trk->max_packet_size)
345  trk->max_packet_size = packet_len;
346 
347  seq = AV_RB16(&data[2]);
348  ts = AV_RB32(&data[4]);
349 
350  if (trk->prev_rtp_ts == 0)
351  trk->prev_rtp_ts = ts;
352  /* Unwrap the 32-bit RTP timestamp that wraps around often
353  * into a not (as often) wrapping 64-bit timestamp. */
354  ts_diff = ts - trk->prev_rtp_ts;
355  if (ts_diff > 0) {
356  trk->cur_rtp_ts_unwrapped += ts_diff;
357  trk->prev_rtp_ts = ts;
358  ts_diff = 0;
359  }
360  if (*dts == AV_NOPTS_VALUE)
361  *dts = trk->cur_rtp_ts_unwrapped;
362 
363  count++;
364  /* RTPpacket header */
365  avio_wb32(out, 0); /* relative_time */
366  avio_write(out, data, 2); /* RTP header */
367  avio_wb16(out, seq); /* RTPsequenceseed */
368  avio_wb16(out, ts_diff ? 4 : 0); /* reserved + flags (extra_flag) */
369  entries_pos = avio_tell(out);
370  avio_wb16(out, 0); /* entry count */
371  if (ts_diff) { /* if extra_flag is set */
372  avio_wb32(out, 16); /* extra_information_length */
373  avio_wb32(out, 12); /* rtpoffsetTLV box */
374  avio_write(out, "rtpo", 4);
375  avio_wb32(out, ts_diff);
376  }
377 
378  data += 12;
379  size -= 12;
380  packet_len -= 12;
381 
382  entries = 0;
383  /* Write one or more constructors describing the payload data */
384  describe_payload(data, packet_len, out, &entries, &trk->sample_queue);
385  data += packet_len;
386  size -= packet_len;
387 
388  curpos = avio_tell(out);
389  avio_seek(out, entries_pos, SEEK_SET);
390  avio_wb16(out, entries);
391  avio_seek(out, curpos, SEEK_SET);
392  }
393 
394  curpos = avio_tell(out);
395  avio_seek(out, count_pos, SEEK_SET);
396  avio_wb16(out, count);
397  avio_seek(out, curpos, SEEK_SET);
398  return count;
399 }
400 
402  int track_index, int sample,
403  uint8_t *sample_data, int sample_size)
404 {
405  MOVMuxContext *mov = s->priv_data;
406  MOVTrack *trk = &mov->tracks[track_index];
407  AVFormatContext *rtp_ctx = trk->rtp_ctx;
408  uint8_t *buf = NULL;
409  int size;
410  AVIOContext *hintbuf = NULL;
411  AVPacket hint_pkt;
412  int ret = 0, count;
413 
414  if (!rtp_ctx)
415  return AVERROR(ENOENT);
416  if (!rtp_ctx->pb)
417  return AVERROR(ENOMEM);
418 
419  if (sample_data)
420  sample_queue_push(&trk->sample_queue, sample_data, sample_size, sample);
421  else
422  sample_queue_push(&trk->sample_queue, pkt->data, pkt->size, sample);
423 
424  /* Feed the packet to the RTP muxer */
425  ff_write_chained(rtp_ctx, 0, pkt, s, 0);
426 
427  /* Fetch the output from the RTP muxer, open a new output buffer
428  * for next time. */
429  size = avio_close_dyn_buf(rtp_ctx->pb, &buf);
430  if ((ret = ffio_open_dyn_packet_buf(&rtp_ctx->pb,
431  RTP_MAX_PACKET_SIZE)) < 0)
432  goto done;
433 
434  if (size <= 0)
435  goto done;
436 
437  /* Open a buffer for writing the hint */
438  if ((ret = avio_open_dyn_buf(&hintbuf)) < 0)
439  goto done;
440  av_init_packet(&hint_pkt);
441  count = write_hint_packets(hintbuf, buf, size, trk, &hint_pkt.dts);
442  av_freep(&buf);
443 
444  /* Write the hint data into the hint track */
445  hint_pkt.size = size = avio_close_dyn_buf(hintbuf, &buf);
446  hint_pkt.data = buf;
447  hint_pkt.pts = hint_pkt.dts;
448  hint_pkt.stream_index = track_index;
449  if (pkt->flags & AV_PKT_FLAG_KEY)
450  hint_pkt.flags |= AV_PKT_FLAG_KEY;
451  if (count > 0)
452  ff_mov_write_packet(s, &hint_pkt);
453 done:
454  av_free(buf);
456  return ret;
457 }
458 
460 {
461  AVFormatContext *rtp_ctx = track->rtp_ctx;
462 
463  avcodec_parameters_free(&track->par);
465  if (!rtp_ctx)
466  return;
467  if (rtp_ctx->pb) {
468  av_write_trailer(rtp_ctx);
469  ffio_free_dyn_buf(&rtp_ctx->pb);
470  }
471  avformat_free_context(rtp_ctx);
472 }
#define NULL
Definition: coverity.c:32
uint8_t * data
Definition: movenc.h:62
Bytestream IO Context.
Definition: avio.h:161
static void output_match(AVIOContext *out, int match_sample, int match_offset, int match_len, int *entries)
Definition: movenchint.c:270
int tag
stsd fourcc
Definition: movenc.h:105
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:1459
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
static int find_sample_match(const uint8_t *data, int len, HintSampleQueue *queue, int *pos, int *match_sample, int *match_offset, int *match_len)
Look for segments in samples in the sample queue matching the data in ptr.
Definition: movenchint.c:215
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
static void output_immediate(const uint8_t *data, int size, AVIOContext *out, int *entries)
Definition: movenchint.c:250
int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt, AVFormatContext *src, int interleave)
Write a packet to another muxer than the one the user originally intended.
Definition: mux.c:1318
int size
Definition: avcodec.h:1481
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:246
#define RTP_MAX_PACKET_SIZE
Definition: movenc.h:34
static AVPacket pkt
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_WB24 unsigned int_TMPL AV_RB16
Definition: bytestream.h:87
static void sample_queue_push(HintSampleQueue *queue, uint8_t *data, int size, int sample)
Add a reference to the sample data to the sample queue.
Definition: movenchint.c:99
#define sample
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition: aviobuf.c:1430
AVCodecParameters * par
Definition: movenc.h:107
Format I/O context.
Definition: avformat.h:1358
HintSampleQueue sample_queue
Definition: movenc.h:135
int offset
Definition: movenc.h:65
uint8_t
#define av_malloc(s)
Opaque data information usually continuous.
Definition: avutil.h:203
AVCodecParameters * avcodec_parameters_alloc(void)
Allocate a new AVCodecParameters and set its fields to default values (unknown/invalid/0).
Definition: utils.c:2014
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_RB32
Definition: bytestream.h:87
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1426
uint8_t * data
Definition: avcodec.h:1480
int own_data
Definition: movenc.h:66
static int write_hint_packets(AVIOContext *out, const uint8_t *data, int size, MOVTrack *trk, int64_t *dts)
Write an RTP hint (that may contain one or more RTP packets) for the packets in data.
Definition: movenchint.c:315
ptrdiff_t size
Definition: opengl_enc.c:100
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:557
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:218
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition: mem.c:198
#define av_log(a,...)
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1512
int sample_number
Definition: movenc.h:64
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
HintSample * samples
Definition: movenc.h:72
uint32_t prev_rtp_ts
Definition: movenc.h:127
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3964
GLsizei count
Definition: opengl_enc.c:108
void avcodec_parameters_free(AVCodecParameters **par)
Free an AVCodecParameters instance and everything associated with it and write NULL to the supplied p...
Definition: utils.c:2024
#define fail()
Definition: checkasm.h:122
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1486
int ffio_open_dyn_packet_buf(AVIOContext **s, int max_packet_size)
Open a write only packetized memory stream with a maximum packet size of &#39;max_packet_size&#39;.
Definition: aviobuf.c:1435
int32_t
#define s(width, name)
Definition: cbs_vp9.c:257
int size
Definition: movenc.h:63
void ffio_free_dyn_buf(AVIOContext **s)
Free a dynamic buffer.
Definition: aviobuf.c:1489
Stream structure.
Definition: avformat.h:881
static void describe_payload(const uint8_t *data, int size, AVIOContext *out, int *entries, HintSampleQueue *queue)
Definition: movenchint.c:283
static void sample_queue_free(HintSampleQueue *queue)
Empty the sample queue, releasing all memory.
Definition: movenchint.c:83
AVIOContext * pb
I/O context.
Definition: avformat.h:1400
void avio_w8(AVIOContext *s, int b)
Definition: aviobuf.c:196
int hint_track
the track that hints this track, -1 if no hint track is set
Definition: movenc.h:124
void * buf
Definition: avisynth_c.h:766
int ff_mov_init_hinting(AVFormatContext *s, int index, int src_index)
Definition: movenchint.c:29
int index
Definition: gxfenc.c:89
static void sample_queue_pop(HintSampleQueue *queue)
Remove the first sample from the sample queue.
Definition: movenchint.c:70
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: utils.c:4433
#define RTP_PT_IS_RTCP(x)
Definition: rtp.h:110
void avio_wb16(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:478
AVFormatContext * rtp_ctx
the format context for the hinting rtp muxer
Definition: movenc.h:126
int ff_rtp_chain_mux_open(AVFormatContext **out, AVFormatContext *s, AVStream *st, URLContext *handle, int packet_size, int idx)
Definition: rtpenc_chain.c:28
static void sample_queue_retain(HintSampleQueue *queue)
Make local copies of all referenced sample data in the queue.
Definition: movenchint.c:125
uint32_t max_packet_size
Definition: movenc.h:129
int src_track
the track that this hint (or tmcd) track describes
Definition: movenc.h:125
void av_init_packet(AVPacket *pkt)
Initialize optional fields of a packet with default values.
Definition: avpacket.c:33
int den
Denominator.
Definition: rational.h:60
#define av_free(p)
unsigned timescale
Definition: movenc.h:86
int len
void * priv_data
Format private data.
Definition: avformat.h:1386
void ff_mov_close_hinting(MOVTrack *track)
Definition: movenchint.c:459
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
Definition: avcodec.h:1479
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:1254
void avio_wb32(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:380
FILE * out
Definition: movenc.c:54
Filter the word “frame” indicates either a video frame or a group of audio samples
#define av_freep(p)
static int track_index(VividasDemuxContext *viv, AVFormatContext *s, uint8_t *buf, unsigned size)
Definition: vividas.c:425
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition: avcodec.h:3972
int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: movenc.c:5311
int stream_index
Definition: avcodec.h:1482
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avformat.h:910
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame 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.Frame references ownership and permissions
#define MKTAG(a, b, c, d)
Definition: common.h:366
static int match_segments(const uint8_t *haystack, int h_len, const uint8_t *needle, int n_pos, int n_len, int *match_h_offset_ptr, int *match_n_offset_ptr, int *match_len_ptr)
Find matches of needle[n_pos ->] within haystack.
Definition: movenchint.c:163
This structure stores compressed data.
Definition: avcodec.h:1457
int ff_mov_add_hinted_packet(AVFormatContext *s, AVPacket *pkt, int track_index, int sample, uint8_t *sample_data, int sample_size)
Definition: movenchint.c:401
MOVTrack * tracks
Definition: movenc.h:189
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1473
int64_t cur_rtp_ts_unwrapped
Definition: movenc.h:128
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248