Ticket #1842: segment.patch

File segment.patch, 7.9 KB (added by Teric, 14 years ago)

a patch for libavformat/segment.c

  • libavformat/segment.c

    old new  
    7474    double start_time, end_time;
    7575} SegmentContext;
    7676
    77 typedef struct _ListSeg {
    78     int index;
    79     float start;
    80     float end;
    81     char segname[64];
    82     struct _ListSeg *next;
    83 } SegEntity;
    84 
    85 SegEntity *SegList = NULL; /* buffered list */
    86 int SegNum = 0; /* buffered list objects number */
    87 int SeqOffset = 0; /* init value of EXT-X-MEDIA-SEQUENCE */
    88 char SegName[1024] = {0}; /* tmp list name */
    89 
    9077static void print_csv_escaped_str(AVIOContext *ctx, const char *str)
    9178{
    9279    int needs_quoting = !!str[strcspn(str, "\",\n\r")];
     
    10390        avio_w8(ctx, '"');
    10491}
    10592
    106 /* dump buffered list objects to play list */
    107 static int seg_dump(AVFormatContext *s)
    108 {
    109     SegEntity *p;
    110     SegmentContext *seg = s->priv_data;
    111     int count = 0;
    112     int ret = 0;
    113 
    114     /* make there are at least 3 objects in the list */
    115     if(SegNum < 3) {
    116         av_log(s, AV_LOG_ERROR, "delay dump coz %d segments hold\n", SegNum);
    117         return -1;
    118     }
    119    
    120     ret = avio_open2(&seg->list_pb, &SegName[0], AVIO_FLAG_WRITE, &s->interrupt_callback, NULL); // open tmp list
    121     if (ret < 0)
    122         return ret;
    123 
    124     p = SegList;
    125    
    126     if (seg->list_type == LIST_TYPE_FLAT) {
    127         while(p) {
    128             avio_printf(seg->list_pb, "%s\n", p->segname);
    129             p = p->next;
    130             count++;
    131         }
    132     } else if (seg->list_type == LIST_TYPE_CSV || seg->list_type == LIST_TYPE_EXT) {
    133         while(p) {
    134             print_csv_escaped_str(seg->list_pb, p->segname);
    135             avio_printf(seg->list_pb, ",%f,%f\n", p->start, p->end);
    136             p = p->next;
    137             count++;
    138         }
    139     } else if (seg->list_type == LIST_TYPE_M3U8) {
    140         avio_printf(seg->list_pb, "#EXTM3U\n");
    141         /*avio_printf(seg->list_pb, "#EXT-X-VERSION:3\n");*/
    142         avio_printf(seg->list_pb, "#EXT-X-MEDIA-SEQUENCE:%d\n", p?SeqOffset:0);
    143 
    144         /*avio_printf(seg->list_pb, "#EXT-X-ALLOWCACHE:%d\n",
    145                     !!(seg->list_flags & SEGMENT_LIST_FLAG_CACHE));*/
    146         if (seg->list_flags & SEGMENT_LIST_FLAG_LIVE)
    147             avio_printf(seg->list_pb, "#EXT-X-TARGETDURATION:%"PRId64"\n", seg->time / 1000000);
    148 
    149         while(p) {
    150             avio_printf(seg->list_pb, "#EXTINF:%d,\n%s\n", (int)(p->end - p->start), p->segname);
    151             av_log(s, AV_LOG_ERROR, "\tdump %s\n", p->segname);
    152             p = p->next;
    153             count++;
    154         }
    155 
    156         avio_flush(seg->list_pb);
    157     }
    158 
    159     avio_close(seg->list_pb);
    160     if(count > 0) {
    161         rename(SegName, seg->list);
    162         av_log(s, AV_LOG_ERROR, "dump %d %d segments to list\n", count, SegNum);
    163     }
    164 
    165     if(count != SegNum) {
    166         av_log(s, AV_LOG_ERROR, "seg queue is inconsistent %d %d\n", count, SegNum);
    167     }
    168 }
    169 
    170 static int seg_enqueue(int cur_idx, float start, float end, char* name)
    171 {
    172     SegEntity *tail;
    173     SegEntity *p;
    174     if (!name)
    175         goto failed;
    176     tail = SegList;
    177     p = SegList;
    178     while(p) {
    179         tail = p;
    180         p = p->next;
    181     }
    182    
    183     p = (SegEntity*)av_malloc(sizeof(SegEntity));
    184     if (!p)
    185         goto failed;
    186     p->next = NULL;
    187     p->index = cur_idx - 1;
    188     p->start = start;
    189     p->end = end;
    190     strcpy(p->segname, name);
    191    
    192     if (!SegList)
    193         SegList = p;
    194     else
    195         tail->next = p;
    196    
    197     SegNum++;
    198     return SegNum;
    199 failed:
    200     return -1;
    201 }
    202 
    203 static SegEntity* seg_dequeue()
    204 {
    205     SegEntity *p;
    206     p = SegList;
    207     if(p) {
    208         SegList = p->next;
    209         SegNum--;
    210         return p;
    211     }
    212     return NULL;
    213 }
    214 
    215 /* prepare overlaped list, which is better for VLC */
    216 static int seg_shrink(int limit)
    217 {
    218     SegEntity *p;
    219     if(SegNum > limit) {
    220         p = seg_dequeue();
    221         if(p) {
    222             av_free(p);
    223             SeqOffset++;
    224         }
    225     }
    226     return SegNum;
    227 }
    228 
    229 /* prepare non-overlaped list */
    230 static int seg_shrink2(int limit)
    231 {
    232     SegEntity *p;
    233     if(SegNum == limit) {
    234         p = seg_dequeue();
    235         while(p) {
    236             av_free(p);
    237             p = seg_dequeue();
    238         }
    239     }
    240     return SegNum;
    241 }
    242 
    24393static int segment_start(AVFormatContext *s)
    24494{
    24595    SegmentContext *seg = s->priv_data;
     
    255105        return AVERROR(EINVAL);
    256106    }
    257107    seg->segment_count++;
    258     av_log(s, AV_LOG_ERROR, "segment count %d index %d wrap %d filename %s\n", seg->segment_count, seg->segment_idx, seg->segment_idx_wrap, oc->filename);
    259108
    260109    if ((err = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
    261110                          &s->interrupt_callback, NULL)) < 0)
     
    293142    SegmentContext *seg = s->priv_data;
    294143    int ret;
    295144
    296     ret = avio_open2(&seg->list_pb, &SegName[0], AVIO_FLAG_WRITE,
     145    ret = avio_open2(&seg->list_pb, seg->list, AVIO_FLAG_WRITE,
    297146                     &s->interrupt_callback, NULL);
    298147    if (ret < 0)
    299148        return ret;
     
    333182    SegmentContext *seg = s->priv_data;
    334183    AVFormatContext *oc = seg->avf;
    335184    int ret = 0;
    336     int num = 0;
    337185
    338186    if (oc->oformat->write_trailer)
    339187        ret = oc->oformat->write_trailer(oc);
     
    344192
    345193    if (seg->list) {
    346194        if (seg->list_size && !(seg->segment_count % seg->list_size)) {
    347             /*segment_list_close(s);
     195            segment_list_close(s);
    348196            if ((ret = segment_list_open(s)) < 0)
    349                 goto end;*/
    350            
     197                goto end;
    351198        }
    352199
    353         num = seg_enqueue(seg->segment_idx, seg->start_time, seg->end_time, oc->filename);
    354200        if (seg->list_type == LIST_TYPE_FLAT) {
    355             /*avio_printf(seg->list_pb, "%s\n", oc->filename);*/
    356             if(num > 0) {
    357                 seg_dump(s);
    358                 seg_shrink2(seg->list_size);
    359             }
     201            avio_printf(seg->list_pb, "%s\n", oc->filename);
    360202        } else if (seg->list_type == LIST_TYPE_CSV || seg->list_type == LIST_TYPE_EXT) {
    361             /*print_csv_escaped_str(seg->list_pb, oc->filename);
    362             avio_printf(seg->list_pb, ",%f,%f\n", seg->start_time, seg->end_time);*/
    363             if(num > 0) {
    364                 seg_dump(s);
    365                 seg_shrink2(seg->list_size);
    366             }
     203            print_csv_escaped_str(seg->list_pb, oc->filename);
     204            avio_printf(seg->list_pb, ",%f,%f\n", seg->start_time, seg->end_time);
    367205        } else if (seg->list_type == LIST_TYPE_M3U8) {
    368             /*avio_printf(seg->list_pb, "#EXTINF:%f,\n%s\n",
    369                         seg->end_time - seg->start_time, oc->filename);*/
    370             num = seg_shrink(seg->list_size);
    371             if(num > 0) {
    372                 seg_dump(s);
    373                 /*seg_shrink2(seg->list_size);*/
    374             }
     206            avio_printf(seg->list_pb, "#EXTINF:%f,\n%s\n",
     207                        seg->end_time - seg->start_time, oc->filename);
    375208        }
    376209        seg->list_max_segment_time = FFMAX(seg->end_time - seg->start_time, seg->list_max_segment_time);
    377         /*avio_flush(seg->list_pb);*/
     210        avio_flush(seg->list_pb);
    378211    }
    379212
    380213end:
     
    446279    int ret, i;
    447280
    448281    seg->segment_count = 0;
    449     /*tuohu: use timestamp as init segment index which is better for skip stale cache objects when restarting on CDN */
    450     snprintf(SegName, "tmp_%s", seg->list, strlen(seg->list));
    451     if (seg->segment_idx == 0) {
    452         seg->segment_idx = ((int)(ff_ntp_time() / 100000));
    453         SeqOffset = seg->segment_idx - 1000;
    454         SeqOffset = SeqOffset > 0 ? SeqOffset : 0;
    455     }
    456282
    457283    if (seg->time_str && seg->times_str) {
    458284        av_log(s, AV_LOG_ERROR,
     
    503329            else if (av_match_ext(seg->list, "m3u8")) seg->list_type = LIST_TYPE_M3U8;
    504330            else                                      seg->list_type = LIST_TYPE_FLAT;
    505331        }
    506         /*if ((ret = segment_list_open(s)) < 0)
    507             goto fail;*/
     332        if ((ret = segment_list_open(s)) < 0)
     333            goto fail;
    508334    }
    509335    if (seg->list_type == LIST_TYPE_EXT)
    510336        av_log(s, AV_LOG_WARNING, "'ext' list type option is deprecated in favor of 'csv'\n");
     
    542368        goto fail;
    543369    }
    544370    seg->segment_count++;
    545     av_log(s, AV_LOG_ERROR, "segment count %d index %d wrap %d filename %s (init)\n", seg->segment_count, seg->segment_idx, seg->segment_idx_wrap, oc->filename);
    546371
    547372    if ((ret = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
    548373                          &s->interrupt_callback, NULL)) < 0)