diff --git a/packager/media/base/media_handler.h b/packager/media/base/media_handler.h
index 18f4bc6482a..7dfd63f10e7 100644
--- a/packager/media/base/media_handler.h
+++ b/packager/media/base/media_handler.h
@@ -57,6 +57,7 @@ struct SegmentInfo {
   bool is_encrypted = false;
   int64_t start_timestamp = -1;
   int64_t duration = 0;
+  int64_t segment_index = 0;
   // This is only available if key rotation is enabled. Note that we may have
   // a |key_rotation_encryption_config| even if the segment is not encrypted,
   // which is the case for clear lead.
diff --git a/packager/media/base/media_handler_test_base.cc b/packager/media/base/media_handler_test_base.cc
index 87e42aa4003..0146843a1e9 100644
--- a/packager/media/base/media_handler_test_base.cc
+++ b/packager/media/base/media_handler_test_base.cc
@@ -249,6 +249,7 @@ std::unique_ptr<SegmentInfo> MediaHandlerTestBase::GetSegmentInfo(
   info->start_timestamp = start_timestamp;
   info->duration = duration;
   info->is_subsegment = is_subsegment;
+  info->segment_index = start_timestamp / duration + 1;
 
   return info;
 }
diff --git a/packager/media/chunking/chunking_handler.cc b/packager/media/chunking/chunking_handler.cc
index a9686071d21..25a18eeed27 100644
--- a/packager/media/chunking/chunking_handler.cc
+++ b/packager/media/chunking/chunking_handler.cc
@@ -26,6 +26,10 @@ bool IsNewSegmentIndex(int64_t new_index, int64_t current_index) {
          new_index != current_index - 1;
 }
 
+bool isGreaterSegmentIndex(int64_t new_index, int64_t current_index) {
+  return new_index > current_index;
+}
+
 }  // namespace
 
 ChunkingHandler::ChunkingHandler(const ChunkingParams& chunking_params)
@@ -60,6 +64,7 @@ Status ChunkingHandler::Process(std::unique_ptr<StreamData> stream_data) {
 }
 
 Status ChunkingHandler::OnFlushRequest(size_t input_stream_index) {
+  set_segment_index_++;
   RETURN_IF_ERROR(EndSegmentIfStarted());
   return FlushDownstream(kStreamIndex);
 }
