Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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->enc = avcodec_alloc_context3(NULL);
  41.     if (!track->enc)
  42.         goto fail;
  43.     track->enc->codec_type = AVMEDIA_TYPE_DATA;
  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:
  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;
  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.  */
  83. static void sample_queue_free(HintSampleQueue *queue)
  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.  */
  99. static void sample_queue_push(HintSampleQueue *queue, uint8_t *data, int size,
  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) {
  107.         HintSample *samples;
  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.  */
  125. static void sample_queue_retain(HintSampleQueue *queue)
  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.  */
  315. static int write_hint_packets(AVIOContext *out, const uint8_t *data,
  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.  
  401. int ff_mov_add_hinted_packet(AVFormatContext *s, AVPacket *pkt,
  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);
  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);
  455.     sample_queue_retain(&trk->sample_queue);
  456.     return ret;
  457. }
  458.  
  459. void ff_mov_close_hinting(MOVTrack *track)
  460. {
  461.     AVFormatContext *rtp_ctx = track->rtp_ctx;
  462.     uint8_t *ptr;
  463.  
  464.     av_freep(&track->enc);
  465.     sample_queue_free(&track->sample_queue);
  466.     if (!rtp_ctx)
  467.         return;
  468.     if (rtp_ctx->pb) {
  469.         av_write_trailer(rtp_ctx);
  470.         avio_close_dyn_buf(rtp_ctx->pb, &ptr);
  471.         av_free(ptr);
  472.     }
  473.     avformat_free_context(rtp_ctx);
  474. }
  475.