Ticket #1842: segment.patch
| File segment.patch, 7.9 KB (added by teric, 7 months ago) |
|---|
-
libavformat/segment.c
old new 74 74 double start_time, end_time; 75 75 } SegmentContext; 76 76 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 90 77 static void print_csv_escaped_str(AVIOContext *ctx, const char *str) 91 78 { 92 79 int needs_quoting = !!str[strcspn(str, "\",\n\r")]; … … 103 90 avio_w8(ctx, '"'); 104 91 } 105 92 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 list121 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 else195 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 243 93 static int segment_start(AVFormatContext *s) 244 94 { 245 95 SegmentContext *seg = s->priv_data; … … 255 105 return AVERROR(EINVAL); 256 106 } 257 107 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);259 108 260 109 if ((err = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE, 261 110 &s->interrupt_callback, NULL)) < 0) … … 293 142 SegmentContext *seg = s->priv_data; 294 143 int ret; 295 144 296 ret = avio_open2(&seg->list_pb, &SegName[0], AVIO_FLAG_WRITE,145 ret = avio_open2(&seg->list_pb, seg->list, AVIO_FLAG_WRITE, 297 146 &s->interrupt_callback, NULL); 298 147 if (ret < 0) 299 148 return ret; … … 333 182 SegmentContext *seg = s->priv_data; 334 183 AVFormatContext *oc = seg->avf; 335 184 int ret = 0; 336 int num = 0;337 185 338 186 if (oc->oformat->write_trailer) 339 187 ret = oc->oformat->write_trailer(oc); … … 344 192 345 193 if (seg->list) { 346 194 if (seg->list_size && !(seg->segment_count % seg->list_size)) { 347 /*segment_list_close(s);195 segment_list_close(s); 348 196 if ((ret = segment_list_open(s)) < 0) 349 goto end;*/ 350 197 goto end; 351 198 } 352 199 353 num = seg_enqueue(seg->segment_idx, seg->start_time, seg->end_time, oc->filename);354 200 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); 360 202 } 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); 367 205 } 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); 375 208 } 376 209 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); 378 211 } 379 212 380 213 end: … … 446 279 int ret, i; 447 280 448 281 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 }456 282 457 283 if (seg->time_str && seg->times_str) { 458 284 av_log(s, AV_LOG_ERROR, … … 503 329 else if (av_match_ext(seg->list, "m3u8")) seg->list_type = LIST_TYPE_M3U8; 504 330 else seg->list_type = LIST_TYPE_FLAT; 505 331 } 506 /*if ((ret = segment_list_open(s)) < 0)507 goto fail; */332 if ((ret = segment_list_open(s)) < 0) 333 goto fail; 508 334 } 509 335 if (seg->list_type == LIST_TYPE_EXT) 510 336 av_log(s, AV_LOG_WARNING, "'ext' list type option is deprecated in favor of 'csv'\n"); … … 542 368 goto fail; 543 369 } 544 370 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);546 371 547 372 if ((ret = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE, 548 373 &s->interrupt_callback, NULL)) < 0)