@@ -74,6 +79,7 @@ Status ChunkingHandler::OnStreamInfo(std::shared_ptr<const StreamInfo> info) {
 }
 
 Status ChunkingHandler::OnCueEvent(std::shared_ptr<const CueEvent> event) {
+  set_segment_index_++;
   RETURN_IF_ERROR(EndSegmentIfStarted());
   const double event_time_in_seconds = event->time_in_seconds;
   RETURN_IF_ERROR(DispatchCueEvent(kStreamIndex, std::move(event)));
@@ -89,7 +95,6 @@ Status ChunkingHandler::OnCueEvent(std::shared_ptr<const CueEvent> event) {
 Status ChunkingHandler::OnMediaSample(
     std::shared_ptr<const MediaSample> sample) {
   DCHECK_NE(time_scale_, 0u) << "kStreamInfo should arrive before kMediaSample";
-
   const int64_t timestamp = sample->pts();
 
   bool started_new_segment = false;
@@ -101,6 +106,11 @@ Status ChunkingHandler::OnMediaSample(
                                 : (timestamp - cue_offset_) / segment_duration_;
     if (!segment_start_time_ ||
         IsNewSegmentIndex(segment_index, current_segment_index_)) {
+      if (!isGreaterSegmentIndex(segment_index, set_segment_index_)) {
+        set_segment_index_ = current_segment_index_ + 1;
+      } else {
+        set_segment_index_ = segment_index;
+      }
       current_segment_index_ = segment_index;
       // Reset subsegment index.
       current_subsegment_index_ = 0;
@@ -151,6 +161,7 @@ Status ChunkingHandler::EndSegmentIfStarted() const {
   auto segment_info = std::make_shared<SegmentInfo>();
   segment_info->start_timestamp = segment_start_time_.value();
   segment_info->duration = max_segment_time_ - segment_start_time_.value();
+  segment_info->segment_index = set_segment_index_;
   return DispatchSegmentInfo(kStreamIndex, std::move(segment_info));
 }
 
diff --git a/packager/media/chunking/chunking_handler.h b/packager/media/chunking/chunking_handler.h
index 8159c8758de..e7dd8333b68 100644
--- a/packager/media/chunking/chunking_handler.h
+++ b/packager/media/chunking/chunking_handler.h
@@ -72,7 +72,7 @@ class ChunkingHandler : public MediaHandler {
   // Segment and subsegment duration in stream's time scale.
   int64_t segment_duration_ = 0;
   int64_t subsegment_duration_ = 0;
-
+  int64_t set_segment_index_ = 0;
   // Current segment index, useful to determine where to do chunking.
   int64_t current_segment_index_ = -1;
   // Current subsegment index, useful to determine where to do chunking.
diff --git a/packager/media/chunking/text_chunker.cc b/packager/media/chunking/text_chunker.cc
index ea43f69ec17..60f3bb6fc0b 100644
--- a/packager/media/chunking/text_chunker.cc
+++ b/packager/media/chunking/text_chunker.cc
@@ -35,6 +35,7 @@ Status TextChunker::OnFlushRequest(size_t input_stream_index) {
   // Keep outputting segments until all the samples leave the system. Calling
   // |DispatchSegment| will remove samples over time.
   while (samples_in_current_segment_.size()) {
+    segment_index_++;
     RETURN_IF_ERROR(DispatchSegment(segment_duration_));
   }
 
@@ -107,6 +108,10 @@ Status TextChunker::DispatchSegment(int64_t duration) {
   std::shared_ptr<SegmentInfo> info = std::make_shared<SegmentInfo>();
   info->start_timestamp = segment_start_;
   info->duration = duration;
+  if (((segment_start_ / segment_duration_) + 1) > segment_index_) {
+    segment_index_ = (segment_start_ / segment_duration_) + 1;
+  }
+  info->segment_index = segment_index_;
   RETURN_IF_ERROR(DispatchSegmentInfo(kStreamIndex, std::move(info)));
 
   // Move onto the next segment.
diff --git a/packager/media/chunking/text_chunker.h b/packager/media/chunking/text_chunker.h
index 8e9e09accb4..b252d201bff 100644
--- a/packager/media/chunking/text_chunker.h
+++ b/packager/media/chunking/text_chunker.h
@@ -52,6 +52,7 @@ class TextChunker : public MediaHandler {
   int64_t segment_start_ = -1;     // Set when the first sample comes in.
   int64_t segment_duration_ = -1;  // Set in OnStreamInfo.
 
+  int64_t segment_index_ = 0;
   // All samples that make up the current segment. We must store the samples
   // until the segment ends because a cue event may end the segment sooner
   // than we expected.
diff --git a/packager/media/event/combined_muxer_listener.cc b/packager/media/event/combined_muxer_listener.cc
index 6c28e267056..ab6aaa31763 100644
--- a/packager/media/event/combined_muxer_listener.cc
+++ b/packager/media/event/combined_muxer_listener.cc
@@ -59,9 +59,11 @@ void CombinedMuxerListener::OnMediaEnd(const MediaRanges& media_ranges,
 void CombinedMuxerListener::OnNewSegment(const std::string& file_name,
                                          int64_t start_time,
                                          int64_t duration,
-                                         uint64_t segment_file_size) {
+                                         uint64_t segment_file_size,
+                                         uint64_t segment_index) {
   for (auto& listener : muxer_listeners_) {
-    listener->OnNewSegment(file_name, start_time, duration, segment_file_size);
+    listener->OnNewSegment(file_name, start_time, duration, segment_file_size,
+                           segment_index);
   }
 }
 
diff --git a/packager/media/event/combined_muxer_listener.h b/packager/media/event/combined_muxer_listener.h
index 2528974ae7d..368871f5aba 100644
--- a/packager/media/event/combined_muxer_listener.h
+++ b/packager/media/event/combined_muxer_listener.h
@@ -42,7 +42,8 @@ class CombinedMuxerListener : public MuxerListener {
   void OnNewSegment(const std::string& file_name,
                     int64_t start_time,
                     int64_t duration,
-                    uint64_t segment_file_size) override;
+                    uint64_t segment_file_size,
+                    uint64_t index_segment) override;
   void OnKeyFrame(int64_t timestamp, uint64_t start_byte_offset, uint64_t size);
   void OnCueEvent(int64_t timestamp, const std::string& cue_data) override;
   /// @}
diff --git a/packager/media/event/hls_notify_muxer_listener.cc b/packager/media/event/hls_notify_muxer_listener.cc
index fdd326c4b6a..7dc75a4152e 100644
--- a/packager/media/event/hls_notify_muxer_listener.cc
+++ b/packager/media/event/hls_notify_muxer_listener.cc
@@ -228,7 +228,8 @@ void HlsNotifyMuxerListener::OnMediaEnd(const MediaRanges& media_ranges,
 void HlsNotifyMuxerListener::OnNewSegment(const std::string& file_name,
                                           int64_t start_time,
                                           int64_t duration,
-                                          uint64_t segment_file_size) {
+                                          uint64_t segment_file_size,
+                                          uint64_t segment_index) {
   if (!media_info_->has_segment_template()) {
     EventInfo event_info;
     event_info.type = EventInfoType::kSegment;
diff --git a/packager/media/event/hls_notify_muxer_listener.h b/packager/media/event/hls_notify_muxer_listener.h
index ed0cb8a4183..8bd26c32427 100644
--- a/packager/media/event/hls_notify_muxer_listener.h
+++ b/packager/media/event/hls_notify_muxer_listener.h
@@ -67,7 +67,8 @@ class HlsNotifyMuxerListener : public MuxerListener {
   void OnNewSegment(const std::string& file_name,
                     int64_t start_time,
                     int64_t duration,
-                    uint64_t segment_file_size) override;
+                    uint64_t segment_file_size,
+                    uint64_t segment_index) override;
   void OnKeyFrame(int64_t timestamp, uint64_t start_byte_offset, uint64_t size);
   void OnCueEvent(int64_t timestamp, const std::string& cue_data) override;
   /// @}
diff --git a/packager/media/event/hls_notify_muxer_listener_unittest.cc b/packager/media/event/hls_notify_muxer_listener_unittest.cc
index d0923a8f443..622525721c1 100644
--- a/packager/media/event/hls_notify_muxer_listener_unittest.cc
+++ b/packager/media/event/hls_notify_muxer_listener_unittest.cc
@@ -345,7 +345,7 @@ TEST_F(HlsNotifyMuxerListenerTest, OnNewSegmentAndCueEvent) {
                        kSegmentDuration, _, kSegmentSize));
   listener_.OnCueEvent(kCueStartTime, "dummy cue data");
   listener_.OnNewSegment("new_segment_name10.ts", kSegmentStartTime,
-                         kSegmentDuration, kSegmentSize);
+                         kSegmentDuration, kSegmentSize, 10);
 }
 
 // Verify that the notifier is called for every segment in OnMediaEnd if
@@ -363,7 +363,7 @@ TEST_F(HlsNotifyMuxerListenerTest, NoSegmentTemplateOnMediaEnd) {
 
   listener_.OnCueEvent(kCueStartTime, "dummy cue data");
   listener_.OnNewSegment("filename.mp4", kSegmentStartTime, kSegmentDuration,
-                         kSegmentSize);
+                         kSegmentSize, 0);
 
   EXPECT_CALL(mock_notifier_, NotifyCueEvent(_, kCueStartTime));
   EXPECT_CALL(
@@ -393,7 +393,7 @@ TEST_F(HlsNotifyMuxerListenerTest, NoSegmentTemplateOnMediaEndTwice) {
   listener_.OnMediaStart(muxer_options1, *video_stream_info, 90000,
                          MuxerListener::kContainerMpeg2ts);
   listener_.OnNewSegment("filename1.mp4", kSegmentStartTime, kSegmentDuration,
-                         kSegmentSize);
+                         kSegmentSize, 1);
   listener_.OnCueEvent(kCueStartTime, "dummy cue data");
 
   EXPECT_CALL(mock_notifier_, NotifyNewStream(_, _, _, _, _))
@@ -410,7 +410,7 @@ TEST_F(HlsNotifyMuxerListenerTest, NoSegmentTemplateOnMediaEndTwice) {
   listener_.OnMediaStart(muxer_options2, *video_stream_info, 90000,
                          MuxerListener::kContainerMpeg2ts);
   listener_.OnNewSegment("filename2.mp4", kSegmentStartTime + kSegmentDuration,
-                         kSegmentDuration, kSegmentSize);
+                         kSegmentDuration, kSegmentSize, 2);
   EXPECT_CALL(mock_notifier_,
               NotifyNewSegment(_, StrEq("filename2.mp4"),
                                kSegmentStartTime + kSegmentDuration, _, _, _));
@@ -436,7 +436,7 @@ TEST_F(HlsNotifyMuxerListenerTest,
                          MuxerListener::kContainerMpeg2ts);
 
   listener_.OnNewSegment("filename.mp4", kSegmentStartTime, kSegmentDuration,
-                         kSegmentSize);
+                         kSegmentSize, 0);
   EXPECT_CALL(
       mock_notifier_,
       NotifyNewSegment(_, StrEq("filename.mp4"), kSegmentStartTime,
@@ -498,7 +498,7 @@ TEST_P(HlsNotifyMuxerListenerKeyFrameTest, NoSegmentTemplate) {
   listener_.OnKeyFrame(kKeyFrameTimestamp, kKeyFrameStartByteOffset,
                        kKeyFrameSize);
   listener_.OnNewSegment("filename.mp4", kSegmentStartTime, kSegmentDuration,
-                         kSegmentSize);
+                         kSegmentSize, 0);
 
   EXPECT_CALL(mock_notifier_,
               NotifyKeyFrame(_, kKeyFrameTimestamp,
diff --git a/packager/media/event/mock_muxer_listener.h b/packager/media/event/mock_muxer_listener.h
index 818fb4bcbac..c74075fe7fe 100644
--- a/packager/media/event/mock_muxer_listener.h
+++ b/packager/media/event/mock_muxer_listener.h
@@ -53,14 +53,14 @@ class MockMuxerListener : public MuxerListener {
 
   // Windows 32 bit cannot mock MediaRanges because it has Optionals that use
   // memory alignment of 8 bytes. The compiler fails if it is mocked.
-  void OnMediaEnd(const MediaRanges& range,
-                  float duration_seconds) override;
+  void OnMediaEnd(const MediaRanges& range, float duration_seconds) override;
 
-  MOCK_METHOD4(OnNewSegment,
+  MOCK_METHOD5(OnNewSegment,
                void(const std::string& segment_name,
                     int64_t start_time,
                     int64_t duration,
-                    uint64_t segment_file_size));
+                    uint64_t segment_file_size,
+                    uint64_t segment_index));
 
   MOCK_METHOD3(OnKeyFrame,
                void(int64_t timestamp,
diff --git a/packager/media/event/mpd_notify_muxer_listener.cc b/packager/media/event/mpd_notify_muxer_listener.cc
index 749b7843cba..1b0b8137d64 100644
--- a/packager/media/event/mpd_notify_muxer_listener.cc
+++ b/packager/media/event/mpd_notify_muxer_listener.cc
@@ -57,17 +57,13 @@ void MpdNotifyMuxerListener::OnEncryptionInfoReady(
 
 void MpdNotifyMuxerListener::OnEncryptionStart() {}
 
-void MpdNotifyMuxerListener::OnMediaStart(
-    const MuxerOptions& muxer_options,
-    const StreamInfo& stream_info,
-    uint32_t time_scale,
-    ContainerType container_type) {
+void MpdNotifyMuxerListener::OnMediaStart(const MuxerOptions& muxer_options,
+                                          const StreamInfo& stream_info,
+                                          uint32_t time_scale,
+                                          ContainerType container_type) {
   std::unique_ptr<MediaInfo> media_info(new MediaInfo());
-  if (!internal::GenerateMediaInfo(muxer_options,
-                                   stream_info,
-                                   time_scale,
-                                   container_type,
-                                   media_info.get())) {
+  if (!internal::GenerateMediaInfo(muxer_options, stream_info, time_scale,
+                                   container_type, media_info.get())) {
     LOG(ERROR) << "Failed to generate MediaInfo from input.";
     return;
   }
@@ -79,7 +75,8 @@ void MpdNotifyMuxerListener::OnMediaStart(
   if (is_encrypted_) {
     internal::SetContentProtectionFields(protection_scheme_, default_key_id_,
                                          key_system_info_, media_info.get());
-    media_info->mutable_protected_content()->set_include_mspr_pro(mpd_notifier_->include_mspr_pro());
+    media_info->mutable_protected_content()->set_include_mspr_pro(
+        mpd_notifier_->include_mspr_pro());
   }
 
   // The content may be splitted into multiple files, but their MediaInfo
@@ -102,8 +99,7 @@ void MpdNotifyMuxerListener::OnMediaStart(
 
 // Record the sample duration in the media info for VOD so that OnMediaEnd, all
 // the information is in the media info.
-void MpdNotifyMuxerListener::OnSampleDurationReady(
-    uint32_t sample_duration) {
+void MpdNotifyMuxerListener::OnSampleDurationReady(uint32_t sample_duration) {
   if (mpd_notifier_->dash_profile() == DashProfile::kLive) {
     mpd_notifier_->NotifySampleDuration(notification_id_.value(),
                                         sample_duration);
@@ -157,7 +153,10 @@ void MpdNotifyMuxerListener::OnMediaEnd(const MediaRanges& media_ranges,
         mpd_notifier_->NotifyNewSegment(
             notification_id_.value(), event_info.segment_info.start_time,
             event_info.segment_info.duration,
-            event_info.segment_info.segment_file_size);
+            event_info.segment_info.segment_file_size,
+            (event_info.segment_info.start_time /
+             event_info.segment_info.duration) +
+                1);
         break;
       case EventInfoType::kKeyFrame:
         // NO-OP for DASH.
@@ -175,10 +174,11 @@ void MpdNotifyMuxerListener::OnMediaEnd(const MediaRanges& media_ranges,
 void MpdNotifyMuxerListener::OnNewSegment(const std::string& file_name,
                                           int64_t start_time,
                                           int64_t duration,
-                                          uint64_t segment_file_size) {
+                                          uint64_t segment_file_size,
+                                          uint64_t segment_index) {
   if (mpd_notifier_->dash_profile() == DashProfile::kLive) {
     mpd_notifier_->NotifyNewSegment(notification_id_.value(), start_time,
-                                    duration, segment_file_size);
+                                    duration, segment_file_size, segment_index);
     if (mpd_notifier_->mpd_type() == MpdType::kDynamic)
       mpd_notifier_->Flush();
   } else {
diff --git a/packager/media/event/mpd_notify_muxer_listener.h b/packager/media/event/mpd_notify_muxer_listener.h
index ffa84c1f865..112d55e3572 100644
--- a/packager/media/event/mpd_notify_muxer_listener.h
+++ b/packager/media/event/mpd_notify_muxer_listener.h
@@ -50,7 +50,8 @@ class MpdNotifyMuxerListener : public MuxerListener {
   void OnNewSegment(const std::string& file_name,
                     int64_t start_time,
                     int64_t duration,
-                    uint64_t segment_file_size) override;
+                    uint64_t segment_file_size,
+                    uint64_t segment_index) override;
   void OnKeyFrame(int64_t timestamp, uint64_t start_byte_offset, uint64_t size);
   void OnCueEvent(int64_t timestamp, const std::string& cue_data) override;
   /// @}
diff --git a/packager/media/event/mpd_notify_muxer_listener_unittest.cc b/packager/media/event/mpd_notify_muxer_listener_unittest.cc
index 219fac18266..a102ef11d18 100644
--- a/packager/media/event/mpd_notify_muxer_listener_unittest.cc
+++ b/packager/media/event/mpd_notify_muxer_listener_unittest.cc
@@ -62,15 +62,13 @@ namespace media {
 
 class MpdNotifyMuxerListenerTest : public ::testing::TestWithParam<MpdType> {
  public:
-
   void SetupForVod() {
     MpdOptions mpd_options;
     mpd_options.dash_profile = DashProfile::kOnDemand;
     // On-demand profile should be static.
     mpd_options.mpd_type = MpdType::kStatic;
     notifier_.reset(new MockMpdNotifier(mpd_options));
-    listener_.reset(
-        new MpdNotifyMuxerListener(notifier_.get()));
+    listener_.reset(new MpdNotifyMuxerListener(notifier_.get()));
   }
 
   void SetupForLive() {
@@ -256,24 +254,24 @@ TEST_F(MpdNotifyMuxerListenerTest, VodOnNewSegment) {
   const uint64_t kSegmentFileSize2 = 83743u;
 
   EXPECT_CALL(*notifier_, NotifyNewContainer(_, _)).Times(0);
-  EXPECT_CALL(*notifier_, NotifyNewSegment(_, _, _, _)).Times(0);
+  EXPECT_CALL(*notifier_, NotifyNewSegment(_, _, _, _, _)).Times(0);
   listener_->OnMediaStart(muxer_options, *video_stream_info,
                           kDefaultReferenceTimeScale,
                           MuxerListener::kContainerMp4);
-  listener_->OnNewSegment("", kStartTime1, kDuration1, kSegmentFileSize1);
+  listener_->OnNewSegment("", kStartTime1, kDuration1, kSegmentFileSize1, 1);
   listener_->OnCueEvent(kStartTime2, "dummy cue data");
-  listener_->OnNewSegment("", kStartTime2, kDuration2, kSegmentFileSize2);
+  listener_->OnNewSegment("", kStartTime2, kDuration2, kSegmentFileSize2, 1);
   ::testing::Mock::VerifyAndClearExpectations(notifier_.get());
 
   InSequence s;
   EXPECT_CALL(*notifier_, NotifyNewContainer(
                               ExpectMediaInfoEq(kExpectedDefaultMediaInfo), _))
       .WillOnce(Return(true));
-  EXPECT_CALL(*notifier_,
-              NotifyNewSegment(_, kStartTime1, kDuration1, kSegmentFileSize1));
+  EXPECT_CALL(*notifier_, NotifyNewSegment(_, kStartTime1, kDuration1,
+                                           kSegmentFileSize1, 1));
   EXPECT_CALL(*notifier_, NotifyCueEvent(_, kStartTime2));
-  EXPECT_CALL(*notifier_,
-              NotifyNewSegment(_, kStartTime2, kDuration2, kSegmentFileSize2));
+  EXPECT_CALL(*notifier_, NotifyNewSegment(_, kStartTime2, kDuration2,
+                                           kSegmentFileSize2, 1));
   EXPECT_CALL(*notifier_, Flush());
   FireOnMediaEndWithParams(GetDefaultOnMediaEndParams());
 }
@@ -307,11 +305,11 @@ TEST_F(MpdNotifyMuxerListenerTest, VodMultipleFiles) {
 
   // Expectation for first file before OnMediaEnd.
   EXPECT_CALL(*notifier_, NotifyNewContainer(_, _)).Times(0);
-  EXPECT_CALL(*notifier_, NotifyNewSegment(_, _, _, _)).Times(0);
+  EXPECT_CALL(*notifier_, NotifyNewSegment(_, _, _, _, _)).Times(0);
   listener_->OnMediaStart(muxer_options1, *video_stream_info,
                           kDefaultReferenceTimeScale,
                           MuxerListener::kContainerMp4);
-  listener_->OnNewSegment("", kStartTime1, kDuration1, kSegmentFileSize1);
+  listener_->OnNewSegment("", kStartTime1, kDuration1, kSegmentFileSize1, 1);
   listener_->OnCueEvent(kStartTime2, "dummy cue data");
   ::testing::Mock::VerifyAndClearExpectations(notifier_.get());
 
@@ -320,8 +318,8 @@ TEST_F(MpdNotifyMuxerListenerTest, VodMultipleFiles) {
   EXPECT_CALL(*notifier_,
               NotifyNewContainer(EqualsProto(expected_media_info1), _))
       .WillOnce(Return(true));
-  EXPECT_CALL(*notifier_,
-              NotifyNewSegment(_, kStartTime1, kDuration1, kSegmentFileSize1));
+  EXPECT_CALL(*notifier_, NotifyNewSegment(_, kStartTime1, kDuration1,
+                                           kSegmentFileSize1, 1));
   EXPECT_CALL(*notifier_, NotifyCueEvent(_, kStartTime2));
   EXPECT_CALL(*notifier_, Flush());
   FireOnMediaEndWithParams(GetDefaultOnMediaEndParams());
@@ -330,13 +328,13 @@ TEST_F(MpdNotifyMuxerListenerTest, VodMultipleFiles) {
   listener_->OnMediaStart(muxer_options2, *video_stream_info,
                           kDefaultReferenceTimeScale,
                           MuxerListener::kContainerMp4);
-  listener_->OnNewSegment("", kStartTime2, kDuration2, kSegmentFileSize2);
+  listener_->OnNewSegment("", kStartTime2, kDuration2, kSegmentFileSize2, 1);
 
   // Expectation for second file OnMediaEnd.
   EXPECT_CALL(*notifier_,
               NotifyMediaInfoUpdate(_, EqualsProto(expected_media_info2)));
-  EXPECT_CALL(*notifier_,
-              NotifyNewSegment(_, kStartTime2, kDuration2, kSegmentFileSize2));
+  EXPECT_CALL(*notifier_, NotifyNewSegment(_, kStartTime2, kDuration2,
+                                           kSegmentFileSize2, 1));
   EXPECT_CALL(*notifier_, Flush());
   FireOnMediaEndWithParams(GetDefaultOnMediaEndParams());
 }
@@ -389,14 +387,14 @@ TEST_P(MpdNotifyMuxerListenerTest, LiveNoKeyRotation) {
   EXPECT_CALL(*notifier_,
               NotifyNewContainer(ExpectMediaInfoEq(kExpectedMediaInfo), _))
       .WillOnce(Return(true));
-  EXPECT_CALL(*notifier_,
-              NotifyNewSegment(_, kStartTime1, kDuration1, kSegmentFileSize1));
+  EXPECT_CALL(*notifier_, NotifyNewSegment(_, kStartTime1, kDuration1,
+                                           kSegmentFileSize1, 0));
   // Flush should only be called once in OnMediaEnd.
   if (GetParam() == MpdType::kDynamic)
     EXPECT_CALL(*notifier_, Flush());
   EXPECT_CALL(*notifier_, NotifyCueEvent(_, kStartTime2));
-  EXPECT_CALL(*notifier_,
-              NotifyNewSegment(_, kStartTime2, kDuration2, kSegmentFileSize2));
+  EXPECT_CALL(*notifier_, NotifyNewSegment(_, kStartTime2, kDuration2,
+                                           kSegmentFileSize2, 0));
   if (GetParam() == MpdType::kDynamic)
     EXPECT_CALL(*notifier_, Flush());
 
@@ -407,9 +405,9 @@ TEST_P(MpdNotifyMuxerListenerTest, LiveNoKeyRotation) {
   listener_->OnMediaStart(muxer_options, *video_stream_info,
                           kDefaultReferenceTimeScale,
                           MuxerListener::kContainerMp4);
-  listener_->OnNewSegment("", kStartTime1, kDuration1, kSegmentFileSize1);
+  listener_->OnNewSegment("", kStartTime1, kDuration1, kSegmentFileSize1, 0);
   listener_->OnCueEvent(kStartTime2, "dummy cue data");
-  listener_->OnNewSegment("", kStartTime2, kDuration2, kSegmentFileSize2);
+  listener_->OnNewSegment("", kStartTime2, kDuration2, kSegmentFileSize2, 0);
   ::testing::Mock::VerifyAndClearExpectations(notifier_.get());
 
   EXPECT_CALL(*notifier_, Flush())
@@ -462,13 +460,13 @@ TEST_P(MpdNotifyMuxerListenerTest, LiveWithKeyRotation) {
               NotifyNewContainer(ExpectMediaInfoEq(kExpectedMediaInfo), _))
       .WillOnce(Return(true));
   EXPECT_CALL(*notifier_, NotifyEncryptionUpdate(_, _, _, _)).Times(1);
-  EXPECT_CALL(*notifier_,
-              NotifyNewSegment(_, kStartTime1, kDuration1, kSegmentFileSize1));
+  EXPECT_CALL(*notifier_, NotifyNewSegment(_, kStartTime1, kDuration1,
+                                           kSegmentFileSize1, 0));
   // Flush should only be called once in OnMediaEnd.
   if (GetParam() == MpdType::kDynamic)
     EXPECT_CALL(*notifier_, Flush());
-  EXPECT_CALL(*notifier_,
-              NotifyNewSegment(_, kStartTime2, kDuration2, kSegmentFileSize2));
+  EXPECT_CALL(*notifier_, NotifyNewSegment(_, kStartTime2, kDuration2,
+                                           kSegmentFileSize2, 0));
   if (GetParam() == MpdType::kDynamic)
     EXPECT_CALL(*notifier_, Flush());
 
@@ -482,8 +480,8 @@ TEST_P(MpdNotifyMuxerListenerTest, LiveWithKeyRotation) {
   listener_->OnEncryptionInfoReady(kNonInitialEncryptionInfo, FOURCC_cbc1,
                                    std::vector<uint8_t>(), iv,
                                    GetDefaultKeySystemInfo());
-  listener_->OnNewSegment("", kStartTime1, kDuration1, kSegmentFileSize1);
-  listener_->OnNewSegment("", kStartTime2, kDuration2, kSegmentFileSize2);
+  listener_->OnNewSegment("", kStartTime1, kDuration1, kSegmentFileSize1, 0);
+  listener_->OnNewSegment("", kStartTime2, kDuration2, kSegmentFileSize2, 0);
   ::testing::Mock::VerifyAndClearExpectations(notifier_.get());
 
   EXPECT_CALL(*notifier_, Flush())
diff --git a/packager/media/event/multi_codec_muxer_listener_unittest.cc b/packager/media/event/multi_codec_muxer_listener_unittest.cc
index acce6036b9b..86f4a420939 100644
--- a/packager/media/event/multi_codec_muxer_listener_unittest.cc
+++ b/packager/media/event/multi_codec_muxer_listener_unittest.cc
@@ -79,10 +79,10 @@ TEST_F(MultiCodecMuxerListenerTest, OnNewSegmentAfterOnMediaStartSingleCodec) {
 
   EXPECT_CALL(*listener_for_first_codec_,
               OnNewSegment(StrEq("new_segment_name10.ts"), kSegmentStartTime,
-                           kSegmentDuration, kSegmentSize));
+                           kSegmentDuration, kSegmentSize, 10));
 
   multi_codec_listener_.OnNewSegment("new_segment_name10.ts", kSegmentStartTime,
-                                     kSegmentDuration, kSegmentSize);
+                                     kSegmentDuration, kSegmentSize, 10);
 }
 
 TEST_F(MultiCodecMuxerListenerTest, OnMediaStartTwoCodecs) {
@@ -114,13 +114,13 @@ TEST_F(MultiCodecMuxerListenerTest, OnNewSegmentAfterOnMediaStartTwoCodecs) {
 
   EXPECT_CALL(*listener_for_first_codec_,
               OnNewSegment(StrEq("new_segment_name10.ts"), kSegmentStartTime,
-                           kSegmentDuration, kSegmentSize));
+                           kSegmentDuration, kSegmentSize, 10));
   EXPECT_CALL(*listener_for_second_codec_,
               OnNewSegment(StrEq("new_segment_name10.ts"), kSegmentStartTime,
-                           kSegmentDuration, kSegmentSize));
+                           kSegmentDuration, kSegmentSize, 10));
 
   multi_codec_listener_.OnNewSegment("new_segment_name10.ts", kSegmentStartTime,
-                                     kSegmentDuration, kSegmentSize);
+                                     kSegmentDuration, kSegmentSize, 10);
 }
 
 }  // namespace media
diff --git a/packager/media/event/muxer_listener.h b/packager/media/event/muxer_listener.h
index 65946c124ed..72d83337288 100644
--- a/packager/media/event/muxer_listener.h
+++ b/packager/media/event/muxer_listener.h
@@ -124,10 +124,12 @@ class MuxerListener {
   /// @param duration is the duration of the segment, relative to the timescale
   ///        specified by MediaInfo passed to OnMediaStart().
   /// @param segment_file_size is the segment size in bytes.
+  /// @param segment_index is the segment index.
   virtual void OnNewSegment(const std::string& segment_name,
                             int64_t start_time,
                             int64_t duration,
-                            uint64_t segment_file_size) = 0;
+                            uint64_t segment_file_size,
+                            uint64_t segment_index) = 0;
 
   /// Called when there is a new key frame. For Video only. Note that it should
   /// be called before OnNewSegment is called on the containing segment.
diff --git a/packager/media/event/vod_media_info_dump_muxer_listener.cc b/packager/media/event/vod_media_info_dump_muxer_listener.cc
index e1f59c4948d..590714bb717 100644
--- a/packager/media/event/vod_media_info_dump_muxer_listener.cc
+++ b/packager/media/event/vod_media_info_dump_muxer_listener.cc
@@ -50,10 +50,10 @@ void VodMediaInfoDumpMuxerListener::OnMediaStart(
   DCHECK(muxer_options.segment_template.empty());
   media_info_.reset(new MediaInfo());
   if (!internal::GenerateMediaInfo(muxer_options,
-                                   stream_info,
-                                   time_scale,
+			           stream_info,
+				   time_scale,
                                    container_type,
-                                   media_info_.get())) {
+				   media_info_.get())) {
     LOG(ERROR) << "Failed to generate MediaInfo from input.";
     return;
   }
@@ -90,7 +90,8 @@ void VodMediaInfoDumpMuxerListener::OnMediaEnd(const MediaRanges& media_ranges,
 void VodMediaInfoDumpMuxerListener::OnNewSegment(const std::string& file_name,
                                                  int64_t start_time,
                                                  int64_t duration,
-                                                 uint64_t segment_file_size) {
+                                                 uint64_t segment_file_size,
+                                                 uint64_t segment_index) {
   const double segment_duration_seconds =
       static_cast<double>(duration) / media_info_->reference_time_scale();
 
diff --git a/packager/media/event/vod_media_info_dump_muxer_listener.h b/packager/media/event/vod_media_info_dump_muxer_listener.h
index 19044d472bc..08cdc7d2998 100644
--- a/packager/media/event/vod_media_info_dump_muxer_listener.h
+++ b/packager/media/event/vod_media_info_dump_muxer_listener.h
@@ -49,7 +49,8 @@ class VodMediaInfoDumpMuxerListener : public MuxerListener {
   void OnNewSegment(const std::string& file_name,
                     int64_t start_time,
                     int64_t duration,
-                    uint64_t segment_file_size) override;
+                    uint64_t segment_file_size,
+                    uint64_t segment_index) override;
   void OnKeyFrame(int64_t timestamp, uint64_t start_byte_offset, uint64_t size);
   void OnCueEvent(int64_t timestamp, const std::string& cue_data) override;
   /// @}
diff --git a/packager/media/event/vod_media_info_dump_muxer_listener_unittest.cc b/packager/media/event/vod_media_info_dump_muxer_listener_unittest.cc
index 9e74b191132..406774cfb8d 100644
--- a/packager/media/event/vod_media_info_dump_muxer_listener_unittest.cc
+++ b/packager/media/event/vod_media_info_dump_muxer_listener_unittest.cc
@@ -70,17 +70,14 @@ class VodMediaInfoDumpMuxerListenerTest : public ::testing::Test {
     ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path_));
     DLOG(INFO) << "Created temp file: " << temp_file_path_.value();
 
-    listener_.reset(new VodMediaInfoDumpMuxerListener(temp_file_path_
-                  .AsUTF8Unsafe()));
+    listener_.reset(
+        new VodMediaInfoDumpMuxerListener(temp_file_path_.AsUTF8Unsafe()));
   }
 
-  void TearDown() override {
-    base::DeleteFile(temp_file_path_, false);
-  }
+  void TearDown() override { base::DeleteFile(temp_file_path_, false); }
 
-  void FireOnMediaStartWithDefaultMuxerOptions(
-      const StreamInfo& stream_info,
-      bool enable_encryption) {
+  void FireOnMediaStartWithDefaultMuxerOptions(const StreamInfo& stream_info,
+                                               bool enable_encryption) {
     MuxerOptions muxer_options;
     SetDefaultMuxerOptions(&muxer_options);
     const uint32_t kReferenceTimeScale = 1000;
@@ -100,7 +97,7 @@ class VodMediaInfoDumpMuxerListenerTest : public ::testing::Test {
 
   void FireOnNewSegmentWithParams(const OnNewSegmentParameters& params) {
     listener_->OnNewSegment(params.file_name, params.start_time,
-                            params.duration, params.segment_file_size);
+                            params.duration, params.segment_file_size, 0);
   }
 
   void FireOnMediaEndWithParams(const OnMediaEndParameters& params) {
diff --git a/packager/media/formats/mp2t/ts_muxer.cc b/packager/media/formats/mp2t/ts_muxer.cc
index bd005afa047..cfa5d5262a0 100644
--- a/packager/media/formats/mp2t/ts_muxer.cc
+++ b/packager/media/formats/mp2t/ts_muxer.cc
@@ -43,7 +43,8 @@ Status TsMuxer::FinalizeSegment(size_t stream_id,
   return segment_info.is_subsegment
              ? Status::OK
              : segmenter_->FinalizeSegment(segment_info.start_timestamp,
-                                           segment_info.duration);
+                                           segment_info.duration,
+                                           segment_info.segment_index);
 }
 
 void TsMuxer::FireOnMediaStartEvent() {
diff --git a/packager/media/formats/mp2t/ts_segmenter.cc b/packager/media/formats/mp2t/ts_segmenter.cc
index aaea5ced179..b492e54be57 100644
--- a/packager/media/formats/mp2t/ts_segmenter.cc
+++ b/packager/media/formats/mp2t/ts_segmenter.cc
@@ -102,7 +102,7 @@ Status TsSegmenter::AddSample(const MediaSample& sample) {
   if (sample.is_encrypted())
     ts_writer_->SignalEncrypted();
 
-  if (!ts_writer_file_opened_ && !sample.is_key_frame())
+  if (!ts_writer_buffer_initialized_ && !sample.is_key_frame())
     LOG(WARNING) << "A segment will start with a non key frame.";
 
   if (!pes_packet_generator_->PushSample(sample)) {
@@ -122,19 +122,16 @@ void TsSegmenter::InjectPesPacketGeneratorForTesting(
 }
 
 void TsSegmenter::SetTsWriterFileOpenedForTesting(bool value) {
-  ts_writer_file_opened_ = value;
+  ts_writer_buffer_initialized_ = value;
 }
 
 Status TsSegmenter::OpenNewSegmentIfClosed(int64_t next_pts) {
-  if (ts_writer_file_opened_)
+  if (ts_writer_buffer_initialized_)
     return Status::OK;
-  const std::string segment_name =
-      GetSegmentName(muxer_options_.segment_template, next_pts,
-                     segment_number_++, muxer_options_.bandwidth);
-  if (!ts_writer_->NewSegment(segment_name))
+  next_pts_ = next_pts;
+  if (!ts_writer_->NewSegment())
     return Status(error::MUXER_FAILURE, "Failed to initilize TsPacketWriter.");
-  current_segment_path_ = segment_name;
-  ts_writer_file_opened_ = true;
+  ts_writer_buffer_initialized_ = true;
   return Status::OK;
 }
 
@@ -148,13 +145,13 @@ Status TsSegmenter::WritePesPacketsToFile() {
       return status;
 
     if (listener_ && IsVideoCodec(codec_) && pes_packet->is_key_frame()) {
-      base::Optional<uint64_t> start_pos = ts_writer_->GetFilePosition();
+      base::Optional<uint64_t> start_pos = ts_writer_->GetPosition();
 
       const int64_t timestamp = pes_packet->pts();
       if (!ts_writer_->AddPesPacket(std::move(pes_packet)))
         return Status(error::MUXER_FAILURE, "Failed to add PES packet.");
 
-      base::Optional<uint64_t> end_pos = ts_writer_->GetFilePosition();
+      base::Optional<uint64_t> end_pos = ts_writer_->GetPosition();
       if (!start_pos || !end_pos) {
         return Status(error::MUXER_FAILURE,
                       "Failed to get file position in WritePesPacketsToFile.");
@@ -169,30 +166,41 @@ Status TsSegmenter::WritePesPacketsToFile() {
 }
 
 Status TsSegmenter::FinalizeSegment(uint64_t start_timestamp,
-                                    uint64_t duration) {
+                                    uint64_t duration,
+                                    uint64_t segment_index) {
   if (!pes_packet_generator_->Flush()) {
-    return Status(error::MUXER_FAILURE,
-                  "Failed to flush PesPacketGenerator.");
+    return Status(error::MUXER_FAILURE, "Failed to flush PesPacketGenerator.");
   }
   Status status = WritePesPacketsToFile();
   if (!status.ok())
     return status;
 
-  // This method may be called from Finalize() so ts_writer_file_opened_ could
+  // This method may be called from Finalize() so ts_writer_buffer_initialized_ could
   // be false.
-  if (ts_writer_file_opened_) {
+  if (ts_writer_buffer_initialized_) {
+    std::string segment_name_segment_index =
+        GetSegmentName(muxer_options_.segment_template, next_pts_,
+                       segment_index - 1, muxer_options_.bandwidth);
+
+    current_segment_path_ = segment_name_segment_index;
+    if (!ts_writer_->CreateFileAndFlushBuffer(segment_name_segment_index)) {
+      LOG(ERROR) << "Failed to create new ts segment file.";
+    }
+
     if (!ts_writer_->FinalizeSegment()) {
       return Status(error::MUXER_FAILURE, "Failed to finalize TsWriter.");
     }
+    
     if (listener_) {
       const int64_t file_size =
           File::GetFileSize(current_segment_path_.c_str());
       listener_->OnNewSegment(current_segment_path_,
                               start_timestamp * timescale_scale_ +
                                   transport_stream_timestamp_offset_,
-                              duration * timescale_scale_, file_size);
+                              duration * timescale_scale_, file_size,
+                              segment_index);
     }
-    ts_writer_file_opened_ = false;
+    ts_writer_buffer_initialized_ = false;
   }
   current_segment_path_.clear();
   return Status::OK;
diff --git a/packager/media/formats/mp2t/ts_segmenter.h b/packager/media/formats/mp2t/ts_segmenter.h
index b140040eb71..dad7e840379 100644
--- a/packager/media/formats/mp2t/ts_segmenter.h
+++ b/packager/media/formats/mp2t/ts_segmenter.h
@@ -55,10 +55,13 @@ class TsSegmenter {
   ///        stream's time scale.
   /// @param duration is the segment's duration in the input stream's time
   ///        scale.
+  /// @param segment_index is the segment index.
   // TODO(kqyang): Remove the usage of segment start timestamp and duration in
   // xx_segmenter, which could cause confusions on which is the source of truth
   // as the segment start timestamp and duration could be tracked locally.
-  Status FinalizeSegment(uint64_t start_timestamp, uint64_t duration);
+  Status FinalizeSegment(uint64_t start_timestamp,
+                         uint64_t duration,
+                         uint64_t segment_index);
 
   /// Only for testing.
   void InjectTsWriterForTesting(std::unique_ptr<TsWriter> writer);
@@ -70,6 +73,8 @@ class TsSegmenter {
   /// Only for testing.
   void SetTsWriterFileOpenedForTesting(bool value);
 
+  int next_pts_ = -1;
+
  private:
   Status OpenNewSegmentIfClosed(int64_t next_pts);
 
@@ -89,13 +94,10 @@ class TsSegmenter {
   // Used for calculating the duration in seconds fo the current segment.
   double timescale_scale_ = 1.0;
 
-  // Used for segment template.
-  uint64_t segment_number_ = 0;
-
   std::unique_ptr<TsWriter> ts_writer_;
-  // Set to true if TsWriter::NewFile() succeeds, set to false after
-  // TsWriter::FinalizeFile() succeeds.
-  bool ts_writer_file_opened_ = false;
+  // Set to true if ts_writer buffer is initialized, set to false after
+  // TsWriter::FinalizeSegment() succeeds.
+  bool ts_writer_buffer_initialized_ = false;
   std::unique_ptr<PesPacketGenerator> pes_packet_generator_;
 
   // For OnNewSegment().
diff --git a/packager/media/formats/mp2t/ts_segmenter_unittest.cc b/packager/media/formats/mp2t/ts_segmenter_unittest.cc
index aa0fd31a9f1..4fbd392e744 100644
--- a/packager/media/formats/mp2t/ts_segmenter_unittest.cc
+++ b/packager/media/formats/mp2t/ts_segmenter_unittest.cc
@@ -81,7 +81,8 @@ class MockTsWriter : public TsWriter {
             // Create a bogus pmt writer, which we don't really care.
             new VideoProgramMapTableWriter(kUnknownCodec))) {}
 
-  MOCK_METHOD1(NewSegment, bool(const std::string& file_name));
+  MOCK_METHOD1(CreateFileAndFlushBuffer, bool(const std::string& file_name));
+  MOCK_METHOD0(NewSegment, bool());
   MOCK_METHOD0(SignalEncrypted, void());
   MOCK_METHOD0(FinalizeSegment, bool());
 
@@ -144,7 +145,7 @@ TEST_F(TsSegmenterTest, AddSample) {
       MediaSample::CopyFrom(kAnyData, arraysize(kAnyData), kIsKeyFrame);
 
   Sequence writer_sequence;
-  EXPECT_CALL(*mock_ts_writer_, NewSegment(StrEq("file1.ts")))
+  EXPECT_CALL(*mock_ts_writer_, NewSegment())
       .InSequence(writer_sequence)
       .WillOnce(Return(true));
 
@@ -159,8 +160,7 @@ TEST_F(TsSegmenterTest, AddSample) {
       .InSequence(ready_pes_sequence)
       .WillOnce(Return(0u));
 
-  EXPECT_CALL(*mock_ts_writer_, AddPesPacketMock(_))
-      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_ts_writer_, AddPesPacketMock(_)).WillOnce(Return(true));
 
   // The pointer is released inside the segmenter.
   EXPECT_CALL(*mock_pes_packet_generator_, GetNextPesPacketMock())
@@ -190,7 +190,6 @@ TEST_F(TsSegmenterTest, PassedSegmentDuration) {
 
   MockMuxerListener mock_listener;
   TsSegmenter segmenter(options, &mock_listener);
-
   const uint32_t kFirstPts = 1000;
 
   EXPECT_CALL(*mock_pes_packet_generator_, Initialize(_))
@@ -209,17 +208,16 @@ TEST_F(TsSegmenterTest, PassedSegmentDuration) {
   // duration.
   EXPECT_CALL(mock_listener,
               OnNewSegment("file1.ts", kFirstPts * kTimeScale / kInputTimescale,
-                           kTimeScale * 11, _));
+                           kTimeScale * 11, _, _));
 
   Sequence writer_sequence;
-  EXPECT_CALL(*mock_ts_writer_, NewSegment(StrEq("file1.ts")))
+  EXPECT_CALL(*mock_ts_writer_, NewSegment())
       .InSequence(writer_sequence)
       .WillOnce(Return(true));
 
   EXPECT_CALL(*mock_pes_packet_generator_, PushSample(_))
       .Times(2)
       .WillRepeatedly(Return(true));
-
   Sequence ready_pes_sequence;
   // First AddSample().
   EXPECT_CALL(*mock_pes_packet_generator_, NumberOfReadyPesPackets())
@@ -240,13 +238,13 @@ TEST_F(TsSegmenterTest, PassedSegmentDuration) {
       .InSequence(ready_pes_sequence)
       .WillOnce(Return(0u));
 
-  EXPECT_CALL(*mock_pes_packet_generator_, Flush())
-      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_pes_packet_generator_, Flush()).WillOnce(Return(true));
 
   EXPECT_CALL(*mock_ts_writer_, FinalizeSegment())
       .InSequence(writer_sequence)
       .WillOnce(Return(true));
-  EXPECT_CALL(*mock_ts_writer_, NewSegment(StrEq("file2.ts")))
+
+  EXPECT_CALL(*mock_ts_writer_, NewSegment())
       .InSequence(writer_sequence)
       .WillOnce(Return(true));
 
@@ -268,7 +266,7 @@ TEST_F(TsSegmenterTest, PassedSegmentDuration) {
   EXPECT_OK(segmenter.Initialize(*stream_info));
   segmenter.InjectTsWriterForTesting(std::move(mock_ts_writer_));
   EXPECT_OK(segmenter.AddSample(*sample1));
-  EXPECT_OK(segmenter.FinalizeSegment(kFirstPts, sample1->duration()));
+  EXPECT_OK(segmenter.FinalizeSegment(kFirstPts, sample1->duration(), 1));
   EXPECT_OK(segmenter.AddSample(*sample2));
 }
 
@@ -326,7 +324,7 @@ TEST_F(TsSegmenterTest, FinalizeSegment) {
   EXPECT_OK(segmenter.Initialize(*stream_info));
   segmenter.InjectTsWriterForTesting(std::move(mock_ts_writer_));
   segmenter.SetTsWriterFileOpenedForTesting(true);
-  EXPECT_OK(segmenter.FinalizeSegment(0, 100 /* arbitrary duration */));
+  EXPECT_OK(segmenter.FinalizeSegment(0, 100 /* arbitrary duration */, 1));
 }
 
 TEST_F(TsSegmenterTest, EncryptedSample) {
@@ -343,7 +341,7 @@ TEST_F(TsSegmenterTest, EncryptedSample) {
   MockMuxerListener mock_listener;
   TsSegmenter segmenter(options, &mock_listener);
 
-  ON_CALL(*mock_ts_writer_, NewSegment(_)).WillByDefault(Return(true));
+  ON_CALL(*mock_ts_writer_, NewSegment()).WillByDefault(Return(true));
   ON_CALL(*mock_ts_writer_, FinalizeSegment()).WillByDefault(Return(true));
   ON_CALL(*mock_ts_writer_, AddPesPacketMock(_)).WillByDefault(Return(true));
   ON_CALL(*mock_pes_packet_generator_, Initialize(_))
@@ -406,7 +404,7 @@ TEST_F(TsSegmenterTest, EncryptedSample) {
   segmenter.InjectTsWriterForTesting(std::move(mock_ts_writer_));
   EXPECT_OK(segmenter.AddSample(*sample1));
 
-  EXPECT_OK(segmenter.FinalizeSegment(1, sample1->duration()));
+  EXPECT_OK(segmenter.FinalizeSegment(1, sample1->duration(), 1));
   // Signal encrypted if sample is encrypted.
   EXPECT_CALL(*mock_ts_writer_raw, SignalEncrypted());
   sample2->set_is_encrypted(true);
diff --git a/packager/media/formats/mp2t/ts_writer.cc b/packager/media/formats/mp2t/ts_writer.cc
index d8dc540178f..a473d0ca5c9 100644
--- a/packager/media/formats/mp2t/ts_writer.cc
+++ b/packager/media/formats/mp2t/ts_writer.cc
@@ -87,9 +87,9 @@ void WritePtsOrDts(uint8_t leading_bits,
   writer->AppendInt(fifth_byte);
 }
 
-bool WritePesToFile(const PesPacket& pes,
-                    ContinuityCounter* continuity_counter,
-                    File* file) {
+bool WritePesToBuffer(const PesPacket& pes,
+                      ContinuityCounter* continuity_counter,
+                      BufferWriter* current_buffer) {
   // The size of the length field.
   const int kAdaptationFieldLengthSize = 1;
   // The size of the flags field.
@@ -153,7 +153,9 @@ bool WritePesToFile(const PesPacket& pes,
                                !kPayloadUnitStartIndicator, pid, !kHasPcr, 0,
                                continuity_counter, &output_writer);
   }
-  return output_writer.WriteToFile(file).ok();
+
+  current_buffer->AppendBuffer(output_writer);
+  return true;
 }
 
 }  // namespace
@@ -163,7 +165,8 @@ TsWriter::TsWriter(std::unique_ptr<ProgramMapTableWriter> pmt_writer)
 
 TsWriter::~TsWriter() {}
 
-bool TsWriter::NewSegment(const std::string& file_name) {
+bool TsWriter::CreateFileAndFlushBuffer(const std::string& file_name) {
+
   if (current_file_) {
     LOG(ERROR) << "File " << current_file_->file_name() << " still open.";
     return false;
@@ -173,6 +176,12 @@ bool TsWriter::NewSegment(const std::string& file_name) {
     LOG(ERROR) << "Failed to open file " << file_name;
     return false;
   }
+  return current_buffer_.get()->WriteToFile(current_file_.get()).ok();
+}
+
+bool TsWriter::NewSegment() {
+ 
+  current_buffer_  = std::unique_ptr<BufferWriter>(new BufferWriter());
 
   BufferWriter psi;
   WritePatToBuffer(kPat, arraysize(kPat), &pat_continuity_counter_, &psi);
@@ -185,12 +194,7 @@ bool TsWriter::NewSegment(const std::string& file_name) {
       return false;
     }
   }
-
-  if (!psi.WriteToFile(current_file_.get()).ok()) {
-    LOG(ERROR) << "Failed to write PSI to file.";
-    return false;
-  }
-
+  current_buffer_.get()->AppendBuffer(psi);
   return true;
 }
 
@@ -203,10 +207,9 @@ bool TsWriter::FinalizeSegment() {
 }
 
 bool TsWriter::AddPesPacket(std::unique_ptr<PesPacket> pes_packet) {
-  DCHECK(current_file_);
-  if (!WritePesToFile(*pes_packet, &elementary_stream_continuity_counter_,
-                      current_file_.get())) {
-    LOG(ERROR) << "Failed to write pes to file.";
+  if (!WritePesToBuffer(*pes_packet, &elementary_stream_continuity_counter_,
+                        current_buffer_.get())) {
+    LOG(ERROR) << "Failed to write pes to buffer.";
     return false;
   }
 
@@ -214,12 +217,11 @@ bool TsWriter::AddPesPacket(std::unique_ptr<PesPacket> pes_packet) {
   return true;
 }
 
-base::Optional<uint64_t> TsWriter::GetFilePosition() {
-  if (!current_file_)
+base::Optional<uint64_t> TsWriter::GetPosition() {
+  if (!current_buffer_.get())
     return base::nullopt;
-  uint64_t position;
-  return current_file_->Tell(&position) ? base::make_optional(position)
-                                        : base::nullopt;
+  uint64_t position = current_buffer_.get()->Size();
+  return position != 0 ? base::make_optional(position) : base::nullopt;
 }
 
 }  // namespace mp2t
diff --git a/packager/media/formats/mp2t/ts_writer.h b/packager/media/formats/mp2t/ts_writer.h
index 43e4c0d09ab..057c517446a 100644
--- a/packager/media/formats/mp2t/ts_writer.h
+++ b/packager/media/formats/mp2t/ts_writer.h
@@ -16,6 +16,7 @@
 #include "packager/file/file.h"
 #include "packager/file/file_closer.h"
 #include "packager/media/formats/mp2t/continuity_counter.h"
+#include "packager/media/base/buffer_writer.h"
 
 namespace shaka {
 namespace media {
@@ -32,27 +33,31 @@ class TsWriter {
   virtual ~TsWriter();
 
   /// This will fail if the current segment is not finalized.
-  /// @param file_name is the output file name.
-  /// @param encrypted must be true if the new segment is encrypted.
   /// @return true on success, false otherwise.
-  virtual bool NewSegment(const std::string& file_name);
+  virtual bool NewSegment();
 
   /// Signals the writer that the rest of the segments are encrypted.
   virtual void SignalEncrypted();
 
-  /// Flush all the pending PesPackets that have not been written to file and
-  /// close the file.
+  /// Flush all the pending PesPackets that have not been added to the buffer.
+  /// Create the file, flush the buffer and close the file.
   /// @return true on success, false otherwise.
   virtual bool FinalizeSegment();
 
-  /// Add PesPacket to the instance. PesPacket might not get written to file
+  /// Add PesPacket to the instance. PesPacket might not be added to the buffer
   /// immediately.
   /// @param pes_packet gets added to the writer.
   /// @return true on success, false otherwise.
   virtual bool AddPesPacket(std::unique_ptr<PesPacket> pes_packet);
 
-  /// @return current file position on success, nullopt otherwise.
-  base::Optional<uint64_t> GetFilePosition();
+  /// @return current buffer position on success, nullopt otherwise.
+  base::Optional<uint64_t> GetPosition();
+
+  /// Creates a file with name @a file_name and flushes 
+  /// current_buffer_ to it.
+  /// @param file_name The path to the file to open.
+  /// @return File creation and buffer flushing succeeded or failed. 
+  virtual bool CreateFileAndFlushBuffer(const std::string& file_name);
 
  private:
   TsWriter(const TsWriter&) = delete;
@@ -67,6 +72,7 @@ class TsWriter {
   std::unique_ptr<ProgramMapTableWriter> pmt_writer_;
 
   std::unique_ptr<File, FileCloser> current_file_;
+  std::unique_ptr<BufferWriter> current_buffer_;
 };
 
 }  // namespace mp2t
diff --git a/packager/media/formats/mp2t/ts_writer_unittest.cc b/packager/media/formats/mp2t/ts_writer_unittest.cc
index 83ceedd0d42..97be645e3f5 100644
--- a/packager/media/formats/mp2t/ts_writer_unittest.cc
+++ b/packager/media/formats/mp2t/ts_writer_unittest.cc
@@ -144,7 +144,9 @@ TEST_F(TsWriterTest, ClearH264Psi) {
   EXPECT_CALL(*mock_pmt_writer, ClearSegmentPmt(_)).WillOnce(WriteOnePmt());
 
   TsWriter ts_writer(std::move(mock_pmt_writer));
-  EXPECT_TRUE(ts_writer.NewSegment(test_file_name_));
+  EXPECT_TRUE(ts_writer.NewSegment());
+  EXPECT_TRUE(ts_writer.CreateFileAndFlushBuffer(test_file_name_));
+
   ASSERT_TRUE(ts_writer.FinalizeSegment());
 
   std::vector<uint8_t> content;
@@ -192,7 +194,8 @@ TEST_F(TsWriterTest, ClearAacPmt) {
   EXPECT_CALL(*mock_pmt_writer, ClearSegmentPmt(_)).WillOnce(WriteOnePmt());
 
   TsWriter ts_writer(std::move(mock_pmt_writer));
-  EXPECT_TRUE(ts_writer.NewSegment(test_file_name_));
+  EXPECT_TRUE(ts_writer.NewSegment());
+  EXPECT_TRUE(ts_writer.CreateFileAndFlushBuffer(test_file_name_));
   ASSERT_TRUE(ts_writer.FinalizeSegment());
 
   std::vector<uint8_t> content;
@@ -213,7 +216,8 @@ TEST_F(TsWriterTest, ClearLeadH264Pmt) {
       .WillOnce(WriteTwoPmts());
 
   TsWriter ts_writer(std::move(mock_pmt_writer));
-  EXPECT_TRUE(ts_writer.NewSegment(test_file_name_));
+  EXPECT_TRUE(ts_writer.NewSegment());
+  EXPECT_TRUE(ts_writer.CreateFileAndFlushBuffer(test_file_name_));
   EXPECT_TRUE(ts_writer.FinalizeSegment());
 
   std::vector<uint8_t> content;
@@ -233,7 +237,7 @@ TEST_F(TsWriterTest, ClearSegmentPmtFailure) {
   EXPECT_CALL(*mock_pmt_writer, ClearSegmentPmt(_)).WillOnce(Return(false));
 
   TsWriter ts_writer(std::move(mock_pmt_writer));
-  EXPECT_FALSE(ts_writer.NewSegment(test_file_name_));
+  EXPECT_FALSE(ts_writer.NewSegment());
 }
 
 // Check the encrypted segments' PMT (after clear lead).
@@ -245,12 +249,14 @@ TEST_F(TsWriterTest, EncryptedSegmentsH264Pmt) {
   EXPECT_CALL(*mock_pmt_writer, EncryptedSegmentPmt(_)).WillOnce(WriteOnePmt());
 
   TsWriter ts_writer(std::move(mock_pmt_writer));
-  EXPECT_TRUE(ts_writer.NewSegment(test_file_name_));
+  EXPECT_TRUE(ts_writer.NewSegment());
+  EXPECT_TRUE(ts_writer.CreateFileAndFlushBuffer(test_file_name_));
   EXPECT_TRUE(ts_writer.FinalizeSegment());
 
   // Overwrite the file but as encrypted segment.
   ts_writer.SignalEncrypted();
-  EXPECT_TRUE(ts_writer.NewSegment(test_file_name_));
+  EXPECT_TRUE(ts_writer.NewSegment());
+  EXPECT_TRUE(ts_writer.CreateFileAndFlushBuffer(test_file_name_));
   EXPECT_TRUE(ts_writer.FinalizeSegment());
 
   std::vector<uint8_t> content;
@@ -270,11 +276,12 @@ TEST_F(TsWriterTest, EncryptedSegmentPmtFailure) {
   EXPECT_CALL(*mock_pmt_writer, EncryptedSegmentPmt(_)).WillOnce(Return(false));
 
   TsWriter ts_writer(std::move(mock_pmt_writer));
-  EXPECT_TRUE(ts_writer.NewSegment(test_file_name_));
+  EXPECT_TRUE(ts_writer.NewSegment());
+  EXPECT_TRUE(ts_writer.CreateFileAndFlushBuffer(test_file_name_));
   EXPECT_TRUE(ts_writer.FinalizeSegment());
 
   ts_writer.SignalEncrypted();
-  EXPECT_FALSE(ts_writer.NewSegment(test_file_name_));
+  EXPECT_FALSE(ts_writer.NewSegment());
 }
 
 // Same as ClearLeadH264Pmt but for AAC.
@@ -285,7 +292,8 @@ TEST_F(TsWriterTest, ClearLeadAacPmt) {
       .WillOnce(WriteTwoPmts());
 
   TsWriter ts_writer(std::move(mock_pmt_writer));
-  EXPECT_TRUE(ts_writer.NewSegment(test_file_name_));
+  EXPECT_TRUE(ts_writer.NewSegment());
+  EXPECT_TRUE(ts_writer.CreateFileAndFlushBuffer(test_file_name_));
   ASSERT_TRUE(ts_writer.FinalizeSegment());
 
   std::vector<uint8_t> content;
@@ -308,12 +316,14 @@ TEST_F(TsWriterTest, EncryptedSegmentsAacPmt) {
   EXPECT_CALL(*mock_pmt_writer, EncryptedSegmentPmt(_)).WillOnce(WriteOnePmt());
 
   TsWriter ts_writer(std::move(mock_pmt_writer));
-  EXPECT_TRUE(ts_writer.NewSegment(test_file_name_));
+  EXPECT_TRUE(ts_writer.NewSegment());
+  EXPECT_TRUE(ts_writer.CreateFileAndFlushBuffer(test_file_name_));
   EXPECT_TRUE(ts_writer.FinalizeSegment());
 
   // Overwrite the file but as encrypted segment.
   ts_writer.SignalEncrypted();
-  EXPECT_TRUE(ts_writer.NewSegment(test_file_name_));
+  EXPECT_TRUE(ts_writer.NewSegment());
+  EXPECT_TRUE(ts_writer.CreateFileAndFlushBuffer(test_file_name_));
   EXPECT_TRUE(ts_writer.FinalizeSegment());
 
   std::vector<uint8_t> content;
@@ -329,7 +339,7 @@ TEST_F(TsWriterTest, EncryptedSegmentsAacPmt) {
 TEST_F(TsWriterTest, AddPesPacket) {
   TsWriter ts_writer(std::unique_ptr<ProgramMapTableWriter>(
       new VideoProgramMapTableWriter(kCodecForTesting)));
-  EXPECT_TRUE(ts_writer.NewSegment(test_file_name_));
+  EXPECT_TRUE(ts_writer.NewSegment());
 
   std::unique_ptr<PesPacket> pes(new PesPacket());
   pes->set_stream_id(0xE0);
@@ -341,6 +351,7 @@ TEST_F(TsWriterTest, AddPesPacket) {
   pes->mutable_data()->assign(kAnyData, kAnyData + arraysize(kAnyData));
 
   EXPECT_TRUE(ts_writer.AddPesPacket(std::move(pes)));
+  EXPECT_TRUE(ts_writer.CreateFileAndFlushBuffer(test_file_name_));
   ASSERT_TRUE(ts_writer.FinalizeSegment());
 
   std::vector<uint8_t> content;
@@ -391,7 +402,7 @@ TEST_F(TsWriterTest, AddPesPacket) {
 TEST_F(TsWriterTest, BigPesPacket) {
   TsWriter ts_writer(std::unique_ptr<ProgramMapTableWriter>(
       new VideoProgramMapTableWriter(kCodecForTesting)));
-  EXPECT_TRUE(ts_writer.NewSegment(test_file_name_));
+  EXPECT_TRUE(ts_writer.NewSegment());
 
   std::unique_ptr<PesPacket> pes(new PesPacket());
   pes->set_pts(0);
@@ -401,6 +412,7 @@ TEST_F(TsWriterTest, BigPesPacket) {
   *pes->mutable_data() = big_data;
 
   EXPECT_TRUE(ts_writer.AddPesPacket(std::move(pes)));
+  EXPECT_TRUE(ts_writer.CreateFileAndFlushBuffer(test_file_name_));
   ASSERT_TRUE(ts_writer.FinalizeSegment());
 
   std::vector<uint8_t> content;
@@ -424,7 +436,7 @@ TEST_F(TsWriterTest, BigPesPacket) {
 TEST_F(TsWriterTest, PesPtsZeroNoDts) {
   TsWriter ts_writer(std::unique_ptr<ProgramMapTableWriter>(
       new VideoProgramMapTableWriter(kCodecForTesting)));
-  EXPECT_TRUE(ts_writer.NewSegment(test_file_name_));
+  EXPECT_TRUE(ts_writer.NewSegment());
 
   std::unique_ptr<PesPacket> pes(new PesPacket());
   pes->set_stream_id(0xE0);
@@ -435,6 +447,7 @@ TEST_F(TsWriterTest, PesPtsZeroNoDts) {
   pes->mutable_data()->assign(kAnyData, kAnyData + arraysize(kAnyData));
 
   EXPECT_TRUE(ts_writer.AddPesPacket(std::move(pes)));
+  EXPECT_TRUE(ts_writer.CreateFileAndFlushBuffer(test_file_name_));
   ASSERT_TRUE(ts_writer.FinalizeSegment());
 
   std::vector<uint8_t> content;
@@ -481,7 +494,7 @@ TEST_F(TsWriterTest, PesPtsZeroNoDts) {
 TEST_F(TsWriterTest, TsPacketPayload183Bytes) {
   TsWriter ts_writer(std::unique_ptr<ProgramMapTableWriter>(
       new VideoProgramMapTableWriter(kCodecForTesting)));
-  EXPECT_TRUE(ts_writer.NewSegment(test_file_name_));
+  EXPECT_TRUE(ts_writer.NewSegment());
 
   std::unique_ptr<PesPacket> pes(new PesPacket());
   pes->set_stream_id(0xE0);
@@ -496,6 +509,7 @@ TEST_F(TsWriterTest, TsPacketPayload183Bytes) {
   *pes->mutable_data() = pes_payload;
 
   EXPECT_TRUE(ts_writer.AddPesPacket(std::move(pes)));
+  EXPECT_TRUE(ts_writer.CreateFileAndFlushBuffer(test_file_name_));
   ASSERT_TRUE(ts_writer.FinalizeSegment());
 
   const uint8_t kExpectedOutputPrefix[] = {
diff --git a/packager/media/formats/mp4/mp4_muxer.cc b/packager/media/formats/mp4/mp4_muxer.cc
index 336f13a0399..41c5eb7d196 100644
--- a/packager/media/formats/mp4/mp4_muxer.cc
+++ b/packager/media/formats/mp4/mp4_muxer.cc
@@ -34,9 +34,7 @@ namespace {
 
 // Sets the range start and end value from offset and size.
 // |start| and |end| are for byte-range-spec specified in RFC2616.
-void SetStartAndEndFromOffsetAndSize(size_t offset,
-                                     size_t size,
-                                     Range* range) {
+void SetStartAndEndFromOffsetAndSize(size_t offset, size_t size, Range* range) {
   DCHECK(range);
   range->start = static_cast<uint32_t>(offset);
   // Note that ranges are inclusive. So we need - 1.
@@ -194,7 +192,7 @@ Status MP4Muxer::FinalizeSegment(size_t stream_id,
   DCHECK(segmenter_);
   VLOG(3) << "Finalizing " << (segment_info.is_subsegment ? "sub" : "")
           << "segment " << segment_info.start_timestamp << " duration "
-          << segment_info.duration;
+          << segment_info.duration << " index " << segment_info.segment_index;
   return segmenter_->FinalizeSegment(stream_id, segment_info);
 }
 
@@ -456,7 +454,7 @@ bool MP4Muxer::GenerateAudioTrak(const AudioStreamInfo* audio_info,
   AudioSampleEntry audio;
   audio.format =
       CodecToFourCC(audio_info->codec(), H26xStreamFormat::kUnSpecified);
-  switch(audio_info->codec()){
+  switch (audio_info->codec()) {
     case kCodecAAC: {
       audio.esds.es_descriptor.set_esid(track_id);
       DecoderConfigDescriptor* decoder_config =
diff --git a/packager/media/formats/mp4/multi_segment_segmenter.cc b/packager/media/formats/mp4/multi_segment_segmenter.cc
index cf12e4c1705..cae3f74187d 100644
--- a/packager/media/formats/mp4/multi_segment_segmenter.cc
+++ b/packager/media/formats/mp4/multi_segment_segmenter.cc
@@ -28,8 +28,7 @@ MultiSegmentSegmenter::MultiSegmentSegmenter(const MuxerOptions& options,
                                              std::unique_ptr<FileType> ftyp,
                                              std::unique_ptr<Movie> moov)
     : Segmenter(options, std::move(ftyp), std::move(moov)),
-      styp_(new SegmentType),
-      num_segments_(0) {
+      styp_(new SegmentType) {
   // Use the same brands for styp as ftyp.
   styp_->major_brand = Segmenter::ftyp()->major_brand;
   styp_->compatible_brands = Segmenter::ftyp()->compatible_brands;
@@ -67,8 +66,8 @@ Status MultiSegmentSegmenter::DoFinalize() {
   return Status::OK;
 }
 
-Status MultiSegmentSegmenter::DoFinalizeSegment() {
-  return WriteSegment();
+Status MultiSegmentSegmenter::DoFinalizeSegment(uint64_t segment_index) {
+  return WriteSegment(segment_index);
 }
 
 Status MultiSegmentSegmenter::WriteInitSegment() {
@@ -87,7 +86,7 @@ Status MultiSegmentSegmenter::WriteInitSegment() {
   return buffer->WriteToFile(file.get());
 }
 
-Status MultiSegmentSegmenter::WriteSegment() {
+Status MultiSegmentSegmenter::WriteSegment(uint64_t segment_index) {
   DCHECK(sidx());
   DCHECK(fragment_buffer());
   DCHECK(styp_);
@@ -112,7 +111,7 @@ Status MultiSegmentSegmenter::WriteSegment() {
   } else {
     file_name = GetSegmentName(options().segment_template,
                                sidx()->earliest_presentation_time,
-                               num_segments_++, options().bandwidth);
+                               segment_index - 1, options().bandwidth);
     file.reset(File::Open(file_name.c_str(), "w"));
     if (!file) {
       return Status(error::FILE_FAILURE,
@@ -157,9 +156,9 @@ Status MultiSegmentSegmenter::WriteSegment() {
   UpdateProgress(segment_duration);
   if (muxer_listener()) {
     muxer_listener()->OnSampleDurationReady(sample_duration());
-    muxer_listener()->OnNewSegment(file_name,
-                                   sidx()->earliest_presentation_time,
-                                   segment_duration, segment_size);
+    muxer_listener()->OnNewSegment(
+        file_name, sidx()->earliest_presentation_time, segment_duration,
+        segment_size, segment_index);
   }
 
   return Status::OK;
diff --git a/packager/media/formats/mp4/multi_segment_segmenter.h b/packager/media/formats/mp4/multi_segment_segmenter.h
index b1c524da216..8ef7258e842 100644
--- a/packager/media/formats/mp4/multi_segment_segmenter.h
+++ b/packager/media/formats/mp4/multi_segment_segmenter.h
@@ -33,19 +33,17 @@ class MultiSegmentSegmenter : public Segmenter {
   bool GetIndexRange(size_t* offset, size_t* size) override;
   std::vector<Range> GetSegmentRanges() override;
   /// @}
-
  private:
   // Segmenter implementation overrides.
   Status DoInitialize() override;
   Status DoFinalize() override;
-  Status DoFinalizeSegment() override;
+  Status DoFinalizeSegment(uint64_t segment_index) override;
 
   // Write segment to file.
   Status WriteInitSegment();
-  Status WriteSegment();
+  Status WriteSegment(uint64_t segment_index);
 
   std::unique_ptr<SegmentType> styp_;
-  uint32_t num_segments_;
 
   DISALLOW_COPY_AND_ASSIGN(MultiSegmentSegmenter);
 };
diff --git a/packager/media/formats/mp4/segmenter.cc b/packager/media/formats/mp4/segmenter.cc
index cce500dea49..cf9097072c6 100644
--- a/packager/media/formats/mp4/segmenter.cc
+++ b/packager/media/formats/mp4/segmenter.cc
@@ -225,7 +225,7 @@ Status Segmenter::FinalizeSegment(size_t stream_id,
   for (std::unique_ptr<Fragmenter>& fragmenter : fragmenters_)
     fragmenter->ClearFragmentFinalized();
   if (!segment_info.is_subsegment) {
-    Status status = DoFinalizeSegment();
+    Status status = DoFinalizeSegment(segment_info.segment_index);
     // Reset segment information to initial state.
     sidx_->references.clear();
     key_frame_infos_.clear();
@@ -250,8 +250,10 @@ double Segmenter::GetDuration() const {
 void Segmenter::UpdateProgress(uint64_t progress) {
   accumulated_progress_ += progress;
 
-  if (!progress_listener_) return;
-  if (progress_target_ == 0) return;
+  if (!progress_listener_)
+    return;
+  if (progress_target_ == 0)
+    return;
   // It might happen that accumulated progress exceeds progress_target due to
   // computation errors, e.g. rounding error. Cap it so it never reports > 100%
   // progress.
@@ -264,7 +266,8 @@ void Segmenter::UpdateProgress(uint64_t progress) {
 }
 
 void Segmenter::SetComplete() {
-  if (!progress_listener_) return;
+  if (!progress_listener_)
+    return;
   progress_listener_->OnProgress(1.0);
 }
 
diff --git a/packager/media/formats/mp4/segmenter.h b/packager/media/formats/mp4/segmenter.h
index 724c12ef6fc..35a2bfa101c 100644
--- a/packager/media/formats/mp4/segmenter.h
+++ b/packager/media/formats/mp4/segmenter.h
@@ -124,7 +124,7 @@ class Segmenter {
  private:
   virtual Status DoInitialize() = 0;
   virtual Status DoFinalize() = 0;
-  virtual Status DoFinalizeSegment() = 0;
+  virtual Status DoFinalizeSegment(uint64_t segment_index) = 0;
 
   uint32_t GetReferenceStreamId();
 
diff --git a/packager/media/formats/mp4/single_segment_segmenter.cc b/packager/media/formats/mp4/single_segment_segmenter.cc
index 7c54d9235a4..7298af95316 100644
--- a/packager/media/formats/mp4/single_segment_segmenter.cc
+++ b/packager/media/formats/mp4/single_segment_segmenter.cc
@@ -51,9 +51,8 @@ bool SingleSegmentSegmenter::GetIndexRange(size_t* offset, size_t* size) {
 
 std::vector<Range> SingleSegmentSegmenter::GetSegmentRanges() {
   std::vector<Range> ranges;
-  uint64_t next_offset =
-      ftyp()->ComputeSize() + moov()->ComputeSize() + vod_sidx_->ComputeSize() +
-      vod_sidx_->first_offset;
+  uint64_t next_offset = ftyp()->ComputeSize() + moov()->ComputeSize() +
+                         vod_sidx_->ComputeSize() + vod_sidx_->first_offset;
   for (const SegmentReference& segment_reference : vod_sidx_->references) {
     Range r;
     r.start = next_offset;
@@ -77,10 +76,9 @@ Status SingleSegmentSegmenter::DoInitialize() {
   if (!TempFilePath(options().temp_dir, &temp_file_name_))
     return Status(error::FILE_FAILURE, "Unable to create temporary file.");
   temp_file_.reset(File::Open(temp_file_name_.c_str(), "w"));
-  return temp_file_
-             ? Status::OK
-             : Status(error::FILE_FAILURE,
-                      "Cannot open file to write " + temp_file_name_);
+  return temp_file_ ? Status::OK
+                    : Status(error::FILE_FAILURE,
+                             "Cannot open file to write " + temp_file_name_);
 }
 
 Status SingleSegmentSegmenter::DoFinalize() {
@@ -159,7 +157,7 @@ Status SingleSegmentSegmenter::DoFinalize() {
   return Status::OK;
 }
 
-Status SingleSegmentSegmenter::DoFinalizeSegment() {
+Status SingleSegmentSegmenter::DoFinalizeSegment(uint64_t segment_index) {
   DCHECK(sidx());
   DCHECK(fragment_buffer());
   // sidx() contains pre-generated segment references with one reference per
@@ -212,14 +210,15 @@ Status SingleSegmentSegmenter::DoFinalizeSegment() {
   // Append fragment buffer to temp file.
   size_t segment_size = fragment_buffer()->Size();
   Status status = fragment_buffer()->WriteToFile(temp_file_.get());
-  if (!status.ok()) return status;
+  if (!status.ok())
+    return status;
 
   UpdateProgress(vod_ref.subsegment_duration);
   if (muxer_listener()) {
     muxer_listener()->OnSampleDurationReady(sample_duration());
-    muxer_listener()->OnNewSegment(options().output_file_name,
-                                   vod_ref.earliest_presentation_time,
-                                   vod_ref.subsegment_duration, segment_size);
+    muxer_listener()->OnNewSegment(
+        options().output_file_name, vod_ref.earliest_presentation_time,
+        vod_ref.subsegment_duration, segment_size, segment_index);
   }
   return Status::OK;
 }
diff --git a/packager/media/formats/mp4/single_segment_segmenter.h b/packager/media/formats/mp4/single_segment_segmenter.h
index 4659f354359..6abe8bd1e42 100644
--- a/packager/media/formats/mp4/single_segment_segmenter.h
+++ b/packager/media/formats/mp4/single_segment_segmenter.h
@@ -44,7 +44,7 @@ class SingleSegmentSegmenter : public Segmenter {
   // Segmenter implementation overrides.
   Status DoInitialize() override;
   Status DoFinalize() override;
-  Status DoFinalizeSegment() override;
+  Status DoFinalizeSegment(uint64_t segment_index) override;
 
   std::unique_ptr<SegmentIndex> vod_sidx_;
   std::string temp_file_name_;
diff --git a/packager/media/formats/packed_audio/packed_audio_writer.cc b/packager/media/formats/packed_audio/packed_audio_writer.cc
index 29f796c56e0..10229c84209 100644
--- a/packager/media/formats/packed_audio/packed_audio_writer.cc
+++ b/packager/media/formats/packed_audio/packed_audio_writer.cc
@@ -79,8 +79,7 @@ Status PackedAudioWriter::FinalizeSegment(size_t stream_id,
       options().segment_template.empty()
           ? options().output_file_name
           : GetSegmentName(options().segment_template, segment_timestamp,
-                           segment_number_++, options().bandwidth);
-
+                           segment_info.segment_index - 1, options().bandwidth);
   // Save |segment_size| as it will be cleared after writing.
   const size_t segment_size = segmenter_->segment_buffer()->Size();
 
@@ -90,7 +89,8 @@ Status PackedAudioWriter::FinalizeSegment(size_t stream_id,
   if (muxer_listener()) {
     muxer_listener()->OnNewSegment(
         segment_path, segment_timestamp + transport_stream_timestamp_offset_,
-        segment_info.duration * segmenter_->TimescaleScale(), segment_size);
+        segment_info.duration * segmenter_->TimescaleScale(), segment_size,
+        segment_info.segment_index);
   }
   return Status::OK;
 }
diff --git a/packager/media/formats/packed_audio/packed_audio_writer_unittest.cc b/packager/media/formats/packed_audio/packed_audio_writer_unittest.cc
index 18c68fe5150..2897f642b63 100644
--- a/packager/media/formats/packed_audio/packed_audio_writer_unittest.cc
+++ b/packager/media/formats/packed_audio/packed_audio_writer_unittest.cc
@@ -42,8 +42,8 @@ const uint32_t kTimescale = 9000;
 const char kOutputFile[] = "memory://test.aac";
 // For multi-segment mode.
 const char kSegmentTemplate[] = "memory://test_$Number$.aac";
-const char kSegment1Name[] = "memory://test_1.aac";
-const char kSegment2Name[] = "memory://test_2.aac";
+const char kSegment124Name[] = "memory://test_124.aac";
+const char kSegment125Name[] = "memory://test_125.aac";
 
 class MockPackedAudioSegmenter : public PackedAudioSegmenter {
  public:
@@ -124,7 +124,7 @@ TEST_P(PackedAudioWriterTest, SubsegmentIgnored) {
   auto subsegment_stream_data = StreamData::FromSegmentInfo(
       kStreamIndex, GetSegmentInfo(kTimestamp, kDuration, kSubsegment));
 
-  EXPECT_CALL(*mock_muxer_listener_ptr_, OnNewSegment(_, _, _, _)).Times(0);
+  EXPECT_CALL(*mock_muxer_listener_ptr_, OnNewSegment(_, _, _, _, _)).Times(0);
   EXPECT_CALL(*mock_segmenter_ptr_, FinalizeSegment()).Times(0);
   ASSERT_OK(Input(kInput)->Dispatch(std::move(subsegment_stream_data)));
 }
@@ -145,9 +145,9 @@ TEST_P(PackedAudioWriterTest, OneSegment) {
 
   EXPECT_CALL(
       *mock_muxer_listener_ptr_,
-      OnNewSegment(is_single_segment_mode_ ? kOutputFile : kSegment1Name,
+      OnNewSegment(is_single_segment_mode_ ? kOutputFile : kSegment124Name,
                    kTimestamp * kMockTimescaleScale,
-                   kDuration * kMockTimescaleScale, kSegmentDataSize));
+                   kDuration * kMockTimescaleScale, kSegmentDataSize, 124));
 
   EXPECT_CALL(*mock_segmenter_ptr_, TimescaleScale())
       .WillRepeatedly(Return(kMockTimescaleScale));
@@ -178,7 +178,7 @@ TEST_P(PackedAudioWriterTest, OneSegment) {
   }
   ASSERT_OK(Input(kInput)->FlushDownstream(kStreamIndex));
 
-  ASSERT_FILE_STREQ(is_single_segment_mode_ ? kOutputFile : kSegment1Name,
+  ASSERT_FILE_STREQ(is_single_segment_mode_ ? kOutputFile : kSegment124Name,
                     kMockSegmentData);
 }
 
@@ -203,15 +203,15 @@ TEST_P(PackedAudioWriterTest, TwoSegments) {
 
   EXPECT_CALL(
       *mock_muxer_listener_ptr_,
-      OnNewSegment(is_single_segment_mode_ ? kOutputFile : kSegment1Name,
+      OnNewSegment(is_single_segment_mode_ ? kOutputFile : kSegment124Name,
                    kTimestamp * kMockTimescaleScale,
                    kDuration * kMockTimescaleScale,
-                   sizeof(kMockSegment1Data) - 1));
+                   sizeof(kMockSegment1Data) - 1, 124));
   EXPECT_CALL(
       *mock_muxer_listener_ptr_,
-      OnNewSegment(is_single_segment_mode_ ? kOutputFile : kSegment2Name,
+      OnNewSegment(is_single_segment_mode_ ? kOutputFile : kSegment125Name,
                    (kTimestamp + kDuration) * kMockTimescaleScale,
-                   kDuration * kMockTimescaleScale, kSegment2DataSize));
+                   kDuration * kMockTimescaleScale, kSegment2DataSize, 125));
 
   EXPECT_CALL(*mock_segmenter_ptr_, TimescaleScale())
       .WillRepeatedly(Return(kMockTimescaleScale));
@@ -251,8 +251,8 @@ TEST_P(PackedAudioWriterTest, TwoSegments) {
     ASSERT_FILE_STREQ(kOutputFile, std::string(kMockSegment1Data) +
                                        std::string(kMockSegment2Data));
   } else {
-    ASSERT_FILE_STREQ(kSegment1Name, kMockSegment1Data);
-    ASSERT_FILE_STREQ(kSegment2Name, kMockSegment2Data);
+    ASSERT_FILE_STREQ(kSegment124Name, kMockSegment1Data);
+    ASSERT_FILE_STREQ(kSegment125Name, kMockSegment2Data);
   }
 }
 
diff --git a/packager/media/formats/webm/encrypted_segmenter_unittest.cc b/packager/media/formats/webm/encrypted_segmenter_unittest.cc
index 3054e193f45..d9ccd0fc3e8 100644
--- a/packager/media/formats/webm/encrypted_segmenter_unittest.cc
+++ b/packager/media/formats/webm/encrypted_segmenter_unittest.cc
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "packager/media/formats/webm/two_pass_single_segment_segmenter.h"
-
 #include <gtest/gtest.h>
+
 #include <memory>
+
 #include "packager/media/formats/webm/segmenter_test_base.h"
+#include "packager/media/formats/webm/two_pass_single_segment_segmenter.h"
 
 namespace shaka {
 namespace media {
@@ -225,7 +226,7 @@ TEST_F(EncryptedSegmenterTest, BasicSupport) {
   // segment encrypted.
   for (int i = 0; i < 5; i++) {
     if (i == 3) {
-      ASSERT_OK(segmenter_->FinalizeSegment(0, 3 * kDuration, !kSubsegment));
+      ASSERT_OK(segmenter_->FinalizeSegment(0, 3 * kDuration, !kSubsegment, 3));
     }
     std::shared_ptr<MediaSample> sample =
         CreateSample(kKeyFrame, kDuration, kNoSideData);
@@ -239,8 +240,8 @@ TEST_F(EncryptedSegmenterTest, BasicSupport) {
     }
     ASSERT_OK(segmenter_->AddSample(*sample));
   }
-  ASSERT_OK(
-      segmenter_->FinalizeSegment(3 * kDuration, 2 * kDuration, !kSubsegment));
+  ASSERT_OK(segmenter_->FinalizeSegment(3 * kDuration, 2 * kDuration,
+                                        !kSubsegment, 2));
   ASSERT_OK(segmenter_->Finalize());
 
   ASSERT_FILE_ENDS_WITH(OutputFileName().c_str(), kBasicSupportData);
diff --git a/packager/media/formats/webm/mkv_writer.cc b/packager/media/formats/webm/mkv_writer.cc
index 0d919d0ac62..0953772c35d 100644
--- a/packager/media/formats/webm/mkv_writer.cc
+++ b/packager/media/formats/webm/mkv_writer.cc
@@ -13,8 +13,17 @@ MkvWriter::MkvWriter() : position_(0) {}
 
 MkvWriter::~MkvWriter() {}
 
+Status MkvWriter::OpenBuffer() {
+  DCHECK(!file_);
+  current_buffer_  = std::unique_ptr<BufferWriter>(new BufferWriter());
+  seekable_ = false;
+  position_ = 0;
+  return Status::OK;
+}
+
 Status MkvWriter::Open(const std::string& name) {
   DCHECK(!file_);
+  DCHECK(!current_buffer_);
   file_.reset(File::Open(name.c_str(), "w"));
   if (!file_)
     return Status(error::FILE_FAILURE, "Unable to open file for writing.");
@@ -26,6 +35,21 @@ Status MkvWriter::Open(const std::string& name) {
   return Status::OK;
 }
 
+bool MkvWriter::CreateFileAndFlushBuffer(const std::string& file_name) {
+
+  if (file_) {
+    LOG(ERROR) << "File " << file_->file_name() << " is open.";
+    return false;
+  }
+  file_.reset(File::Open(file_name.c_str(), "w"));
+  if (!file_) {
+    LOG(ERROR) << "Failed to open file " << file_name;
+    return false;
+  }
+  seekable_ = file_->Seek(0);
+  return current_buffer_.get()->WriteToFile(file_.get()).ok();
+}
+
 Status MkvWriter::Close() {
   const std::string file_name = file_->file_name();
   if (!file_.release()->Close()) {
@@ -38,21 +62,28 @@ Status MkvWriter::Close() {
 }
 
 mkvmuxer::int32 MkvWriter::Write(const void* buf, mkvmuxer::uint32 len) {
-  DCHECK(file_);
-
-  const char* data = reinterpret_cast<const char*>(buf);
-  int64_t total_bytes_written = 0;
-  while (total_bytes_written < len) {
-    const int64_t written =
-        file_->Write(data + total_bytes_written, len - total_bytes_written);
-    if (written < 0)
-      return written;
-
-    total_bytes_written += written;
+  if (seekable_) {
+    DCHECK(file_);
+
+    const char* data = reinterpret_cast<const char*>(buf);
+    int64_t total_bytes_written = 0;
+    while (total_bytes_written < len) {
+      const int64_t written =
+          file_->Write(data + total_bytes_written, len - total_bytes_written);
+      if (written < 0)
+        return written;
+
+      total_bytes_written += written;
+    }
+
+    DCHECK_EQ(total_bytes_written, len);
+    position_ += len;
+  } else {
+     // Write to buffer if file is not present.
+     const uint8_t* data = reinterpret_cast<const uint8_t*>(buf);
+     current_buffer_.get()->AppendArray(data, len);
+     position_ = current_buffer_.get()->Size();
   }
-
-  DCHECK_EQ(total_bytes_written, len);
-  position_ += len;
   return 0;
 }
 
@@ -61,6 +92,7 @@ int64_t MkvWriter::WriteFromFile(File* source) {
 }
 
 int64_t MkvWriter::WriteFromFile(File* source, int64_t max_copy) {
+  DCHECK(seekable_);
   DCHECK(file_);
 
   const int64_t size = File::CopyFile(source, file_.get(), max_copy);
diff --git a/packager/media/formats/webm/mkv_writer.h b/packager/media/formats/webm/mkv_writer.h
index cfed034a83a..9c2280385db 100644
--- a/packager/media/formats/webm/mkv_writer.h
+++ b/packager/media/formats/webm/mkv_writer.h
@@ -13,6 +13,7 @@
 #include "packager/file/file_closer.h"
 #include "packager/status.h"
 #include "packager/third_party/libwebm/src/mkvmuxer.hpp"
+#include "packager/media/base/buffer_writer.h"
 
 namespace shaka {
 namespace media {
@@ -28,6 +29,11 @@ class MkvWriter : public mkvmuxer::IMkvWriter {
   /// @param name The path to the file to open.
   /// @return Whether the operation succeeded.
   Status Open(const std::string& name);
+
+  /// Initialize a buffer.
+  /// @return Whether the operation succeeded.
+  Status OpenBuffer();
+  
   /// Closes the file.  MUST call Open before calling any other methods.
   Status Close();
 
@@ -58,10 +64,17 @@ class MkvWriter : public mkvmuxer::IMkvWriter {
   /// @return The number of bytes written; or < 0 on error.
   int64_t WriteFromFile(File* source, int64_t max_copy);
 
+  /// Creates a file with name @a file_name and flushes 
+  /// current_buffer_ to it.
+  /// @param name The path to the file to open.
+  /// @return File creation and buffer flushing succeeded or failed. 
+  virtual bool CreateFileAndFlushBuffer(const std::string& file_name);
+  
   File* file() { return file_.get(); }
-
+ 
  private:
   std::unique_ptr<File, FileCloser> file_;
+  std::unique_ptr<BufferWriter> current_buffer_;
   // Keep track of the position and whether we can seek.
   mkvmuxer::int64 position_;
   bool seekable_;
diff --git a/packager/media/formats/webm/multi_segment_segmenter.cc b/packager/media/formats/webm/multi_segment_segmenter.cc
index 4a2f24bae21..fe004365310 100644
--- a/packager/media/formats/webm/multi_segment_segmenter.cc
+++ b/packager/media/formats/webm/multi_segment_segmenter.cc
@@ -24,15 +24,27 @@ MultiSegmentSegmenter::~MultiSegmentSegmenter() {}
 
 Status MultiSegmentSegmenter::FinalizeSegment(uint64_t start_timestamp,
                                               uint64_t duration_timestamp,
-                                              bool is_subsegment) {
+                                              bool is_subsegment,
+                                              uint64_t segment_index) {
   CHECK(cluster());
   RETURN_IF_ERROR(Segmenter::FinalizeSegment(
-      start_timestamp, duration_timestamp, is_subsegment));
+      start_timestamp, duration_timestamp, is_subsegment, segment_index));
+  if (!is_subsegment) {
+    std::string segment_name =
+        GetSegmentName(options().segment_template, start_timestamp,
+                       segment_index - 1, options().bandwidth);
+
+    if (!writer_->CreateFileAndFlushBuffer(segment_name)) {
+      LOG(ERROR) << "Failed creating file for webm segment.";
+    }
+  }
+
   if (!cluster()->Finalize())
     return Status(error::FILE_FAILURE, "Error finalizing segment.");
 
   if (!is_subsegment) {
     const std::string segment_name = writer_->file()->file_name();
+
     // Close the file, which also does flushing, to make sure the file is
     // written before manifest is updated.
     RETURN_IF_ERROR(writer_->Close());
@@ -40,7 +52,7 @@ Status MultiSegmentSegmenter::FinalizeSegment(uint64_t start_timestamp,
     if (muxer_listener()) {
       const uint64_t size = cluster()->Size();
       muxer_listener()->OnNewSegment(segment_name, start_timestamp,
-                                     duration_timestamp, size);
+                                     duration_timestamp, size, segment_index);
     }
     VLOG(1) << "WEBM file '" << writer_->file()->file_name() << "' finalized.";
   }
@@ -77,12 +89,9 @@ Status MultiSegmentSegmenter::DoFinalize() {
 Status MultiSegmentSegmenter::NewSegment(uint64_t start_timestamp,
                                          bool is_subsegment) {
   if (!is_subsegment) {
-    // Create a new file for the new segment.
-    std::string segment_name =
-        GetSegmentName(options().segment_template, start_timestamp,
-                       num_segment_, options().bandwidth);
     writer_.reset(new MkvWriter);
-    Status status = writer_->Open(segment_name);
+    // Initialize the buffer for a new segment.
+    Status status = writer_->OpenBuffer();
     if (!status.ok())
       return status;
     num_segment_++;
diff --git a/packager/media/formats/webm/multi_segment_segmenter.h b/packager/media/formats/webm/multi_segment_segmenter.h
index 4d788ca7937..5f86c625f0b 100644
--- a/packager/media/formats/webm/multi_segment_segmenter.h
+++ b/packager/media/formats/webm/multi_segment_segmenter.h
@@ -30,7 +30,8 @@ class MultiSegmentSegmenter : public Segmenter {
   /// @{
   Status FinalizeSegment(uint64_t start_timestamp,
                          uint64_t duration_timestamp,
-                         bool is_subsegment) override;
+                         bool is_subsegment,
+                         uint64_t segment_index) override;
   bool GetInitRangeStartAndEnd(uint64_t* start, uint64_t* end) override;
   bool GetIndexRangeStartAndEnd(uint64_t* start, uint64_t* end) override;
   std::vector<Range> GetSegmentRanges() override;
diff --git a/packager/media/formats/webm/multi_segment_segmenter_unittest.cc b/packager/media/formats/webm/multi_segment_segmenter_unittest.cc
index 5513f00c51a..42d37921ff3 100644
--- a/packager/media/formats/webm/multi_segment_segmenter_unittest.cc
+++ b/packager/media/formats/webm/multi_segment_segmenter_unittest.cc
@@ -5,7 +5,9 @@
 #include "packager/media/formats/webm/multi_segment_segmenter.h"
 
 #include <gtest/gtest.h>
+
 #include <memory>
+
 #include "packager/media/base/muxer_util.h"
 #include "packager/media/formats/webm/segmenter_test_base.h"
 
@@ -69,6 +71,7 @@ const uint8_t kBasicSupportDataInit[] = {
           // DisplayHeight: 100
           0x54, 0xba, 0x81, 0x64
 };
+
 const uint8_t kBasicSupportDataSegment[] = {
   // ID: Cluster, Payload Size: 64
   0x1f, 0x43, 0xb6, 0x75, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
@@ -126,15 +129,15 @@ TEST_F(MultiSegmentSegmenterTest, BasicSupport) {
         CreateSample(kKeyFrame, kDuration, kNoSideData);
     ASSERT_OK(segmenter_->AddSample(*sample));
   }
-  ASSERT_OK(segmenter_->FinalizeSegment(0, 8 * kDuration, !kSubsegment));
+  ASSERT_OK(segmenter_->FinalizeSegment(0, 8 * kDuration, !kSubsegment, 8));
   ASSERT_OK(segmenter_->Finalize());
 
   // Verify the resulting data.
   ASSERT_FILE_ENDS_WITH(OutputFileName().c_str(), kBasicSupportDataInit);
-  ASSERT_FILE_EQ(TemplateFileName(0).c_str(), kBasicSupportDataSegment);
+  ASSERT_FILE_EQ(TemplateFileName(7).c_str(), kBasicSupportDataSegment);
 
   // There is no second segment.
-  EXPECT_FALSE(File::Open(TemplateFileName(1).c_str(), "r"));
+  EXPECT_FALSE(File::Open(TemplateFileName(8).c_str(), "r"));
 }
 
 TEST_F(MultiSegmentSegmenterTest, SplitsFilesOnSegment) {
@@ -145,27 +148,27 @@ TEST_F(MultiSegmentSegmenterTest, SplitsFilesOnSegment) {
   // Write the samples to the Segmenter.
   for (int i = 0; i < 8; i++) {
     if (i == 5) {
-      ASSERT_OK(segmenter_->FinalizeSegment(0, 5 * kDuration, !kSubsegment));
+      ASSERT_OK(segmenter_->FinalizeSegment(0, 5 * kDuration, !kSubsegment, 5));
     }
     std::shared_ptr<MediaSample> sample =
         CreateSample(kKeyFrame, kDuration, kNoSideData);
     ASSERT_OK(segmenter_->AddSample(*sample));
   }
-  ASSERT_OK(
-      segmenter_->FinalizeSegment(5 * kDuration, 8 * kDuration, !kSubsegment));
+  ASSERT_OK(segmenter_->FinalizeSegment(5 * kDuration, 8 * kDuration,
+                                        !kSubsegment, 8));
   ASSERT_OK(segmenter_->Finalize());
 
   // Verify the resulting data.
   ClusterParser parser;
-  ASSERT_NO_FATAL_FAILURE(parser.PopulateFromCluster(TemplateFileName(0)));
+  ASSERT_NO_FATAL_FAILURE(parser.PopulateFromCluster(TemplateFileName(4)));
   ASSERT_EQ(1u, parser.cluster_count());
   EXPECT_EQ(5u, parser.GetFrameCountForCluster(0));
 
-  ASSERT_NO_FATAL_FAILURE(parser.PopulateFromCluster(TemplateFileName(1)));
+  ASSERT_NO_FATAL_FAILURE(parser.PopulateFromCluster(TemplateFileName(7)));
   ASSERT_EQ(1u, parser.cluster_count());
   EXPECT_EQ(3u, parser.GetFrameCountForCluster(0));
 
-  EXPECT_FALSE(File::Open(TemplateFileName(2).c_str(), "r"));
+  EXPECT_FALSE(File::Open(TemplateFileName(9).c_str(), "r"));
 }
 
 TEST_F(MultiSegmentSegmenterTest, SplitsClustersOnSubsegment) {
@@ -176,23 +179,23 @@ TEST_F(MultiSegmentSegmenterTest, SplitsClustersOnSubsegment) {
   // Write the samples to the Segmenter.
   for (int i = 0; i < 8; i++) {
     if (i == 5) {
-      ASSERT_OK(segmenter_->FinalizeSegment(0, 5 * kDuration, kSubsegment));
+      ASSERT_OK(segmenter_->FinalizeSegment(0, 5 * kDuration, kSubsegment, 5));
     }
     std::shared_ptr<MediaSample> sample =
         CreateSample(kKeyFrame, kDuration, kNoSideData);
     ASSERT_OK(segmenter_->AddSample(*sample));
   }
-  ASSERT_OK(segmenter_->FinalizeSegment(0, 8 * kDuration, !kSubsegment));
+  ASSERT_OK(segmenter_->FinalizeSegment(0, 8 * kDuration, !kSubsegment, 8));
   ASSERT_OK(segmenter_->Finalize());
 
   // Verify the resulting data.
   ClusterParser parser;
-  ASSERT_NO_FATAL_FAILURE(parser.PopulateFromCluster(TemplateFileName(0)));
+  ASSERT_NO_FATAL_FAILURE(parser.PopulateFromCluster(TemplateFileName(7)));
   ASSERT_EQ(2u, parser.cluster_count());
   EXPECT_EQ(5u, parser.GetFrameCountForCluster(0));
   EXPECT_EQ(3u, parser.GetFrameCountForCluster(1));
 
-  EXPECT_FALSE(File::Open(TemplateFileName(1).c_str(), "r"));
+  EXPECT_FALSE(File::Open(TemplateFileName(8).c_str(), "r"));
 }
 
 }  // namespace media
diff --git a/packager/media/formats/webm/segmenter.cc b/packager/media/formats/webm/segmenter.cc
index b3ffdcfb188..70c29cf3920 100644
--- a/packager/media/formats/webm/segmenter.cc
+++ b/packager/media/formats/webm/segmenter.cc
@@ -135,8 +135,8 @@ Status Segmenter::Initialize(const StreamInfo& info,
   if (info.is_encrypted()) {
     if (info.encryption_config().per_sample_iv_size != kWebMIvSize)
       return Status(error::MUXER_FAILURE, "Incorrect size WebM encryption IV.");
-    status = UpdateTrackForEncryption(info.encryption_config().key_id,
-                                      track.get());
+    status =
+        UpdateTrackForEncryption(info.encryption_config().key_id, track.get());
     if (!status.ok())
       return status;
   }
@@ -196,7 +196,8 @@ Status Segmenter::AddSample(const MediaSample& source_sample) {
 
 Status Segmenter::FinalizeSegment(uint64_t start_timestamp,
                                   uint64_t duration_timestamp,
-                                  bool is_subsegment) {
+                                  bool is_subsegment,
+                                  uint64_t segment_index) {
   if (is_subsegment)
     new_subsegment_ = true;
   else
@@ -211,9 +212,8 @@ float Segmenter::GetDurationInSeconds() const {
 }
 
 uint64_t Segmenter::FromBmffTimestamp(uint64_t bmff_timestamp) {
-  return NsToWebMTimecode(
-      BmffTimestampToNs(bmff_timestamp, time_scale_),
-      segment_info_.timecode_scale());
+  return NsToWebMTimecode(BmffTimestampToNs(bmff_timestamp, time_scale_),
+                          segment_info_.timecode_scale());
 }
 
 uint64_t Segmenter::FromWebMTimecode(uint64_t webm_timecode) {
@@ -389,8 +389,7 @@ Status Segmenter::WriteFrame(bool write_duration) {
         BmffTimestampToNs(prev_sample_->duration(), time_scale_));
   }
   frame.set_is_key(prev_sample_->is_key_frame());
-  frame.set_timestamp(
-      BmffTimestampToNs(prev_sample_->pts(), time_scale_));
+  frame.set_timestamp(BmffTimestampToNs(prev_sample_->pts(), time_scale_));
   frame.set_track_number(track_id_);
 
   if (prev_sample_->side_data_size() > 0) {
diff --git a/packager/media/formats/webm/segmenter.h b/packager/media/formats/webm/segmenter.h
index f6c7c2184d1..0284c6d6970 100644
--- a/packager/media/formats/webm/segmenter.h
+++ b/packager/media/formats/webm/segmenter.h
@@ -57,7 +57,8 @@ class Segmenter {
   /// Finalize the (sub)segment.
   virtual Status FinalizeSegment(uint64_t start_timestamp,
                                  uint64_t duration_timestamp,
-                                 bool is_subsegment) = 0;
+                                 bool is_subsegment,
+                                 uint64_t segment_index) = 0;
 
   /// @return true if there is an initialization range, while setting @a start
   ///         and @a end; or false if initialization range does not apply.
diff --git a/packager/media/formats/webm/single_segment_segmenter.cc b/packager/media/formats/webm/single_segment_segmenter.cc
index 29a6be75722..3cb9c269e44 100644
--- a/packager/media/formats/webm/single_segment_segmenter.cc
+++ b/packager/media/formats/webm/single_segment_segmenter.cc
@@ -21,9 +21,10 @@ SingleSegmentSegmenter::~SingleSegmentSegmenter() {}
 
 Status SingleSegmentSegmenter::FinalizeSegment(uint64_t start_timestamp,
                                                uint64_t duration_timestamp,
-                                               bool is_subsegment) {
-  Status status = Segmenter::FinalizeSegment(start_timestamp,
-                                             duration_timestamp, is_subsegment);
+                                               bool is_subsegment,
+                                               uint64_t segment_index) {
+  Status status = Segmenter::FinalizeSegment(
+      start_timestamp, duration_timestamp, is_subsegment, segment_index);
   if (!status.ok())
     return status;
   // No-op for subsegment in single segment mode.
@@ -35,7 +36,7 @@ Status SingleSegmentSegmenter::FinalizeSegment(uint64_t start_timestamp,
   if (muxer_listener()) {
     const uint64_t size = cluster()->Size();
     muxer_listener()->OnNewSegment(options().output_file_name, start_timestamp,
-                                   duration_timestamp, size);
+                                   duration_timestamp, size, segment_index);
   }
   return Status::OK;
 }
diff --git a/packager/media/formats/webm/single_segment_segmenter.h b/packager/media/formats/webm/single_segment_segmenter.h
index 0115fcd0afe..201ca1e1743 100644
--- a/packager/media/formats/webm/single_segment_segmenter.h
+++ b/packager/media/formats/webm/single_segment_segmenter.h
@@ -7,10 +7,10 @@
 #ifndef PACKAGER_MEDIA_FORMATS_WEBM_SINGLE_SEGMENT_SEGMENTER_H_
 #define PACKAGER_MEDIA_FORMATS_WEBM_SINGLE_SEGMENT_SEGMENTER_H_
 
-#include "packager/media/formats/webm/segmenter.h"
-
 #include <memory>
+
 #include "packager/media/formats/webm/mkv_writer.h"
+#include "packager/media/formats/webm/segmenter.h"
 #include "packager/status.h"
 
 namespace shaka {
@@ -32,7 +32,8 @@ class SingleSegmentSegmenter : public Segmenter {
   /// @{
   Status FinalizeSegment(uint64_t start_timestamp,
                          uint64_t duration_timestamp,
-                         bool is_subsegment) override;
+                         bool is_subsegment,
+                         uint64_t segment_index) override;
   bool GetInitRangeStartAndEnd(uint64_t* start, uint64_t* end) override;
   bool GetIndexRangeStartAndEnd(uint64_t* start, uint64_t* end) override;
   std::vector<Range> GetSegmentRanges() override;
diff --git a/packager/media/formats/webm/single_segment_segmenter_unittest.cc b/packager/media/formats/webm/single_segment_segmenter_unittest.cc
index 175931183b4..50260b8a18f 100644
--- a/packager/media/formats/webm/single_segment_segmenter_unittest.cc
+++ b/packager/media/formats/webm/single_segment_segmenter_unittest.cc
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "packager/media/formats/webm/two_pass_single_segment_segmenter.h"
-
 #include <gtest/gtest.h>
+
 #include <memory>
+
 #include "packager/media/formats/webm/segmenter_test_base.h"
+#include "packager/media/formats/webm/two_pass_single_segment_segmenter.h"
 
 namespace shaka {
 namespace media {
@@ -163,7 +164,7 @@ TEST_F(SingleSegmentSegmenterTest, BasicSupport) {
         CreateSample(kKeyFrame, kDuration, side_data_flag);
     ASSERT_OK(segmenter_->AddSample(*sample));
   }
-  ASSERT_OK(segmenter_->FinalizeSegment(0, 5 * kDuration, !kSubsegment));
+  ASSERT_OK(segmenter_->FinalizeSegment(0, 5 * kDuration, !kSubsegment, 5));
   ASSERT_OK(segmenter_->Finalize());
 
   ASSERT_FILE_ENDS_WITH(OutputFileName().c_str(), kBasicSupportData);
@@ -176,14 +177,14 @@ TEST_F(SingleSegmentSegmenterTest, SplitsClustersOnSegment) {
   // Write the samples to the Segmenter.
   for (int i = 0; i < 8; i++) {
     if (i == 5) {
-      ASSERT_OK(segmenter_->FinalizeSegment(0, 5 * kDuration, !kSubsegment));
+      ASSERT_OK(segmenter_->FinalizeSegment(0, 5 * kDuration, !kSubsegment, 5));
     }
     std::shared_ptr<MediaSample> sample =
         CreateSample(kKeyFrame, kDuration, kNoSideData);
     ASSERT_OK(segmenter_->AddSample(*sample));
   }
-  ASSERT_OK(
-      segmenter_->FinalizeSegment(5 * kDuration, 8 * kDuration, !kSubsegment));
+  ASSERT_OK(segmenter_->FinalizeSegment(5 * kDuration, 8 * kDuration,
+                                        !kSubsegment, 8));
   ASSERT_OK(segmenter_->Finalize());
 
   // Verify the resulting data.
@@ -201,13 +202,13 @@ TEST_F(SingleSegmentSegmenterTest, IgnoresSubsegment) {
   // Write the samples to the Segmenter.
   for (int i = 0; i < 8; i++) {
     if (i == 5) {
-      ASSERT_OK(segmenter_->FinalizeSegment(0, 5 * kDuration, kSubsegment));
+      ASSERT_OK(segmenter_->FinalizeSegment(0, 5 * kDuration, kSubsegment, 5));
     }
     std::shared_ptr<MediaSample> sample =
         CreateSample(kKeyFrame, kDuration, kNoSideData);
     ASSERT_OK(segmenter_->AddSample(*sample));
   }
-  ASSERT_OK(segmenter_->FinalizeSegment(0, 8 * kDuration, !kSubsegment));
+  ASSERT_OK(segmenter_->FinalizeSegment(0, 8 * kDuration, !kSubsegment, 8));
   ASSERT_OK(segmenter_->Finalize());
 
   // Verify the resulting data.
@@ -234,7 +235,7 @@ TEST_F(SingleSegmentSegmenterTest, LargeTimestamp) {
     ASSERT_OK(segmenter_->AddSample(*sample));
   }
   ASSERT_OK(segmenter_->FinalizeSegment(kLargeTimestamp, 5 * kDuration,
-                                        !kSubsegment));
+                                        !kSubsegment, 5));
   ASSERT_OK(segmenter_->Finalize());
 
   // Verify the resulting data.
@@ -270,7 +271,7 @@ TEST_F(SingleSegmentSegmenterTest, ReallyLargeTimestamp) {
     ASSERT_OK(segmenter_->AddSample(*sample));
   }
   ASSERT_OK(segmenter_->FinalizeSegment(kReallyLargeTimestamp, 5 * kDuration,
-                                        !kSubsegment));
+                                        !kSubsegment, 5));
   ASSERT_OK(segmenter_->Finalize());
 
   // Verify the resulting data.
diff --git a/packager/media/formats/webm/webm_muxer.cc b/packager/media/formats/webm/webm_muxer.cc
index dcf02be7a7a..786640e5780 100644
--- a/packager/media/formats/webm/webm_muxer.cc
+++ b/packager/media/formats/webm/webm_muxer.cc
@@ -78,9 +78,9 @@ Status WebMMuxer::FinalizeSegment(size_t stream_id,
     return Status(error::UNIMPLEMENTED,
                   "Key rotation is not implemented for WebM");
   }
-  return segmenter_->FinalizeSegment(segment_info.start_timestamp,
-                                     segment_info.duration,
-                                     segment_info.is_subsegment);
+  return segmenter_->FinalizeSegment(
+      segment_info.start_timestamp, segment_info.duration,
+      segment_info.is_subsegment, segment_info.segment_index);
 }
 
 void WebMMuxer::FireOnMediaStartEvent() {
diff --git a/packager/media/formats/webvtt/webvtt_text_output_handler.cc b/packager/media/formats/webvtt/webvtt_text_output_handler.cc
index 3043209114e..e338bdbccc2 100644
--- a/packager/media/formats/webvtt/webvtt_text_output_handler.cc
+++ b/packager/media/formats/webvtt/webvtt_text_output_handler.cc
@@ -85,13 +85,13 @@ Status WebVttTextOutputHandler::OnSegmentInfo(const SegmentInfo& info) {
   total_duration_ms_ += info.duration;
 
   const std::string& segment_template = muxer_options_.segment_template;
-  const uint32_t index = segment_index_++;
+  const uint32_t index = info.segment_index;
   const uint64_t start = info.start_timestamp;
   const uint64_t duration = info.duration;
   const uint32_t bandwidth = muxer_options_.bandwidth;
 
   const std::string filename =
-      GetSegmentName(segment_template, start, index, bandwidth);
+      GetSegmentName(segment_template, start, index - 1, bandwidth);
 
   // Write everything to the file before telling the manifest so that the
   // file will exist on disk.
@@ -110,7 +110,8 @@ Status WebVttTextOutputHandler::OnSegmentInfo(const SegmentInfo& info) {
 
   // Update the manifest with our new file.
   const uint64_t size = File::GetFileSize(filename.c_str());
-  muxer_listener_->OnNewSegment(filename, start, duration, size);
+  muxer_listener_->OnNewSegment(filename, start, duration, size,
+                                info.segment_index);
 
   return Status::OK;
 }
diff --git a/packager/media/formats/webvtt/webvtt_text_output_handler_unittest.cc b/packager/media/formats/webvtt/webvtt_text_output_handler_unittest.cc
index cde1afa78dc..3212f5061a6 100644
--- a/packager/media/formats/webvtt/webvtt_text_output_handler_unittest.cc
+++ b/packager/media/formats/webvtt/webvtt_text_output_handler_unittest.cc
@@ -4,6 +4,8 @@
 // license that can be found in the LICENSE file or at
 // https://developers.google.com/open-source/licenses/bsd
 
+#include "packager/media/formats/webvtt/webvtt_text_output_handler.h"
+
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
@@ -12,7 +14,6 @@
 #include "packager/media/base/text_stream_info.h"
 #include "packager/media/event/combined_muxer_listener.h"
 #include "packager/media/event/mock_muxer_listener.h"
-#include "packager/media/formats/webvtt/webvtt_text_output_handler.h"
 #include "packager/status_test_util.h"
 
 namespace shaka {
@@ -60,7 +61,7 @@ class WebVttSegmentedOutputTest : public MediaHandlerTestBase {
 };
 
 TEST_F(WebVttSegmentedOutputTest, WithNoSegmentAndWithNoSamples) {
-  EXPECT_CALL(*muxer_listener_, OnNewSegment(_, _, _, _)).Times(0);
+  EXPECT_CALL(*muxer_listener_, OnNewSegment(_, _, _, _, _)).Times(0);
 
   {
     // No segments should  have be created as there were no samples.
@@ -94,7 +95,7 @@ TEST_F(WebVttSegmentedOutputTest, WithOneSegmentAndWithOneSample) {
     EXPECT_CALL(*muxer_listener_, OnMediaStart(_, _, _, _));
     EXPECT_CALL(*muxer_listener_,
                 OnNewSegment(kSegmentedFileOutput1, kSegmentStart,
-                             kSegmentDuration, _));
+                             kSegmentDuration, _, 1));
 
     const float kMediaDuration = 1 * kSegmentDuration / kMillisecondsPerSecond;
     EXPECT_CALL(*muxer_listener_,
@@ -141,10 +142,10 @@ TEST_F(WebVttSegmentedOutputTest, WithTwoSegmentAndWithOneSample) {
     EXPECT_CALL(*muxer_listener_, OnMediaStart(_, _, _, _));
     EXPECT_CALL(*muxer_listener_,
                 OnNewSegment(kSegmentedFileOutput1, kSegment1Start,
-                             kSegmentDuration, _));
+                             kSegmentDuration, _, _));
     EXPECT_CALL(*muxer_listener_,
                 OnNewSegment(kSegmentedFileOutput2, kSegment2Start,
-                             kSegmentDuration, _));
+                             kSegmentDuration, _, _));
 
     const float kMediaDuration = 2 * kSegmentDuration / kMillisecondsPerSecond;
     EXPECT_CALL(*muxer_listener_,
@@ -201,10 +202,10 @@ TEST_F(WebVttSegmentedOutputTest, WithAnEmptySegment) {
     EXPECT_CALL(*muxer_listener_, OnMediaStart(_, _, _, _));
     EXPECT_CALL(*muxer_listener_,
                 OnNewSegment(kSegmentedFileOutput1, kSegment1Start,
-                             kSegmentDuration, _));
+                             kSegmentDuration, _, _));
     EXPECT_CALL(*muxer_listener_,
                 OnNewSegment(kSegmentedFileOutput2, kSegment2Start,
-                             kSegmentDuration, _));
+                             kSegmentDuration, _, _));
 
     const float kMediaDuration = 2 * kSegmentDuration / kMillisecondsPerSecond;
     EXPECT_CALL(*muxer_listener_,
diff --git a/packager/mpd/base/adaptation_set_unittest.cc b/packager/mpd/base/adaptation_set_unittest.cc
index 0d6e37d3b89..1b602b98582 100644
--- a/packager/mpd/base/adaptation_set_unittest.cc
+++ b/packager/mpd/base/adaptation_set_unittest.cc
@@ -682,30 +682,33 @@ TEST_F(OnDemandAdaptationSetTest, SubsegmentAlignment) {
   const uint64_t kStartTime = 0u;
   const uint64_t kDuration = 10u;
   const uint64_t kAnySize = 19834u;
+  const uint64_t kSegmentIndex = 1;
 
   auto adaptation_set = CreateAdaptationSet(kNoLanguage);
   Representation* representation_480p =
       adaptation_set->AddRepresentation(ConvertToMediaInfo(k480pMediaInfo));
   // Add a subsegment immediately before adding the 360p Representation.
   // This should still work for VOD.
-  representation_480p->AddNewSegment(kStartTime, kDuration, kAnySize);
+  representation_480p->AddNewSegment(kStartTime, kDuration, kAnySize,
+                                     kSegmentIndex);
 
   Representation* representation_360p =
       adaptation_set->AddRepresentation(ConvertToMediaInfo(k360pMediaInfo));
-  representation_360p->AddNewSegment(kStartTime, kDuration, kAnySize);
+  representation_360p->AddNewSegment(kStartTime, kDuration, kAnySize,
+                                     kSegmentIndex);
 
   xml::scoped_xml_ptr<xmlNode> aligned(adaptation_set->GetXml());
   EXPECT_THAT(aligned.get(), AttributeEqual("subsegmentAlignment", "true"));
 
   // Unknown because 480p has an extra subsegments.
-  representation_480p->AddNewSegment(11, 20, kAnySize);
+  representation_480p->AddNewSegment(11, 20, kAnySize, (11 / 20) + 1);
   xml::scoped_xml_ptr<xmlNode> alignment_unknown(adaptation_set->GetXml());
   EXPECT_THAT(alignment_unknown.get(),
               Not(AttributeSet("subsegmentAlignment")));
 
   // Add segments that make them not aligned.
-  representation_360p->AddNewSegment(10, 1, kAnySize);
-  representation_360p->AddNewSegment(11, 19, kAnySize);
+  representation_360p->AddNewSegment(10, 1, kAnySize, (10 / 1) + 1);
+  representation_360p->AddNewSegment(11, 19, kAnySize, (11 / 19) + 1);
 
   xml::scoped_xml_ptr<xmlNode> unaligned(adaptation_set->GetXml());
   EXPECT_THAT(unaligned.get(), Not(AttributeSet("subsegmentAlignment")));
@@ -747,8 +750,8 @@ TEST_F(OnDemandAdaptationSetTest, ForceSetsubsegmentAlignment) {
   static_assert(kStartTime1 != kStartTime2, "StartTimesShouldBeDifferent");
   const uint64_t kDuration = 10u;
   const uint64_t kAnySize = 19834u;
-  representation_480p->AddNewSegment(kStartTime1, kDuration, kAnySize);
-  representation_360p->AddNewSegment(kStartTime2, kDuration, kAnySize);
+  representation_480p->AddNewSegment(kStartTime1, kDuration, kAnySize, 1);
+  representation_360p->AddNewSegment(kStartTime2, kDuration, kAnySize, 1);
   xml::scoped_xml_ptr<xmlNode> unaligned(adaptation_set->GetXml());
   EXPECT_THAT(unaligned.get(), Not(AttributeSet("subsegmentAlignment")));
 
@@ -798,15 +801,15 @@ TEST_F(LiveAdaptationSetTest, SegmentAlignmentDynamicMpd) {
   Representation* representation_360p =
       adaptation_set->AddRepresentation(ConvertToMediaInfo(k360pMediaInfo));
 
-  representation_480p->AddNewSegment(kStartTime, kDuration, kAnySize);
-  representation_360p->AddNewSegment(kStartTime, kDuration, kAnySize);
+  representation_480p->AddNewSegment(kStartTime, kDuration, kAnySize, 1);
+  representation_360p->AddNewSegment(kStartTime, kDuration, kAnySize, 1);
   xml::scoped_xml_ptr<xmlNode> aligned(adaptation_set->GetXml());
   EXPECT_THAT(aligned.get(), AttributeEqual("segmentAlignment", "true"));
 
   // Add segments that make them not aligned.
-  representation_480p->AddNewSegment(11, 20, kAnySize);
-  representation_360p->AddNewSegment(10, 1, kAnySize);
-  representation_360p->AddNewSegment(11, 19, kAnySize);
+  representation_480p->AddNewSegment(11, 20, kAnySize, (11 / 20) + 1);
+  representation_360p->AddNewSegment(10, 1, kAnySize, (10 / 1) + 1);
+  representation_360p->AddNewSegment(11, 19, kAnySize, (11 / 19) + 1);
 
   xml::scoped_xml_ptr<xmlNode> unaligned(adaptation_set->GetXml());
   EXPECT_THAT(unaligned.get(), Not(AttributeSet("segmentAlignment")));
@@ -851,16 +854,16 @@ TEST_F(LiveAdaptationSetTest, SegmentAlignmentStaticMpd) {
   // Representation.
   Representation* representation_480p =
       adaptation_set->AddRepresentation(ConvertToMediaInfo(k480pMediaInfo));
-  representation_480p->AddNewSegment(kStartTime, kDuration, kAnySize);
+  representation_480p->AddNewSegment(kStartTime, kDuration, kAnySize, 1);
 
   Representation* representation_360p =
       adaptation_set->AddRepresentation(ConvertToMediaInfo(k360pMediaInfo));
-  representation_360p->AddNewSegment(kStartTime, kDuration, kAnySize);
+  representation_360p->AddNewSegment(kStartTime, kDuration, kAnySize, 1);
 
   representation_480p->AddNewSegment(kStartTime + kDuration, kDuration,
-                                     kAnySize);
+                                     kAnySize, 2);
   representation_360p->AddNewSegment(kStartTime + kDuration, kDuration,
-                                     kAnySize);
+                                     kAnySize, 2);
 
   xml::scoped_xml_ptr<xmlNode> aligned(adaptation_set->GetXml());
   EXPECT_THAT(aligned.get(), AttributeEqual("segmentAlignment", "true"));
diff --git a/packager/mpd/base/mock_mpd_builder.h b/packager/mpd/base/mock_mpd_builder.h
index 6d46396f306..7c4b70cdeab 100644
--- a/packager/mpd/base/mock_mpd_builder.h
+++ b/packager/mpd/base/mock_mpd_builder.h
@@ -75,8 +75,11 @@ class MockRepresentation : public Representation {
                void(const ContentProtectionElement& element));
   MOCK_METHOD2(UpdateContentProtectionPssh,
                void(const std::string& drm_uuid, const std::string& pssh));
-  MOCK_METHOD3(AddNewSegment,
-               void(int64_t start_time, int64_t duration, uint64_t size));
+  MOCK_METHOD4(AddNewSegment,
+               void(int64_t start_time,
+                    int64_t duration,
+                    uint64_t size,
+                    uint64_t segment_index));
   MOCK_METHOD1(SetSampleDuration, void(uint32_t sample_duration));
   MOCK_CONST_METHOD0(GetMediaInfo, const MediaInfo&());
 };
diff --git a/packager/mpd/base/mock_mpd_notifier.h b/packager/mpd/base/mock_mpd_notifier.h
index 0726f520925..7d2eacd8254 100644
--- a/packager/mpd/base/mock_mpd_notifier.h
+++ b/packager/mpd/base/mock_mpd_notifier.h
@@ -7,12 +7,11 @@
 #ifndef MPD_BASE_MOCK_MPD_NOTIFIER_H_
 #define MPD_BASE_MOCK_MPD_NOTIFIER_H_
 
-#include "packager/mpd/base/mpd_notifier.h"
-
 #include <gmock/gmock.h>
 
 #include "packager/mpd/base/content_protection_element.h"
 #include "packager/mpd/base/media_info.pb.h"
+#include "packager/mpd/base/mpd_notifier.h"
 
 namespace shaka {
 
@@ -26,11 +25,12 @@ class MockMpdNotifier : public MpdNotifier {
                bool(const MediaInfo& media_info, uint32_t* container_id));
   MOCK_METHOD2(NotifySampleDuration,
                bool(uint32_t container_id, uint32_t sample_duration));
-  MOCK_METHOD4(NotifyNewSegment,
+  MOCK_METHOD5(NotifyNewSegment,
                bool(uint32_t container_id,
                     uint64_t start_time,
                     uint64_t duration,
-                    uint64_t size));
+                    uint64_t size,
+                    uint64_t segment_index));
   MOCK_METHOD2(NotifyCueEvent, bool(uint32_t container_id, uint64_t timestamp));
   MOCK_METHOD4(NotifyEncryptionUpdate,
                bool(uint32_t container_id,
diff --git a/packager/mpd/base/mpd_builder_unittest.cc b/packager/mpd/base/mpd_builder_unittest.cc
index acd7ed1c8e1..69a3d170749 100644
--- a/packager/mpd/base/mpd_builder_unittest.cc
+++ b/packager/mpd/base/mpd_builder_unittest.cc
@@ -4,11 +4,12 @@
 // license that can be found in the LICENSE file or at
 // https://developers.google.com/open-source/licenses/bsd
 
+#include "packager/mpd/base/mpd_builder.h"
+
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
 #include "packager/mpd/base/adaptation_set.h"
-#include "packager/mpd/base/mpd_builder.h"
 #include "packager/mpd/base/period.h"
 #include "packager/mpd/base/representation.h"
 #include "packager/mpd/test/mpd_builder_test_helper.h"
@@ -71,7 +72,8 @@ class MpdBuilderTest : public ::testing::Test {
         adaptation_set->AddRepresentation(media_info);
     representation->AddNewSegment(
         segment_start_time_seconds * media_info.reference_time_scale(),
-        segment_duration_seconds * media_info.reference_time_scale(), kBytes);
+        segment_duration_seconds * media_info.reference_time_scale(), kBytes,
+        (segment_start_time_seconds / segment_duration_seconds) + 1);
   }
 
  protected:
@@ -117,14 +119,14 @@ class LiveMpdBuilderTest : public MpdBuilderTest<DashProfile::kLive> {
 
   // Injects a clock that always returns 2016 Jan 11 15:10:24 in UTC.
   void InjectTestClock() {
-    base::Time::Exploded test_time = { 2016,  // year.
-                                       1,  // month
-                                       1,  // day_of_week = Monday.
-                                       11,  // day_of_month
-                                       15,  // hour.
-                                       10,  // minute.
-                                       24,  // second.
-                                       0 };  // millisecond.
+    base::Time::Exploded test_time = {2016,  // year.
+                                      1,     // month
+                                      1,     // day_of_week = Monday.
+                                      11,    // day_of_month
+                                      15,    // hour.
+                                      10,    // minute.
+                                      24,    // second.
+                                      0};    // millisecond.
     ASSERT_TRUE(test_time.HasValidValues());
     mpd_.InjectClockForTesting(std::unique_ptr<base::Clock>(
         new TestClock(base::Time::FromUTCExploded(test_time))));
diff --git a/packager/mpd/base/mpd_notifier.h b/packager/mpd/base/mpd_notifier.h
index 6576b7c625d..ad954056034 100644
--- a/packager/mpd/base/mpd_notifier.h
+++ b/packager/mpd/base/mpd_notifier.h
@@ -65,11 +65,13 @@ class MpdNotifier {
   /// @param duration is the duration of the new segment, in units of the
   ///        stream's time scale.
   /// @param size is the new segment size in bytes.
+  /// @param segment_index is the segment index.
   /// @return true on success, false otherwise.
   virtual bool NotifyNewSegment(uint32_t container_id,
                                 uint64_t start_time,
                                 uint64_t duration,
-                                uint64_t size) = 0;
+                                uint64_t size,
+                                uint64_t segment_index) = 0;
 
   /// Notifies MpdBuilder that there is a new CueEvent.
   /// @param container_id Container ID obtained from calling
@@ -105,7 +107,9 @@ class MpdNotifier {
   virtual bool Flush() = 0;
 
   /// @return include_mspr_pro option flag
-  bool include_mspr_pro() const { return mpd_options_.mpd_params.include_mspr_pro; }
+  bool include_mspr_pro() const {
+    return mpd_options_.mpd_params.include_mspr_pro;
+  }
 
   /// @return The dash profile for this object.
   DashProfile dash_profile() const { return mpd_options_.dash_profile; }
diff --git a/packager/mpd/base/representation.cc b/packager/mpd/base/representation.cc
index b1b46c8c2e0..04442193cea 100644
--- a/packager/mpd/base/representation.cc
+++ b/packager/mpd/base/representation.cc
@@ -170,7 +170,8 @@ void Representation::UpdateContentProtectionPssh(const std::string& drm_uuid,
 
 void Representation::AddNewSegment(int64_t start_time,
                                    int64_t duration,
-                                   uint64_t size) {
+                                   uint64_t size,
+                                   uint64_t segment_index) {
   if (start_time == 0 && duration == 0) {
     LOG(WARNING) << "Got segment with start_time and duration == 0. Ignoring.";
     return;
@@ -186,7 +187,7 @@ void Representation::AddNewSegment(int64_t start_time,
   if (state_change_listener_)
     state_change_listener_->OnNewSegmentForRepresentation(start_time, duration);
 
-  AddSegmentInfo(start_time, duration);
+  AddSegmentInfo(start_time, duration, segment_index);
   current_buffer_depth_ += segment_infos_.back().duration;
 
   bandwidth_estimator_.AddBlock(
@@ -328,10 +329,20 @@ bool Representation::HasRequiredMediaInfoFields() const {
   return true;
 }
 
-void Representation::AddSegmentInfo(int64_t start_time, int64_t duration) {
+void Representation::AddSegmentInfo(int64_t start_time,
+                                    int64_t duration,
+                                    uint64_t segment_index) {
   const uint64_t kNoRepeat = 0;
   const int64_t adjusted_duration = AdjustDuration(duration);
 
+  if (segment_infos_.empty()) {
+    if (mpd_options_.mpd_params.target_segment_duration > 0 &&
+        mpd_options_.mpd_params.allow_approximate_segment_timeline) {
+      start_number_ = segment_index;
+      stream_just_started_ = true;
+    }
+  }
+
   if (!segment_infos_.empty()) {
     // Contiguous segment.
     const SegmentInfo& previous = segment_infos_.back();
@@ -348,6 +359,19 @@ void Representation::AddSegmentInfo(int64_t start_time, int64_t duration) {
       if (ApproximiatelyEqual(segment_end_time_for_same_duration,
                               actual_segment_end_time)) {
         ++segment_infos_.back().repeat;
+        if (mpd_options_.mpd_params.allow_approximate_segment_timeline &&
+            mpd_options_.mpd_params.target_segment_duration > 0 &&
+            stream_just_started_ && segment_infos_.size() == 2) {
+          const SegmentInfo& first_segment = segment_infos_.front();
+          const SegmentInfo& last_segment = segment_infos_.back();
+          if (first_segment.repeat == 0 &&
+              first_segment.duration < last_segment.duration &&
+              last_segment.repeat > 0) {
+            segment_infos_.pop_front();
+            start_number_ = last_segment.start_time / last_segment.duration + 1;
+          }
+          stream_just_started_ = false;
+        }
       } else {
         segment_infos_.push_back(
             {previous_segment_end_time,
diff --git a/packager/mpd/base/representation.h b/packager/mpd/base/representation.h
index 813d43edc5f..f0621ea4f68 100644
--- a/packager/mpd/base/representation.h
+++ b/packager/mpd/base/representation.h
@@ -9,16 +9,16 @@
 #ifndef PACKAGER_MPD_BASE_REPRESENTATION_H_
 #define PACKAGER_MPD_BASE_REPRESENTATION_H_
 
-#include "packager/mpd/base/bandwidth_estimator.h"
-#include "packager/mpd/base/media_info.pb.h"
-#include "packager/mpd/base/segment_info.h"
-#include "packager/mpd/base/xml/scoped_xml_ptr.h"
-
 #include <stdint.h>
 
 #include <list>
 #include <memory>
 
+#include "packager/mpd/base/bandwidth_estimator.h"
+#include "packager/mpd/base/media_info.pb.h"
+#include "packager/mpd/base/segment_info.h"
+#include "packager/mpd/base/xml/scoped_xml_ptr.h"
+
 namespace shaka {
 
 struct ContentProtectionElement;
@@ -100,10 +100,12 @@ class Representation {
   ///        stream's time scale.
   /// @param duration is the duration of the segment, in units of the stream's
   ///        time scale.
+  /// @param segment_index is the current segment index.
   /// @param size of the segment in bytes.
   virtual void AddNewSegment(int64_t start_time,
                              int64_t duration,
-                             uint64_t size);
+                             uint64_t size,
+                             uint64_t segment_index);
 
   /// Set the sample duration of this Representation.
   /// Sample duration is not available right away especially for live. This
@@ -182,7 +184,9 @@ class Representation {
 
   // Add a SegmentInfo. This function may insert an adjusted SegmentInfo if
   // |allow_approximate_segment_timeline_| is set.
-  void AddSegmentInfo(int64_t start_time, int64_t duration);
+  void AddSegmentInfo(int64_t start_time,
+                      int64_t duration,
+                      uint64_t segment_index);
 
   // Check if two timestamps are approximately equal if
   // |allow_approximate_segment_timeline_| is set; Otherwise check whether the
@@ -231,6 +235,8 @@ class Representation {
   // Starts from 1.
   uint32_t start_number_ = 1;
 
+  bool stream_just_started_ = false;
+
   // If this is not null, then Representation is responsible for calling the
   // right methods at right timings.
   std::unique_ptr<RepresentationStateChangeListener> state_change_listener_;
diff --git a/packager/mpd/base/representation_unittest.cc b/packager/mpd/base/representation_unittest.cc
index c9a9f97684b..6a73062e522 100644
--- a/packager/mpd/base/representation_unittest.cc
+++ b/packager/mpd/base/representation_unittest.cc
@@ -280,7 +280,8 @@ TEST_F(RepresentationTest,
                            kAnyRepresentationId, std::move(listener));
   EXPECT_TRUE(representation->Init());
 
-  representation->AddNewSegment(kStartTime, kDuration, 10 /* any size */);
+  representation->AddNewSegment(kStartTime, kDuration, 10 /* any size */,
+                                (kStartTime / kDuration) + 1);
 }
 
 // Make sure
@@ -468,7 +469,8 @@ class SegmentTemplateTest : public RepresentationTest {
     }
 
     for (int i = 0; i < repeat + 1; ++i) {
-      representation_->AddNewSegment(start_time, duration, size);
+      representation_->AddNewSegment(start_time, duration, size,
+                                     (start_time / duration) + 1);
       start_time += duration;
       bandwidth_estimator_.AddBlock(
           size, static_cast<double>(duration) / kDefaultTimeScale);
@@ -799,12 +801,16 @@ TEST_P(ApproximateSegmentTimelineTest,
   if (allow_approximate_segment_timeline_) {
     expected_s_elements = base::StringPrintf(
         kSElementTemplateWithoutR, kStartTime, kScaledTargetSegmentDuration);
+    EXPECT_THAT(representation_->GetXml().get(),
+                XmlNodeEqual(SegmentTimelineTestBase::ExpectedXml(
+                    expected_s_elements, 1372)));
   } else {
     expected_s_elements = base::StringPrintf(kSElementTemplateWithoutR,
                                              kStartTime, kDurationSmaller);
+    EXPECT_THAT(representation_->GetXml().get(),
+                XmlNodeEqual(SegmentTimelineTestBase::ExpectedXml(
+                    expected_s_elements, 1)));
   }
-  EXPECT_THAT(representation_->GetXml().get(),
-              XmlNodeEqual(ExpectedXml(expected_s_elements)));
 }
 
 TEST_P(ApproximateSegmentTimelineTest, SegmentsWithSimilarDurations) {
diff --git a/packager/mpd/base/simple_mpd_notifier.cc b/packager/mpd/base/simple_mpd_notifier.cc
index 9f93a4a642f..34d9c7f5895 100644
--- a/packager/mpd/base/simple_mpd_notifier.cc
+++ b/packager/mpd/base/simple_mpd_notifier.cc
@@ -86,14 +86,15 @@ bool SimpleMpdNotifier::NotifySampleDuration(uint32_t container_id,
 bool SimpleMpdNotifier::NotifyNewSegment(uint32_t container_id,
                                          uint64_t start_time,
                                          uint64_t duration,
-                                         uint64_t size) {
+                                         uint64_t size,
+                                         uint64_t segment_index) {
   base::AutoLock auto_lock(lock_);
   auto it = representation_map_.find(container_id);
   if (it == representation_map_.end()) {
     LOG(ERROR) << "Unexpected container_id: " << container_id;
     return false;
   }
-  it->second->AddNewSegment(start_time, duration, size);
+  it->second->AddNewSegment(start_time, duration, size, segment_index);
   return true;
 }
 
diff --git a/packager/mpd/base/simple_mpd_notifier.h b/packager/mpd/base/simple_mpd_notifier.h
index 749da46a1cf..b90e105d63e 100644
--- a/packager/mpd/base/simple_mpd_notifier.h
+++ b/packager/mpd/base/simple_mpd_notifier.h
@@ -41,7 +41,8 @@ class SimpleMpdNotifier : public MpdNotifier {
   bool NotifyNewSegment(uint32_t container_id,
                         uint64_t start_time,
                         uint64_t duration,
-                        uint64_t size) override;
+                        uint64_t size,
+                        uint64_t segment_index) override;
   bool NotifyCueEvent(uint32_t container_id, uint64_t timestamp) override;
   bool NotifyEncryptionUpdate(uint32_t container_id,
                               const std::string& drm_uuid,
diff --git a/packager/mpd/base/simple_mpd_notifier_unittest.cc b/packager/mpd/base/simple_mpd_notifier_unittest.cc
index f9d34928676..5032ee89d40 100644
--- a/packager/mpd/base/simple_mpd_notifier_unittest.cc
+++ b/packager/mpd/base/simple_mpd_notifier_unittest.cc
@@ -4,6 +4,8 @@
 // license that can be found in the LICENSE file or at
 // https://developers.google.com/open-source/licenses/bsd
 
+#include "packager/mpd/base/simple_mpd_notifier.h"
+
 #include <gmock/gmock.h>
 #include <google/protobuf/util/message_differencer.h>
 #include <gtest/gtest.h>
@@ -13,7 +15,6 @@
 #include "packager/mpd/base/mock_mpd_builder.h"
 #include "packager/mpd/base/mpd_builder.h"
 #include "packager/mpd/base/mpd_options.h"
-#include "packager/mpd/base/simple_mpd_notifier.h"
 #include "packager/mpd/test/mpd_builder_test_helper.h"
 
 namespace shaka {
@@ -189,10 +190,10 @@ TEST_F(SimpleMpdNotifierTest, NotifyNewSegment) {
   const uint32_t kSegmentDuration = 100u;
   const uint64_t kSegmentSize = 123456u;
   EXPECT_CALL(*mock_representation,
-              AddNewSegment(kStartTime, kSegmentDuration, kSegmentSize));
+              AddNewSegment(kStartTime, kSegmentDuration, kSegmentSize, 1));
 
   EXPECT_TRUE(notifier.NotifyNewSegment(kRepresentationId, kStartTime,
-                                        kSegmentDuration, kSegmentSize));
+                                        kSegmentDuration, kSegmentSize, 1));
 }
 
 TEST_F(SimpleMpdNotifierTest, NotifyCueEvent) {
diff --git a/packager/mpd/base/xml/xml_node.cc b/packager/mpd/base/xml/xml_node.cc
index a231b3683fc..7bb314eec74 100644
--- a/packager/mpd/base/xml/xml_node.cc
+++ b/packager/mpd/base/xml/xml_node.cc
@@ -56,7 +56,7 @@ bool IsTimelineConstantDuration(const std::list<SegmentInfo>& segment_infos,
     return false;
 
   const SegmentInfo& first_segment = segment_infos.front();
-  if (first_segment.start_time != first_segment.duration * (start_number - 1))
+  if (first_segment.start_time / first_segment.duration != (start_number - 1))
     return false;
 
   if (segment_infos.size() == 1)
@@ -179,9 +179,8 @@ void XmlNode::SetStringAttribute(const char* attribute_name,
 void XmlNode::SetIntegerAttribute(const char* attribute_name, uint64_t number) {
   DCHECK(node_);
   DCHECK(attribute_name);
-  xmlSetProp(node_.get(),
-             BAD_CAST attribute_name,
-             BAD_CAST (base::Uint64ToString(number).c_str()));
+  xmlSetProp(node_.get(), BAD_CAST attribute_name,
+             BAD_CAST(base::Uint64ToString(number).c_str()));
 }
 
 void XmlNode::SetFloatingPointAttribute(const char* attribute_name,
@@ -437,12 +436,12 @@ bool RepresentationXmlNode::AddLiveOnlyInfo(
                                            segment_infos.front().duration);
       if (FLAGS_dash_add_last_segment_number_when_needed) {
         uint32_t last_segment_number = start_number - 1;
-        for (const auto& segment_info_element : segment_infos) 
+        for (const auto& segment_info_element : segment_infos)
           last_segment_number += segment_info_element.repeat + 1;
-	
+
         AddSupplementalProperty(
-          "http://dashif.org/guidelines/last-segment-number",
-          std::to_string(last_segment_number));	
+            "http://dashif.org/guidelines/last-segment-number",
+            std::to_string(last_segment_number));
       }
     } else {
       XmlNode segment_timeline("SegmentTimeline");
diff --git a/packager/mpd/base/xml/xml_node_unittest.cc b/packager/mpd/base/xml/xml_node_unittest.cc
index 1840765c703..870db0cbbab 100644
--- a/packager/mpd/base/xml/xml_node_unittest.cc
+++ b/packager/mpd/base/xml/xml_node_unittest.cc
@@ -4,6 +4,8 @@
 // license that can be found in the LICENSE file or at
 // https://developers.google.com/open-source/licenses/bsd
 
+#include "packager/mpd/base/xml/xml_node.h"
+
 #include <gflags/gflags.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
@@ -14,7 +16,6 @@
 #include "packager/base/logging.h"
 #include "packager/base/strings/string_util.h"
 #include "packager/mpd/base/segment_info.h"
-#include "packager/mpd/base/xml/xml_node.h"
 #include "packager/mpd/test/xml_compare.h"
 
 DECLARE_bool(segment_template_constant_duration);
@@ -57,7 +58,6 @@ TEST(XmlNodeTest, MetaTestXmlElementsEqual) {
       "  <C />\n"
       "</A>";
 
-
   // This is same as kXml1 but the attributes are reordered. Note that the
   // children are not reordered.
   static const char kXml1AttributeReorder[] =
@@ -134,9 +134,8 @@ TEST(XmlNodeTest, MetaTestXmlElementsEqual) {
 // But if it is run on <B> for the first XML, it will return "content1", but
 // for second XML will return "c".
 TEST(XmlNodeTest, MetaTestXmlEqualDifferentContent) {
-  ASSERT_FALSE(XmlEqual(
-      "<A><B>content1</B><B>content2</B></A>",
-      "<A><B>c</B><B>ontent1content2</B></A>"));
+  ASSERT_FALSE(XmlEqual("<A><B>content1</B><B>content2</B></A>",
+                        "<A><B>c</B><B>ontent1content2</B></A>"));
 }
 
 TEST(XmlNodeTest, ExtractReferencedNamespaces) {
@@ -449,31 +448,31 @@ TEST_F(LiveSegmentTimelineTest, TwoSegmentInfoWithGap) {
                   "</Representation>"));
 }
 
-TEST_F(LiveSegmentTimelineTest, LastSegmentNumberSupplementalProperty) {        
-  const uint32_t kStartNumber = 1;                                              
-  const uint64_t kStartTime = 0;                                                
-  const uint64_t kDuration = 100;                                               
-  const uint64_t kRepeat = 9;                                                   
-                                                                                
-  std::list<SegmentInfo> segment_infos = {                                      
-      {kStartTime, kDuration, kRepeat},                                         
-  };                                                                            
-  RepresentationXmlNode representation;                                         
-  FLAGS_dash_add_last_segment_number_when_needed = true;                       
-                                                                                
-  ASSERT_TRUE(                                                                  
+TEST_F(LiveSegmentTimelineTest, LastSegmentNumberSupplementalProperty) {
+  const uint32_t kStartNumber = 1;
+  const uint64_t kStartTime = 0;
+  const uint64_t kDuration = 100;
+  const uint64_t kRepeat = 9;
+
+  std::list<SegmentInfo> segment_infos = {
+      {kStartTime, kDuration, kRepeat},
+  };
+  RepresentationXmlNode representation;
+  FLAGS_dash_add_last_segment_number_when_needed = true;
+
+  ASSERT_TRUE(
       representation.AddLiveOnlyInfo(media_info_, segment_infos, kStartNumber));
-                                                                                
-  EXPECT_THAT(                                                                  
-      representation.GetRawPtr(),                                               
-      XmlNodeEqual("<Representation>"                                           
-                   "<SupplementalProperty schemeIdUri=\"http://dashif.org/"     
-                   "guidelines/last-segment-number\" value=\"10\"/>"            
-                   "  <SegmentTemplate media=\"$Number$.m4s\" "                 
-                   "                   startNumber=\"1\" duration=\"100\"/>"    
-                   "</Representation>"));                                       
-  FLAGS_dash_add_last_segment_number_when_needed = false;                                                                                                      
-}                      
+
+  EXPECT_THAT(
+      representation.GetRawPtr(),
+      XmlNodeEqual("<Representation>"
+                   "<SupplementalProperty schemeIdUri=\"http://dashif.org/"
+                   "guidelines/last-segment-number\" value=\"10\"/>"
+                   "  <SegmentTemplate media=\"$Number$.m4s\" "
+                   "                   startNumber=\"1\" duration=\"100\"/>"
+                   "</Representation>"));
+  FLAGS_dash_add_last_segment_number_when_needed = false;
+}
 
 }  // namespace xml
 }  // namespace shaka