DASH Media Packaging SDK
 All Classes Namespaces Functions Variables Typedefs Enumerator
ts_segmenter.cc
1 // Copyright 2016 Google Inc. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 
7 #include "packager/media/formats/mp2t/ts_segmenter.h"
8 
9 #include <memory>
10 
11 #include "packager/media/base/muxer_util.h"
12 #include "packager/media/base/status.h"
13 
14 namespace edash_packager {
15 namespace media {
16 namespace mp2t {
17 
18 namespace {
19 const int kTsTimescale = 90000;
20 } // namespace
21 
23  : muxer_options_(options),
24  ts_writer_(new TsWriter()),
25  pes_packet_generator_(new PesPacketGenerator()) {}
26 TsSegmenter::~TsSegmenter() {}
27 
29  if (muxer_options_.segment_template.empty())
30  return Status(error::MUXER_FAILURE, "Segment template not specified.");
31  if (!ts_writer_->Initialize(stream_info))
32  return Status(error::MUXER_FAILURE, "Failed to initialize TsWriter.");
33  if (!pes_packet_generator_->Initialize(stream_info)) {
34  return Status(error::MUXER_FAILURE,
35  "Failed to initialize PesPacketGenerator.");
36  }
37 
38  return Status::OK;
39 }
40 
42  return Flush();
43 }
44 
45 // First checks whether the sample is a key frame. If so and the segment has
46 // passed the segment duration, then flush the generator and write all the data
47 // to file.
48 Status TsSegmenter::AddSample(scoped_refptr<MediaSample> sample) {
49  const bool passed_segment_duration =
50  current_segment_total_sample_duration_ > muxer_options_.segment_duration;
51  if (sample->is_key_frame() && passed_segment_duration) {
52  Status status = Flush();
53  if (!status.ok())
54  return status;
55  }
56 
57  if (!ts_writer_file_opened_ && !sample->is_key_frame())
58  LOG(WARNING) << "A segment will start with a non key frame.";
59 
60  if (!pes_packet_generator_->PushSample(sample)) {
61  return Status(error::MUXER_FAILURE,
62  "Failed to add sample to PesPacketGenerator.");
63  }
64 
65  current_segment_total_sample_duration_ += sample->duration() / kTsTimescale;
66 
67  return WritePesPacketsToFile();
68 }
69 
70 void TsSegmenter::InjectTsWriterForTesting(scoped_ptr<TsWriter> writer) {
71  ts_writer_ = writer.Pass();
72 }
73 
75  scoped_ptr<PesPacketGenerator> generator) {
76  pes_packet_generator_ = generator.Pass();
77 }
78 
80  ts_writer_file_opened_ = value;
81 }
82 
83 Status TsSegmenter::OpenNewSegmentIfClosed(uint32_t next_pts) {
84  if (ts_writer_file_opened_)
85  return Status::OK;
86  const std::string segment_name =
87  GetSegmentName(muxer_options_.segment_template, next_pts,
88  segment_number_++, muxer_options_.bandwidth);
89  if (!ts_writer_->NewSegment(segment_name))
90  return Status(error::MUXER_FAILURE, "Failed to initilize TsPacketWriter.");
91  ts_writer_file_opened_ = true;
92  return Status::OK;
93 }
94 
95 Status TsSegmenter::WritePesPacketsToFile() {
96  while (pes_packet_generator_->NumberOfReadyPesPackets() > 0u) {
97  scoped_ptr<PesPacket> pes_packet =
98  pes_packet_generator_->GetNextPesPacket();
99 
100  Status status = OpenNewSegmentIfClosed(pes_packet->pts());
101  if (!status.ok())
102  return status;
103 
104  if (!ts_writer_->AddPesPacket(pes_packet.Pass()))
105  return Status(error::MUXER_FAILURE, "Failed to add PES packet.");
106  }
107  return Status::OK;
108 }
109 
110 Status TsSegmenter::Flush() {
111  if (!pes_packet_generator_->Flush()) {
112  return Status(error::MUXER_FAILURE,
113  "Failed to flush PesPacketGenerator.");
114  }
115  Status status = WritePesPacketsToFile();
116  if (!status.ok())
117  return status;
118 
119  // This method may be called from Finalize() so ts_writer_file_opened_ could
120  // be false.
121  if (ts_writer_file_opened_) {
122  if (!ts_writer_->FinalizeSegment()) {
123  return Status(error::MUXER_FAILURE, "Failed to finalize TsWriter.");
124  }
125  ts_writer_file_opened_ = false;
126  }
127  current_segment_total_sample_duration_ = 0.0;
128  return Status::OK;
129 }
130 
131 } // namespace mp2t
132 } // namespace media
133 } // namespace edash_packager
Status Initialize(const StreamInfo &stream_info)
Definition: ts_segmenter.cc:28
Abstract class holds stream information.
Definition: stream_info.h:26
void SetTsWriterFileOpenedForTesting(bool value)
Only for testing.
Definition: ts_segmenter.cc:79
void InjectTsWriterForTesting(scoped_ptr< TsWriter > writer)
Only for testing.
Definition: ts_segmenter.cc:70
Status AddSample(scoped_refptr< MediaSample > sample)
Definition: ts_segmenter.cc:48
void InjectPesPacketGeneratorForTesting(scoped_ptr< PesPacketGenerator > generator)
Only for testing.
Definition: ts_segmenter.cc:74
TsSegmenter(const MuxerOptions &options)
Definition: ts_segmenter.cc:22
This structure contains the list of configuration options for Muxer.
Definition: muxer_options.h:18