Merge commit 'fe5d5a8ffcafdc14c0d26eaea6464c89e120cc9e'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 22 Aug 2013 11:42:47 +0000 (13:42 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 22 Aug 2013 11:58:23 +0000 (13:58 +0200)
* commit 'fe5d5a8ffcafdc14c0d26eaea6464c89e120cc9e':
  movenc: Make chapter track QuickTime compatible

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavformat/movenc.c

@@@ -3382,10 -2980,8 +3382,10 @@@ static int mov_write_packet(AVFormatCon
  
  // QuickTime chapters involve an additional text track with the chapter names
  // as samples, and a tref pointing from the other tracks to the chapter one.
- static void mov_create_chapter_track(AVFormatContext *s, int tracknum)
+ static int mov_create_chapter_track(AVFormatContext *s, int tracknum)
  {
 +    AVIOContext *pb;
 +
      MOVMuxContext *mov = s->priv_data;
      MOVTrack *track = &mov->tracks[tracknum];
      AVPacket pkt = { .stream_index = tracknum, .flags = AV_PKT_FLAG_KEY };
      track->timescale = MOV_TIMESCALE;
      track->enc = avcodec_alloc_context3(NULL);
      track->enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
++#if 0
+     track->enc->extradata = av_malloc(sizeof(chapter_properties));
+     if (track->enc->extradata == NULL)
+         return AVERROR(ENOMEM);
+     track->enc->extradata_size = sizeof(chapter_properties);
+     memcpy(track->enc->extradata, chapter_properties, sizeof(chapter_properties));
++#else
 +    if (avio_open_dyn_buf(&pb) >= 0) {
 +        int size;
 +        uint8_t *buf;
 +
 +        /* Stub header (usually for Quicktime chapter track) */
 +        // TextSampleEntry
 +        avio_wb32(pb, 0x01); // displayFlags
 +        avio_w8(pb, 0x00);   // horizontal justification
 +        avio_w8(pb, 0x00);   // vertical justification
 +        avio_w8(pb, 0x00);   // bgColourRed
 +        avio_w8(pb, 0x00);   // bgColourGreen
 +        avio_w8(pb, 0x00);   // bgColourBlue
 +        avio_w8(pb, 0x00);   // bgColourAlpha
 +        // BoxRecord
 +        avio_wb16(pb, 0x00); // defTextBoxTop
 +        avio_wb16(pb, 0x00); // defTextBoxLeft
 +        avio_wb16(pb, 0x00); // defTextBoxBottom
 +        avio_wb16(pb, 0x00); // defTextBoxRight
 +        // StyleRecord
 +        avio_wb16(pb, 0x00); // startChar
 +        avio_wb16(pb, 0x00); // endChar
 +        avio_wb16(pb, 0x01); // fontID
 +        avio_w8(pb, 0x00);   // fontStyleFlags
 +        avio_w8(pb, 0x00);   // fontSize
 +        avio_w8(pb, 0x00);   // fgColourRed
 +        avio_w8(pb, 0x00);   // fgColourGreen
 +        avio_w8(pb, 0x00);   // fgColourBlue
 +        avio_w8(pb, 0x00);   // fgColourAlpha
 +        // FontTableBox
 +        avio_wb32(pb, 0x0D); // box size
 +        ffio_wfourcc(pb, "ftab"); // box atom name
 +        avio_wb16(pb, 0x01); // entry count
 +        // FontRecord
 +        avio_wb16(pb, 0x01); // font ID
 +        avio_w8(pb, 0x00);   // font name length
 +
 +        if ((size = avio_close_dyn_buf(pb, &buf)) > 0) {
 +            track->enc->extradata = buf;
 +            track->enc->extradata_size = size;
 +        } else {
 +            av_free(&buf);
 +        }
 +    }
++#endif
  
      for (i = 0; i < s->nb_chapters; i++) {
          AVChapter *c = s->chapters[i];
              av_freep(&pkt.data);
          }
      }
+     return 0;
  }
  
 +static int mov_create_timecode_track(AVFormatContext *s, int index, int src_index, const char *tcstr)
 +{
 +    int ret;
 +    MOVMuxContext *mov  = s->priv_data;
 +    MOVTrack *track     = &mov->tracks[index];
 +    AVStream *src_st    = s->streams[src_index];
 +    AVTimecode tc;
 +    AVPacket pkt    = {.stream_index = index, .flags = AV_PKT_FLAG_KEY, .size = 4};
 +    AVRational rate = {src_st->codec->time_base.den, src_st->codec->time_base.num};
 +
 +    /* if the codec time base makes no sense, try to fallback on stream frame rate */
 +    if (av_timecode_check_frame_rate(rate) < 0) {
 +        av_log(s, AV_LOG_DEBUG, "timecode: tbc=%d/%d invalid, fallback on %d/%d\n",
 +               rate.num, rate.den, src_st->avg_frame_rate.num, src_st->avg_frame_rate.den);
 +        rate = src_st->avg_frame_rate;
 +    }
 +
 +    /* compute the frame number */
 +    ret = av_timecode_init_from_string(&tc, rate, tcstr, s);
 +    if (ret < 0)
 +        return ret;
 +
 +    /* tmcd track based on video stream */
 +    track->mode      = mov->mode;
 +    track->tag       = MKTAG('t','m','c','d');
 +    track->src_track = src_index;
 +    track->timescale = mov->tracks[src_index].timescale;
 +    if (tc.flags & AV_TIMECODE_FLAG_DROPFRAME)
 +        track->timecode_flags |= MOV_TIMECODE_FLAG_DROPFRAME;
 +
 +    /* encode context: tmcd data stream */
 +    track->enc = avcodec_alloc_context3(NULL);
 +    track->enc->codec_type = AVMEDIA_TYPE_DATA;
 +    track->enc->codec_tag  = track->tag;
 +    track->enc->time_base  = src_st->codec->time_base;
 +
 +    /* the tmcd track just contains one packet with the frame number */
 +    pkt.data = av_malloc(pkt.size);
 +    AV_WB32(pkt.data, tc.start);
 +    ret = ff_mov_write_packet(s, &pkt);
 +    av_free(pkt.data);
 +    return ret;
 +}
 +
  static int mov_write_header(AVFormatContext *s)
  {
      AVIOContext *pb = s->pb;