Ticket #1842: segment.patch

File segment.patch, 7.9 KB (added by teric, 4 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)