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 
41  if (!track->enc)
42  goto fail;
44  track->enc->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);
61  av_freep(&track->enc);
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_free(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_free(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  queue->size += 10;
109  samples = av_realloc(queue->samples, sizeof(HintSample)*queue->size);
110  if (!samples)
111  return;
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 pts 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 *pts)
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 
332  data += 4;
333  size -= 4;
334  if (packet_len > size || packet_len <= 12)
335  break;
336  if (RTP_PT_IS_RTCP(data[1])) {
337  /* RTCP packet, just skip */
338  data += packet_len;
339  size -= packet_len;
340  continue;
341  }
342 
343  if (packet_len > trk->max_packet_size)
344  trk->max_packet_size = packet_len;
345 
346  seq = AV_RB16(&data[2]);
347  ts = AV_RB32(&data[4]);
348 
349  if (trk->prev_rtp_ts == 0)
350  trk->prev_rtp_ts = ts;
351  /* Unwrap the 32-bit RTP timestamp that wraps around often
352  * into a not (as often) wrapping 64-bit timestamp. */
353  trk->cur_rtp_ts_unwrapped += (int32_t) (ts - trk->prev_rtp_ts);
354  trk->prev_rtp_ts = ts;
355  if (*pts == AV_NOPTS_VALUE)
356  *pts = trk->cur_rtp_ts_unwrapped;
357 
358  count++;
359  /* RTPpacket header */
360  avio_wb32(out, 0); /* relative_time */
361  avio_write(out, data, 2); /* RTP header */
362  avio_wb16(out, seq); /* RTPsequenceseed */
363  avio_wb16(out, 0); /* reserved + flags */
364  entries_pos = avio_tell(out);
365  avio_wb16(out, 0); /* entry count */
366 
367  data += 12;
368  size -= 12;
369  packet_len -= 12;
370 
371  entries = 0;
372  /* Write one or more constructors describing the payload data */
373  describe_payload(data, packet_len, out, &entries, &trk->sample_queue);
374  data += packet_len;
375  size -= packet_len;
376 
377  curpos = avio_tell(out);
378  avio_seek(out, entries_pos, SEEK_SET);
379  avio_wb16(out, entries);
380  avio_seek(out, curpos, SEEK_SET);
381  }
382 
383  curpos = avio_tell(out);
384  avio_seek(out, count_pos, SEEK_SET);
385  avio_wb16(out, count);
386  avio_seek(out, curpos, SEEK_SET);
387  return count;
388 }
389 
391  int track_index, int sample,
392  uint8_t *sample_data, int sample_size)
393 {
394  MOVMuxContext *mov = s->priv_data;
395  MOVTrack *trk = &mov->tracks[track_index];
396  AVFormatContext *rtp_ctx = trk->rtp_ctx;
397  uint8_t *buf = NULL;
398  int size;
399  AVIOContext *hintbuf = NULL;
400  AVPacket hint_pkt;
401  int ret = 0, count;
402 
403  if (!rtp_ctx)
404  return AVERROR(ENOENT);
405  if (!rtp_ctx->pb)
406  return AVERROR(ENOMEM);
407 
408  if (sample_data)
409  sample_queue_push(&trk->sample_queue, sample_data, sample_size, sample);
410  else
411  sample_queue_push(&trk->sample_queue, pkt->data, pkt->size, sample);
412 
413  /* Feed the packet to the RTP muxer */
414  ff_write_chained(rtp_ctx, 0, pkt, s);
415 
416  /* Fetch the output from the RTP muxer, open a new output buffer
417  * for next time. */
418  size = avio_close_dyn_buf(rtp_ctx->pb, &buf);
419  if ((ret = ffio_open_dyn_packet_buf(&rtp_ctx->pb,
420  RTP_MAX_PACKET_SIZE)) < 0)
421  goto done;
422 
423  if (size <= 0)
424  goto done;
425 
426  /* Open a buffer for writing the hint */
427  if ((ret = avio_open_dyn_buf(&hintbuf)) < 0)
428  goto done;
429  av_init_packet(&hint_pkt);
430  count = write_hint_packets(hintbuf, buf, size, trk, &hint_pkt.dts);
431  av_freep(&buf);
432 
433  /* Write the hint data into the hint track */
434  hint_pkt.size = size = avio_close_dyn_buf(hintbuf, &buf);
435  hint_pkt.data = buf;
436  hint_pkt.pts = hint_pkt.dts;
437  hint_pkt.stream_index = track_index;
438  if (pkt->flags & AV_PKT_FLAG_KEY)
439  hint_pkt.flags |= AV_PKT_FLAG_KEY;
440  if (count > 0)
441  ff_mov_write_packet(s, &hint_pkt);
442 done:
443  av_free(buf);
445  return ret;
446 }
447 
449  AVFormatContext* rtp_ctx = track->rtp_ctx;
450  uint8_t *ptr;
451 
452  av_freep(&track->enc);
454  if (!rtp_ctx)
455  return;
456  if (rtp_ctx->pb) {
457  av_write_trailer(rtp_ctx);
458  avio_close_dyn_buf(rtp_ctx->pb, &ptr);
459  av_free(ptr);
460  }
461  avformat_free_context(rtp_ctx);
462 }
AVFormatContext * rtp_ctx
the format context for the hinting rtp muxer
Definition: movenc.h:113
uint8_t * data
Definition: movenc.h:58
const char * s
Definition: avisynth_c.h:668
Bytestream IO Context.
Definition: avio.h:68
static void output_match(AVIOContext *out, int match_sample, int match_offset, int match_len, int *entries)
Definition: movenchint.c:270
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:988
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
int src_track
the track that this hint (or tmcd) track describes
Definition: movenc.h:112
static void output_immediate(const uint8_t *data, int size, AVIOContext *out, int *entries)
Definition: movenchint.c:250
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:199
#define RTP_MAX_PACKET_SIZE
Definition: movenc.h:32
AVCodecContext * enc
Definition: movenc.h:100
void * av_realloc(void *ptr, size_t size)
Allocate or reallocate a block of memory.
Definition: mem.c:141
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:976
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
int offset
Definition: movenc.h:61
uint8_t
Opaque data information usually continuous.
Definition: avutil.h:145
#define AV_RB32
static AVPacket pkt
Definition: demuxing.c:56
AVStream ** streams
Definition: avformat.h:992
uint8_t * data
int own_data
Definition: movenc.h:62
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:248
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:173
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
int sample_number
Definition: movenc.h:60
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
unsigned timescale
Definition: movenc.h:81
int tag
stsd fourcc
Definition: movenc.h:99
HintSample * samples
Definition: movenc.h:68
#define AV_RB16
Spectrum Plot time data
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
int hint_track
the track that hints this track, -1 if no hint track is set
Definition: movenc.h:111
int size
int flags
A combination of AV_PKT_FLAG values.
AVCodecContext * avcodec_alloc_context3(const AVCodec *codec)
Allocate an AVCodecContext and set its fields to default values.
ret
Definition: avfilter.c:821
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:981
int32_t
uint32_t max_packet_size
Definition: movenc.h:116
int64_t cur_rtp_ts_unwrapped
Definition: movenc.h:115
int size
Definition: movenc.h:59
static int write_hint_packets(AVIOContext *out, const uint8_t *data, int size, MOVTrack *trk, int64_t *pts)
Write an RTP hint (that may contain one or more RTP packets) for the packets in data.
Definition: movenchint.c:315
Stream structure.
Definition: avformat.h:643
static void describe_payload(const uint8_t *data, int size, AVIOContext *out, int *entries, HintSampleQueue *queue)
Definition: movenchint.c:283
NULL
Definition: eval.c:55
static void sample_queue_free(HintSampleQueue *queue)
Empty the sample queue, releasing all memory.
Definition: movenchint.c:83
enum AVMediaType codec_type
AVIOContext * pb
I/O context.
Definition: avformat.h:977
void avio_w8(AVIOContext *s, int b)
Definition: aviobuf.c:151
unsigned int codec_tag
fourcc (LSB first, so "ABCD" -> (&#39;D&#39;<<24) + (&#39;C&#39;<<16) + (&#39;B&#39;<<8) + &#39;A&#39;).
void * buf
Definition: avisynth_c.h:594
int ff_mov_init_hinting(AVFormatContext *s, int index, int src_index)
Definition: movenchint.c:29
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
int index
Definition: gxfenc.c:89
synthesis window for stochastic i
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.
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
uint32_t prev_rtp_ts
Definition: movenc.h:114
#define RTP_PT_IS_RTCP(x)
Definition: rtp.h:109
void avio_wb16(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:373
track
Definition: brsc.py:18
int ff_rtp_chain_mux_open(AVFormatContext **out, AVFormatContext *s, AVStream *st, URLContext *handle, int packet_size, int idx)
Definition: rtpenc_chain.c:29
HintSampleQueue sample_queue
Definition: movenc.h:122
static void sample_queue_retain(HintSampleQueue *queue)
Make local copies of all referenced sample data in the queue.
Definition: movenchint.c:125
int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt, AVFormatContext *src)
Write a packet to another muxer than the one the user originally intended.
void av_init_packet(AVPacket *pkt)
Initialize optional fields of a packet with default values.
Definition: avpacket.c:56
int den
denominator
Definition: rational.h:45
int len
void * priv_data
Format private data.
Definition: avformat.h:964
void ff_mov_close_hinting(MOVTrack *track)
Definition: movenchint.c:448
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:769
void avio_wb32(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:299
Filter the word “frame” indicates either a video frame or a group of audio samples
void INT64 INT64 count
Definition: avisynth_c.h:594
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31))))#define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac){}void ff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map){AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);return NULL;}return ac;}in_planar=av_sample_fmt_is_planar(in_fmt);out_planar=av_sample_fmt_is_planar(out_fmt);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;}int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){int use_generic=1;int len=in->nb_samples;int p;if(ac->dc){av_dlog(ac->avr,"%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> out
int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: movenc.c:3120
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avformat.h:679
#define MKTAG(a, b, c, d)
Definition: common.h:282
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.
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:390
MOVTrack * tracks
Definition: movenc.h:152
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