RDK Documentation (Open Sourced RDK Components)
fragmentcollector_progressive.cpp
Go to the documentation of this file.
1 /*
2  * If not stated otherwise in this file or this component's license file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2018 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 /**
21  * @file fragmentcollector_progressive.cpp
22  * @brief Streamer for progressive mp3/mp4 playback
23  */
24 
26 #include "priv_aamp.h"
27 #include <stdlib.h>
28 #include <string.h>
29 #include <pthread.h>
30 #include <signal.h>
31 #include <assert.h>
32 
33 /**
34  * @struct StreamWriteCallbackContext
35  * @brief Write call back functions for streamer
36  */
37 
39 {
40  bool sentTunedEvent;
41  PrivateInstanceAAMP *aamp;
42  StreamWriteCallbackContext() : aamp(NULL), sentTunedEvent(false)
43  {
44  }
45 };
46 
47 /**
48 Test Content Examples:
49 http://127.0.0.1:8080/overlay360.mp4
50 - unable to play on OSX with error:
51 /GstPipeline:AAMPGstPlayerPipeline/GstPlayBin:playbin0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/GstQTDemux:qtdemux0:
52  no 'moov' atom within the first 10 MB
53 
54 http://d3rlna7iyyu8wu.cloudfront.net/Atmos/MP4/shattered-3Mb.mp4
55 - plays on OSX but without audio
56 
57 http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4
58 - plays on OSX with video/audio
59 
60  TODO: consider harvesting fixed size chunks instead of immediately tiny ranges of bytes to gstreamer
61  TODO: consider config for required bytes to collect before starting gstreamer pipeline
62  TODO: if we can't keep up with required bandwidth we don't have luxury of ABR ramp down; need to inform app about buffering status
63  TODO: consider config for required bytes to collect after buffer runs dry before updating state
64  TODO: consider harvesting additional configurable buffer of bytes even while throttled so they are "on deck" and ready to inject
65 
66  TODO: pause/play testing
67 
68  TODO: we are not yet reporting a valid duration, either for entire stream or for each injected chunk
69  is there a nice way to get real mp4 file rate from initial headers?
70  if we can't determine mp4 logical duration, can/should we report -1 as length?
71 
72  TODO: progress reporting/testing
73  TODO: what to return for available bitrates?
74  TODO: FF/REW should be disabled, with out any available rates
75  TODO: trickplay requests must return error
76 
77  TODO: errors that can occur at tune time or mid-stream
78  TODO: extend StreamFile with applicable features from aamp->GetFile
79  TODO: profiling - stream based, not fragment based
80  */
81 
82 /**
83  * @fn StreamWriteCallback
84  * @param ptr
85  * @param size always 1, per curl documentation
86  * @param nmemb number of bytes advertised in this callback
87  * @param userdata app-specific context
88  */
89 static size_t StreamWriteCallback( void *ptr, size_t size, size_t nmemb, void *userdata )
90 {
92  struct PrivateInstanceAAMP *aamp = context->aamp;
93  //pthread_mutex_lock(&context->aamp->mLock);
94  if( context->aamp->mDownloadsEnabled)
95  {
96  // TODO: info logging is normally only done up until first frame rendered, but even so is too noisy for below, since CURL write callback yields many small chunks
97  AAMPLOG_INFO("StreamWriteCallback(%zu bytes)\n", nmemb);
98  // throttle download speed if gstreamer isn't hungry
99  aamp->BlockUntilGstreamerWantsData( NULL/*CB*/, 0.0/*periodMs*/, eMEDIATYPE_VIDEO );
100  double fpts = 0.0;
101  double fdts = 0.0;
102  double fDuration = 2.0; // HACK! //CID:113073 - Position variable initialized but not used
103  if( nmemb>0 )
104  {
105  aamp->SendStreamCopy( eMEDIATYPE_VIDEO, ptr, nmemb, fpts, fdts, fDuration);
106  if( !context->sentTunedEvent )
107  { // send TunedEvent after first chunk injected - this is hint for XRE to hide the "tuning overcard"
108  aamp->SendTunedEvent(false);
109  context->sentTunedEvent = true;
110  }
111  }
112  }
113  else
114  {
115  AAMPLOG_WARN("write_callback - interrupted\n");
116  nmemb = 0;
117  }
118  //pthread_mutex_unlock(&context->aamp->mLock);
119  return nmemb;
120 }
121 
122 
123 void StreamAbstractionAAMP_PROGRESSIVE::StreamFile( const char *uri, long *http_error )
124 { // TODO: move to main_aamp
125 
126 
127  long http_code = -1;
128  AAMPLOG_INFO("StreamFile: %s\n", uri );
129  CURL *curl = curl_easy_init();
130  if (curl)
131  {
133  context.aamp = aamp;
134  context.sentTunedEvent = false;
135 
136  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, StreamWriteCallback );
137  curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&context );
138  curl_easy_setopt(curl, CURLOPT_URL, uri );
139  curl_easy_setopt(curl, CURLOPT_USERAGENT, "aamp-progressive/1.0"); // TODO: use same user agent string normally used by AAMP
140  CURLcode res = curl_easy_perform(curl); // synchronous; callbacks allow interruption
141  if( res == CURLE_OK)
142  { // all data collected
143  curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
144  }
145  if (http_error)
146  {
147  *http_error = http_code;
148  }
149  curl_easy_cleanup(curl);
150  }
151 }
152 
153 /**
154  * @brief harvest chunks from large mp3/mp4
155  */
157 {
158  std::string contentUrl = aamp->GetManifestUrl();
159  std::string effectiveUrl;
160  long http_error;
161 
163  {
164  StreamFile( contentUrl.c_str(), &http_error );
165  }
166  else
167  {
168  // send TunedEvent after first chunk injected - this is hint for XRE to hide the "tuning overcard"
169  aamp->SendTunedEvent(false);
170  }
171 
172  while( aamp->DownloadsAreEnabled() )
173  {
174  aamp->InterruptableMsSleep( 1000 );
175  }
176 }
177 
178 /**
179  * @brief Fragment collector thread
180  * @param arg Pointer to StreamAbstractionAAMP_PROGRESSIVE object
181  * @retval void
182  */
183 static void * FragmentCollector(void *arg)
184 {
185  if(aamp_pthread_setname(pthread_self(), "aampPSFetcher"))
186  {
187  AAMPLOG_WARN("aamp_pthread_setname failed\n");
188  }
190  context->FetcherLoop();
191  return NULL;
192 }
193 
194 
195 /**
196  * @brief Initialize a newly created object.
197  */
199 {
201  aamp->CurlInit(eCURLINSTANCE_VIDEO, AAMP_TRACK_COUNT,aamp->GetNetworkProxy()); //CID:110904 - newTune bool variable initialized not used
202  aamp->IsTuneTypeNew = false;
203  std::set<std::string> mLangList; /**< emptry language list */
204  std::vector<long> bitrates; /**< empty bitrates */
205  for (int i = 0; i < AAMP_TRACK_COUNT; i++)
206  {
207  aamp->SetCurlTimeout(aamp->mNetworkTimeoutMs, (AampCurlInstance) i);
208  }
210  return retval;
211 }
212 
213 
214 /*
215 AAMPStatusType StreamAbstractionAAMP_PROGRESSIVE::Init(TuneType tuneType)
216 {
217  AAMPStatusType retval = eAAMPSTATUS_OK;
218  bool newTune = aamp->IsNewTune();
219  aamp->IsTuneTypeNew = false;
220  return retval;
221 }
222  */
223 
224 /**
225  * @brief StreamAbstractionAAMP_PROGRESSIVE Constructor
226  */
228 fragmentCollectorThreadStarted(false), fragmentCollectorThreadID(0), seekPosition(seek_pos)
229 {
230  trickplayMode = (rate != AAMP_NORMAL_PLAY_RATE);
231 }
232 
233 /**
234  * @brief StreamAbstractionAAMP_PROGRESSIVE Destructor
235  */
237 {
238 }
239 
240 /**
241  * @brief Starts streaming.
242  */
244 {
245  pthread_create(&fragmentCollectorThreadID, NULL, &FragmentCollector, this);
246  fragmentCollectorThreadStarted = true;
247 }
248 
249 /**
250  * @brief Stops streaming.
251  */
252 void StreamAbstractionAAMP_PROGRESSIVE::Stop(bool clearChannelData)
253 {
254  if(fragmentCollectorThreadStarted)
255  {
257 
258  int rc = pthread_join(fragmentCollectorThreadID, NULL);
259  if (rc != 0)
260  {
261  AAMPLOG_WARN("***pthread_join failed, returned %d\n", rc);
262  }
263  fragmentCollectorThreadStarted = false;
264 
266  }
267  }
268 
269 /**
270  * @brief Stub implementation
271  */
273 { // STUB
274 }
275 
276 /**
277  * @brief Get output format of stream.
278  */
279 void StreamAbstractionAAMP_PROGRESSIVE::GetStreamFormat(StreamOutputFormat &primaryOutputFormat, StreamOutputFormat &audioOutputFormat, StreamOutputFormat &auxAudioOutputFormat, StreamOutputFormat &subtitleOutputFormat)
280 {
281  primaryOutputFormat = FORMAT_ISO_BMFF;
282  audioOutputFormat = FORMAT_INVALID;
283  auxAudioOutputFormat = FORMAT_INVALID;
284  subtitleOutputFormat = FORMAT_INVALID;
285 }
286 
287 /**
288  * @brief Return MediaTrack of requested type
289  */
291 {
292  return NULL;//mPriv->GetMediaTrack(type);
293 }
294 
295 /**
296  * @brief Get current stream position.
297  */
299 {
300  return seekPosition;
301 }
302 
303 /**
304  * @brief Get stream information of a profile from subclass.
305  */
307 {
308  return NULL;
309 }
310 
311 /**
312  * @brief Get PTS of first sample.
313  */
315 {
316  return 0.0;
317 }
318 
319 /**
320  * @brief Get Start time PTS of first sample.
321  */
323 {
324  return 0.0;
325 }
326 
327 /**
328  * @brief Get the Buffered duration
329  */
331 {
332  return -1.0;
333 }
334 
335 /**
336  * @brief check whether initial caching data supported
337  *
338  */
340 {
341  return false;
342 }
343 
344 /**
345  * @brief Get index of profile corresponds to bandwidth
346  */
348 {
349  return 0;
350 }
351 
352 /**
353  * @brief To get the available video bitrates.
354  */
356 { // STUB
357  return std::vector<long>();
358 }
359 
360 /**
361  * @brief Gets Max Bitrate avialable for current playback.
362  */
364 { // STUB
365  return 0;
366 }
367 
368 /**
369  * @brief To get the available audio bitrates.
370  */
372 { // STUB
373  return std::vector<long>();
374 }
375 
376 /**
377  * @brief To get the available video tracks.
378  */
380 { // STUB
381  return std::vector<StreamInfo*>();
382 }
383 
384 /**
385  * @brief To get the available thumbnail tracks.
386  */
388 { // STUB
389  return std::vector<StreamInfo*>();
390 }
391 
392 /**
393  * @brief Function to set thumbnail track for processing
394  */
396 {
397  (void)thumbnailIndex; /* unused */
398  return false;
399 }
400 
401 
402 std::vector<ThumbnailData> StreamAbstractionAAMP_PROGRESSIVE::GetThumbnailRangeData(double start, double end, std::string *baseurl, int *raw_w, int *raw_h, int *width, int *height)
403 {
404  return std::vector<ThumbnailData>();
405 }
406 
407 /**
408  * @brief Stops injecting fragments to StreamSink.
409  */
411 { // STUB - discontinuity related
412 }
413 
414 /**
415  * @brief Start injecting fragments to StreamSink.
416  */
418 { // STUB - discontinuity related
419 }
420 
421 
422 
423 
424 
425 
426 
StreamAbstractionAAMP_PROGRESSIVE::StopInjection
void StopInjection(void) override
Stops injecting fragments to StreamSink.
Definition: fragmentcollector_progressive.cpp:410
PrivateInstanceAAMP::SetCurlTimeout
void SetCurlTimeout(long timeout, AampCurlInstance instance)
Set curl timeout(CURLOPT_TIMEOUT)
Definition: priv_aamp.cpp:3315
StreamAbstractionAAMP_PROGRESSIVE::GetStreamFormat
void GetStreamFormat(StreamOutputFormat &primaryOutputFormat, StreamOutputFormat &audioOutputFormat, StreamOutputFormat &auxOutputFormat, StreamOutputFormat &subtitleOutputFormat) override
Get output format of stream.
Definition: fragmentcollector_progressive.cpp:279
PrivateInstanceAAMP::SendTunedEvent
bool SendTunedEvent(bool isSynchronous=true)
Send tuned event to listeners if required.
Definition: priv_aamp.cpp:7826
StreamOutputFormat
StreamOutputFormat
Media output format.
Definition: main_aamp.h:106
StreamInfo
Structure holding the information of a stream.
Definition: StreamAbstractionAAMP.h:69
StreamAbstractionAAMP_PROGRESSIVE::IsInitialCachingSupported
bool IsInitialCachingSupported() override
check whether initial caching data supported
Definition: fragmentcollector_progressive.cpp:339
eMEDIATYPE_VIDEO
@ eMEDIATYPE_VIDEO
Definition: AampMediaType.h:39
PrivateInstanceAAMP::InterruptableMsSleep
void InterruptableMsSleep(int timeInMs)
Sleep until timeout is reached or interrupted.
Definition: priv_aamp.cpp:6771
TuneType
TuneType
Tune Typea.
Definition: priv_aamp.h:190
StreamAbstractionAAMP::aamp
PrivateInstanceAAMP * aamp
Definition: StreamAbstractionAAMP.h:727
FORMAT_INVALID
@ FORMAT_INVALID
Definition: main_aamp.h:108
FORMAT_ISO_BMFF
@ FORMAT_ISO_BMFF
Definition: main_aamp.h:110
fragmentcollector_progressive.h
Streamer for progressive mp3/mp4 playback.
PrivateInstanceAAMP::CurlInit
void CurlInit(AampCurlInstance startIdx, unsigned int instanceCount=1, std::string proxyName="")
Curl initialization function.
Definition: priv_aamp.cpp:3252
StreamAbstractionAAMP_PROGRESSIVE::SetThumbnailTrack
bool SetThumbnailTrack(int) override
Function to set thumbnail track for processing.
Definition: fragmentcollector_progressive.cpp:395
StreamAbstractionAAMP_PROGRESSIVE::DumpProfiles
void DumpProfiles(void) override
Stub implementation.
Definition: fragmentcollector_progressive.cpp:272
ISCONFIGSET
#define ISCONFIGSET(x)
Definition: AampConfig.h:84
StreamAbstractionAAMP_PROGRESSIVE::~StreamAbstractionAAMP_PROGRESSIVE
~StreamAbstractionAAMP_PROGRESSIVE()
StreamAbstractionAAMP_PROGRESSIVE Destructor.
Definition: fragmentcollector_progressive.cpp:236
StreamAbstractionAAMP_PROGRESSIVE::GetBWIndex
int GetBWIndex(long bitrate) override
Get index of profile corresponds to bandwidth.
Definition: fragmentcollector_progressive.cpp:347
AampLogManager
AampLogManager Class.
Definition: AampLogManager.h:150
FragmentCollector
static void * FragmentCollector(void *arg)
Fragment collector thread.
Definition: fragmentcollector_progressive.cpp:183
PrivateInstanceAAMP::GetManifestUrl
std::string & GetManifestUrl(void)
Get manifest URL.
Definition: priv_aamp.h:1890
PrivateInstanceAAMP::IsTuneTypeNew
bool IsTuneTypeNew
Definition: priv_aamp.h:996
StreamAbstractionAAMP_PROGRESSIVE::GetVideoBitrates
std::vector< long > GetVideoBitrates(void) override
To get the available video bitrates.
Definition: fragmentcollector_progressive.cpp:355
MediaTrack
Base Class for Media Track.
Definition: StreamAbstractionAAMP.h:159
StreamAbstractionAAMP
StreamAbstraction class of AAMP.
Definition: StreamAbstractionAAMP.h:577
StreamAbstractionAAMP_PROGRESSIVE::GetStreamInfo
StreamInfo * GetStreamInfo(int idx) override
Get stream information of a profile from subclass.
Definition: fragmentcollector_progressive.cpp:306
StreamAbstractionAAMP_PROGRESSIVE::GetStartTimeOfFirstPTS
double GetStartTimeOfFirstPTS() override
Get Start time PTS of first sample.
Definition: fragmentcollector_progressive.cpp:322
StreamAbstractionAAMP_PROGRESSIVE::Init
AAMPStatusType Init(TuneType tuneType) override
Initialize a newly created object.
Definition: fragmentcollector_progressive.cpp:198
StreamAbstractionAAMP_PROGRESSIVE::GetThumbnailRangeData
std::vector< ThumbnailData > GetThumbnailRangeData(double, double, std::string *, int *, int *, int *, int *) override
Definition: fragmentcollector_progressive.cpp:402
PrivateInstanceAAMP::SendMediaMetadataEvent
void SendMediaMetadataEvent(void)
Generate media metadata event based on parsed attribute values.
Definition: priv_aamp.cpp:8688
TrackType
TrackType
Media Track Types.
Definition: StreamAbstractionAAMP.h:48
PrivateInstanceAAMP::GetNetworkProxy
std::string GetNetworkProxy()
To get the network proxy.
Definition: priv_aamp.cpp:9079
StreamAbstractionAAMP_PROGRESSIVE
Streamer for progressive mp3/mp4 playback.
Definition: fragmentcollector_progressive.h:37
StreamAbstractionAAMP_PROGRESSIVE::Stop
void Stop(bool clearChannelData) override
Stops streaming.
Definition: fragmentcollector_progressive.cpp:252
AAMP_TRACK_COUNT
#define AAMP_TRACK_COUNT
Definition: priv_aamp.h:67
eAAMPSTATUS_OK
@ eAAMPSTATUS_OK
Definition: priv_aamp.h:207
StreamAbstractionAAMP_PROGRESSIVE::GetAvailableThumbnailTracks
std::vector< StreamInfo * > GetAvailableThumbnailTracks(void) override
To get the available thumbnail tracks.
Definition: fragmentcollector_progressive.cpp:387
StreamWriteCallbackContext
Write call back functions for streamer.
Definition: fragmentcollector_progressive.cpp:38
StreamAbstractionAAMP_PROGRESSIVE::StreamAbstractionAAMP_PROGRESSIVE
StreamAbstractionAAMP_PROGRESSIVE(AampLogManager *logObj, class PrivateInstanceAAMP *aamp, double seekpos, float rate)
StreamAbstractionAAMP_PROGRESSIVE Constructor.
Definition: fragmentcollector_progressive.cpp:227
PrivateInstanceAAMP::SendStreamCopy
void SendStreamCopy(MediaType mediaType, const void *ptr, size_t len, double fpts, double fdts, double fDuration)
API to send audio/video stream into the sink.
Definition: priv_aamp.cpp:7010
StreamAbstractionAAMP_PROGRESSIVE::GetMaxBitrate
long GetMaxBitrate(void) override
Gets Max Bitrate avialable for current playback.
Definition: fragmentcollector_progressive.cpp:363
priv_aamp.h
Private functions and types used internally by AAMP.
StreamAbstractionAAMP_PROGRESSIVE::Start
void Start() override
Starts streaming.
Definition: fragmentcollector_progressive.cpp:243
StreamAbstractionAAMP_PROGRESSIVE::GetAvailableVideoTracks
std::vector< StreamInfo * > GetAvailableVideoTracks(void) override
To get the available video tracks.
Definition: fragmentcollector_progressive.cpp:379
AampCurlInstance
AampCurlInstance
Enumeration for Curl Instances.
Definition: priv_aamp.h:156
PrivateInstanceAAMP
Class representing the AAMP player's private instance, which is not exposed to outside world.
Definition: priv_aamp.h:640
StreamAbstractionAAMP::trickplayMode
bool trickplayMode
Definition: StreamAbstractionAAMP.h:917
PrivateInstanceAAMP::BlockUntilGstreamerWantsData
void BlockUntilGstreamerWantsData(void(*cb)(void), int periodMs, int track)
Block the injector thread until the gstreanmer needs buffer/more data.
Definition: priv_aamp.cpp:3224
eCURLINSTANCE_VIDEO
@ eCURLINSTANCE_VIDEO
Definition: priv_aamp.h:158
AAMPStatusType
AAMPStatusType
AAMP Function return values.
Definition: priv_aamp.h:205
StreamAbstractionAAMP_PROGRESSIVE::GetFirstPTS
double GetFirstPTS() override
Get PTS of first sample.
Definition: fragmentcollector_progressive.cpp:314
PrivateInstanceAAMP::DownloadsAreEnabled
bool DownloadsAreEnabled(void)
Check if downloads are enabled.
Definition: priv_aamp.cpp:6752
StreamAbstractionAAMP_PROGRESSIVE::StartInjection
void StartInjection(void) override
Start injecting fragments to StreamSink.
Definition: fragmentcollector_progressive.cpp:417
PrivateInstanceAAMP::DisableDownloads
void DisableDownloads(void)
abort ongoing downloads and returns error on future downloads called while stopping fragment collecto...
Definition: priv_aamp.cpp:6741
StreamAbstractionAAMP_PROGRESSIVE::GetAudioBitrates
std::vector< long > GetAudioBitrates(void) override
To get the available audio bitrates.
Definition: fragmentcollector_progressive.cpp:371
PrivateInstanceAAMP::EnableDownloads
void EnableDownloads(void)
Enable downloads after aamp_DisableDownloads. Called after stopping fragment collector thread.
Definition: priv_aamp.cpp:6761
StreamAbstractionAAMP_PROGRESSIVE::GetBufferedDuration
double GetBufferedDuration() override
Get the Buffered duration.
Definition: fragmentcollector_progressive.cpp:330
StreamAbstractionAAMP_PROGRESSIVE::GetStreamPosition
double GetStreamPosition() override
Get current stream position.
Definition: fragmentcollector_progressive.cpp:298
PrivateInstanceAAMP::rate
float rate
Definition: priv_aamp.h:955
StreamAbstractionAAMP_PROGRESSIVE::GetMediaTrack
MediaTrack * GetMediaTrack(TrackType type) override
Return MediaTrack of requested type.
Definition: fragmentcollector_progressive.cpp:290
eAAMPConfig_UseAppSrcForProgressivePlayback
@ eAAMPConfig_UseAppSrcForProgressivePlayback
Definition: AampConfig.h:133
StreamAbstractionAAMP_PROGRESSIVE::FetcherLoop
void FetcherLoop()
harvest chunks from large mp3/mp4
Definition: fragmentcollector_progressive.cpp:156