Merge commit 'bef3b1f59f036aba4a5fe599b2480f6bd9e6b280'
authorDerek Buitenhuis <derek.buitenhuis@gmail.com>
Wed, 18 Nov 2015 16:40:16 +0000 (16:40 +0000)
committerDerek Buitenhuis <derek.buitenhuis@gmail.com>
Wed, 18 Nov 2015 16:40:16 +0000 (16:40 +0000)
* commit 'bef3b1f59f036aba4a5fe599b2480f6bd9e6b280':
  movenc: Allow setting start_dts/start_cts before writing actual packets

Merged-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
1  2 
libavformat/movenc.c

@@@ -4574,7 -3592,19 +4571,19 @@@ static int mov_write_single_packet(AVFo
              mov->flags &= ~FF_MOV_FLAG_FRAG_DISCONT;
          }
  
 -        if (trk->entry)
+         if (!pkt->size) {
+             if (trk->start_dts == AV_NOPTS_VALUE && trk->frag_discont) {
+                 trk->start_dts = pkt->dts;
+                 if (pkt->pts != AV_NOPTS_VALUE)
+                     trk->start_cts = pkt->pts - pkt->dts;
+                 else
+                     trk->start_cts = 0;
+             }
+             return 0;             /* Discard 0 sized packets */
+         }
 +        if (trk->entry && pkt->stream_index < s->nb_streams)
              frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts,
                                           s->streams[pkt->stream_index]->time_base,
                                           AV_TIME_BASE_Q);
          }
  
          return ff_mov_write_packet(s, pkt);
-         if (!pkt->size) return 0; /* Discard 0 sized packets */
 +}
 +
 +static int mov_write_subtitle_end_packet(AVFormatContext *s,
 +                                         int stream_index,
 +                                         int64_t dts) {
 +    AVPacket end;
 +    uint8_t data[2] = {0};
 +    int ret;
 +
 +    av_init_packet(&end);
 +    end.size = sizeof(data);
 +    end.data = data;
 +    end.pts = dts;
 +    end.dts = dts;
 +    end.duration = 0;
 +    end.stream_index = stream_index;
 +
 +    ret = mov_write_single_packet(s, &end);
 +    av_packet_unref(&end);
 +
 +    return ret;
 +}
 +
 +static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
 +{
 +    if (!pkt) {
 +        mov_flush_fragment(s, 1);
 +        return 1;
 +    } else {
 +        int i;
 +        MOVMuxContext *mov = s->priv_data;
 +
++        if (!pkt->size)
++            return mov_write_single_packet(s, pkt); /* Passthrough. */
 +
 +        /*
 +         * Subtitles require special handling.
 +         *
 +         * 1) For full complaince, every track must have a sample at
 +         * dts == 0, which is rarely true for subtitles. So, as soon
 +         * as we see any packet with dts > 0, write an empty subtitle
 +         * at dts == 0 for any subtitle track with no samples in it.
 +         *
 +         * 2) For each subtitle track, check if the current packet's
 +         * dts is past the duration of the last subtitle sample. If
 +         * so, we now need to write an end sample for that subtitle.
 +         *
 +         * This must be done conditionally to allow for subtitles that
 +         * immediately replace each other, in which case an end sample
 +         * is not needed, and is, in fact, actively harmful.
 +         *
 +         * 3) See mov_write_trailer for how the final end sample is
 +         * handled.
 +         */
 +        for (i = 0; i < mov->nb_streams; i++) {
 +            MOVTrack *trk = &mov->tracks[i];
 +            int ret;
 +
 +            if (trk->enc->codec_id == AV_CODEC_ID_MOV_TEXT &&
 +                trk->track_duration < pkt->dts &&
 +                (trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
 +                ret = mov_write_subtitle_end_packet(s, i, trk->track_duration);
 +                if (ret < 0) return ret;
 +                trk->last_sample_is_subtitle_end = 1;
 +            }
 +        }
 +
 +        return mov_write_single_packet(s, pkt);
      }
  }