dashenc: Don't segment all video streams when one stream gets a keyframe
This makes sure that segments actually start at a keyframe (and makes sure we don't split segments twice in a row, with one segment consisting of only a handful of packets), when one stream uses b-frames while another one doesn't. Signed-off-by: Martin Storsjö <martin@martin.st>
This commit is contained in:
		
							parent
							
								
									6f26f14f13
								
							
						
					
					
						commit
						fe42f94ce1
					
				| @ -75,7 +75,6 @@ typedef struct DASHContext { | ||||
|     int single_file; | ||||
|     OutputStream *streams; | ||||
|     int has_video, has_audio; | ||||
|     int nb_segments; | ||||
|     int last_duration; | ||||
|     int total_duration; | ||||
|     char availability_start_time[100]; | ||||
| @ -595,10 +594,13 @@ static void find_index_range(AVFormatContext *s, const char *dirname, | ||||
|     *index_length = AV_RB32(&buf[0]); | ||||
| } | ||||
| 
 | ||||
| static int dash_flush(AVFormatContext *s, int final) | ||||
| static int dash_flush(AVFormatContext *s, int final, int stream) | ||||
| { | ||||
|     DASHContext *c = s->priv_data; | ||||
|     int i, ret = 0; | ||||
|     int cur_flush_segment_index = 0; | ||||
|     if (stream >= 0) | ||||
|         cur_flush_segment_index = c->streams[stream].segment_index; | ||||
| 
 | ||||
|     for (i = 0; i < s->nb_streams; i++) { | ||||
|         OutputStream *os = &c->streams[i]; | ||||
| @ -609,6 +611,18 @@ static int dash_flush(AVFormatContext *s, int final) | ||||
|         if (!os->packets_written) | ||||
|             continue; | ||||
| 
 | ||||
|         // Flush the single stream that got a keyframe right now.
 | ||||
|         // Flush all audio streams as well, in sync with video keyframes,
 | ||||
|         // but not the other video streams.
 | ||||
|         if (stream >= 0 && i != stream) { | ||||
|             if (s->streams[i]->codec->codec_type != AVMEDIA_TYPE_AUDIO) | ||||
|                 continue; | ||||
|             // Make sure we don't flush audio streams multiple times, when
 | ||||
|             // all video streams are flushed one at a time.
 | ||||
|             if (c->has_video && os->segment_index > cur_flush_segment_index) | ||||
|                 continue; | ||||
|         } | ||||
| 
 | ||||
|         if (!c->single_file) { | ||||
|             snprintf(filename, sizeof(filename), "chunk-stream%d-%05d.m4s", i, os->segment_index); | ||||
|             snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, filename); | ||||
| @ -665,7 +679,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) | ||||
|     DASHContext *c = s->priv_data; | ||||
|     AVStream *st = s->streams[pkt->stream_index]; | ||||
|     OutputStream *os = &c->streams[pkt->stream_index]; | ||||
|     int64_t seg_end_duration = (c->nb_segments + 1) * (int64_t) c->min_seg_duration; | ||||
|     int64_t seg_end_duration = (os->segment_index) * (int64_t) c->min_seg_duration; | ||||
|     int ret; | ||||
| 
 | ||||
|     // If forcing the stream to start at 0, the mp4 muxer will set the start
 | ||||
| @ -701,9 +715,8 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if ((ret = dash_flush(s, 0)) < 0) | ||||
|         if ((ret = dash_flush(s, 0, pkt->stream_index)) < 0) | ||||
|             return ret; | ||||
|         c->nb_segments++; | ||||
|     } | ||||
| 
 | ||||
|     if (!os->packets_written) | ||||
| @ -729,7 +742,7 @@ static int dash_write_trailer(AVFormatContext *s) | ||||
|                                          s->streams[0]->time_base, | ||||
|                                          AV_TIME_BASE_Q); | ||||
|     } | ||||
|     dash_flush(s, 1); | ||||
|     dash_flush(s, 1, -1); | ||||
| 
 | ||||
|     if (c->remove_at_exit) { | ||||
|         char filename[1024]; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user