2 * MOV, 3GP, MP4 muxer RTP hinting
3 * Copyright (c) 2010 Martin Storsjo
5 * This file is part of Libav.
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.
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.
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
23 #include "libavutil/intreadwrite.h"
25 #include "rtpenc_chain.h"
26 #include "avio_internal.h"
29 int ff_mov_init_hinting(AVFormatContext
*s
, int index
, int src_index
)
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
);
37 track
->tag
= MKTAG('r','t','p',' ');
38 track
->src_track
= src_index
;
40 track
->enc
= avcodec_alloc_context3(NULL
);
43 track
->enc
->codec_type
= AVMEDIA_TYPE_DATA
;
44 track
->enc
->codec_tag
= track
->tag
;
46 ret
= ff_rtp_chain_mux_open(&track
->rtp_ctx
, s
, src_st
, NULL
,
47 RTP_MAX_PACKET_SIZE
, src_index
);
51 /* Copy the RTP AVStream timebase back to the hint AVStream */
52 track
->timescale
= track
->rtp_ctx
->streams
[0]->time_base
.den
;
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
;
59 av_log(s
, AV_LOG_WARNING
,
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;
68 * Remove the first sample from the sample queue.
70 static void sample_queue_pop(HintSampleQueue
*queue
)
74 if (queue
->samples
[0].own_data
)
75 av_free(queue
->samples
[0].data
);
77 memmove(queue
->samples
, queue
->samples
+ 1, sizeof(HintSample
)*queue
->len
);
81 * Empty the sample queue, releasing all memory.
83 static void sample_queue_free(HintSampleQueue
*queue
)
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
);
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
99 static void sample_queue_push(HintSampleQueue
*queue
, uint8_t *data
, int size
,
102 /* No need to keep track of smaller samples, since describing them
103 * with immediates is more efficient. */
106 if (!queue
->samples
|| queue
->len
>= queue
->size
) {
109 samples
= av_realloc(queue
->samples
, sizeof(HintSample
)*queue
->size
);
112 queue
->samples
= samples
;
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;
123 * Make local copies of all referenced sample data in the queue.
125 static void sample_queue_retain(HintSampleQueue
*queue
)
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
);
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));
139 memcpy(ptr
, sample
->data
, sample
->size
);
141 sample
->own_data
= 1;
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).
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
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
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
,
169 for (h_pos
= 0; h_pos
< h_len
; h_pos
++) {
171 int match_h_pos
, match_n_pos
;
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
])
180 /* If a sufficiently large match was found, try to expand
181 * the matched segment backwards. */
184 while (match_n_pos
> 0 && match_h_pos
> 0 &&
185 needle
[match_n_pos
- 1] == haystack
[match_h_pos
- 1]) {
192 *match_h_offset_ptr
= match_h_pos
;
193 *match_n_offset_ptr
= match_n_pos
;
194 *match_len_ptr
= match_len
;
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.
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
215 static int find_sample_match(const uint8_t *data
, int len
,
216 HintSampleQueue
*queue
, int *pos
,
217 int *match_sample
, int *match_offset
,
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)
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 */
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;
243 /* No match for this sample, remove it */
244 sample_queue_pop(queue
);
250 static void output_immediate(const uint8_t *data
, int size
,
251 AVIOContext
*out
, int *entries
)
257 avio_w8(out
, 1); /* immediate constructor */
258 avio_w8(out
, len
); /* amount of valid data */
259 avio_write(out
, data
, len
);
263 for (; len
< 14; len
++)
270 static void output_match(AVIOContext
*out
, int match_sample
,
271 int match_offset
, int match_len
, int *entries
)
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 */
283 static void describe_payload(const uint8_t *data
, int size
,
284 AVIOContext
*out
, int *entries
,
285 HintSampleQueue
*queue
)
287 /* Describe the payload using different constructors */
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)
293 output_immediate(data
, pos
, out
, entries
);
296 output_match(out
, match_sample
, match_offset
, match_len
, entries
);
300 output_immediate(data
, size
, out
, entries
);
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
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
315 static int write_hint_packets(AVIOContext
*out
, const uint8_t *data
,
316 int size
, MOVTrack
*trk
, int64_t *pts
)
319 int64_t count_pos
, entries_pos
;
320 int count
= 0, entries
;
322 count_pos
= avio_tell(out
);
323 /* RTPsample header */
324 avio_wb16(out
, 0); /* packet count */
325 avio_wb16(out
, 0); /* reserved */
328 uint32_t packet_len
= AV_RB32(data
);
334 if (packet_len
> size
|| packet_len
<= 12)
336 if (RTP_PT_IS_RTCP(data
[1])) {
337 /* RTCP packet, just skip */
343 if (packet_len
> trk
->max_packet_size
)
344 trk
->max_packet_size
= packet_len
;
346 seq
= AV_RB16(&data
[2]);
347 ts
= AV_RB32(&data
[4]);
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
;
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 */
372 /* Write one or more constructors describing the payload data */
373 describe_payload(data
, packet_len
, out
, &entries
, &trk
->sample_queue
);
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
);
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
);
390 int ff_mov_add_hinted_packet(AVFormatContext
*s
, AVPacket
*pkt
,
391 int track_index
, int sample
,
392 uint8_t *sample_data
, int sample_size
)
394 MOVMuxContext
*mov
= s
->priv_data
;
395 MOVTrack
*trk
= &mov
->tracks
[track_index
];
396 AVFormatContext
*rtp_ctx
= trk
->rtp_ctx
;
399 AVIOContext
*hintbuf
= NULL
;
404 return AVERROR(ENOENT
);
406 return AVERROR(ENOMEM
);
409 sample_queue_push(&trk
->sample_queue
, sample_data
, sample_size
, sample
);
411 sample_queue_push(&trk
->sample_queue
, pkt
->data
, pkt
->size
, sample
);
413 /* Feed the packet to the RTP muxer */
414 ff_write_chained(rtp_ctx
, 0, pkt
, s
);
416 /* Fetch the output from the RTP muxer, open a new output buffer
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)
426 /* Open a buffer for writing the hint */
427 if ((ret
= avio_open_dyn_buf(&hintbuf
)) < 0)
429 av_init_packet(&hint_pkt
);
430 count
= write_hint_packets(hintbuf
, buf
, size
, trk
, &hint_pkt
.dts
);
433 /* Write the hint data into the hint track */
434 hint_pkt
.size
= size
= avio_close_dyn_buf(hintbuf
, &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
;
441 ff_mov_write_packet(s
, &hint_pkt
);
444 sample_queue_retain(&trk
->sample_queue
);
448 void ff_mov_close_hinting(MOVTrack
*track
) {
449 AVFormatContext
* rtp_ctx
= track
->rtp_ctx
;
452 av_freep(&track
->enc
);
453 sample_queue_free(&track
->sample_queue
);
457 av_write_trailer(rtp_ctx
);
458 avio_close_dyn_buf(rtp_ctx
->pb
, &ptr
);
461 avformat_free_context(rtp_ctx
);