29 Harvestor::Harvestor() : mMasterHarvestorThreadID(),
30 mSlaveHarvestorThreadID(),
37 std::map<std::thread::id, HarvestProfileDetails> Harvestor::mHarvestInfo = std::map<std::thread::id, HarvestProfileDetails>();
38 std::vector<std::thread::id> Harvestor::mHarvestThreadId(0);
40 bool Harvestor::mHarvestReportFlag =
false;
41 std::string Harvestor::mHarvestPath =
"";
42 char Harvestor::exePathName[PATH_MAX] =
"";
47 char harvestCmd[mHarvestCommandLength] = {
'\0'};
48 bool slaveFlag =
false;
50 Harvestor::mPlayerInstanceAamp = playerInstanceAamp;
52 int len = strlen(cmd) - 8;
53 strncpy(harvestCmd, cmd+8, len);
55 if(memcmp(harvestCmd,
"harvestMode=Master",18) == 0)
57 printf(
"%s:%d: thread create:MasterHarvestor thread\n", __FUNCTION__, __LINE__);
59 mMasterHarvestorThreadID = std::thread (&Harvestor::masterHarvestor, harvestCmd);
61 catch (std::exception& e)
63 printf(
"%s:%d: Error at thread create:MasterHarvestor thread : %s\n", __FUNCTION__, __LINE__, e.what());
66 else if(memcmp(harvestCmd,
"harvestMode=Slave",17) == 0)
68 printf(
"%s:%d: thread create:SlaveHarvestor thread\n", __FUNCTION__, __LINE__);
70 mSlaveHarvestorThreadID = std::thread (&Harvestor::slaveHarvestor, harvestCmd);
71 }
catch (std::exception& e)
73 printf(
"%s:%d: Error at thread create:SlaveHarvestor thread : %s\n", __FUNCTION__, __LINE__, e.what());
78 printf(
"[AAMPCLI] Invalid harvest command %s\n", cmd);
81 if (mMasterHarvestorThreadID.joinable())
83 mMasterHarvestorThreadID.join();
86 if (mSlaveHarvestorThreadID.joinable())
88 mSlaveHarvestorThreadID.join();
94 void Harvestor::masterHarvestor(
void * arg)
96 char * cmd = (
char *)arg;
97 std::map<std::string, std::string> cmdlineParams;
98 std::vector<std::string> params;
99 std::stringstream ss(cmd);
101 long currentAudioBitrate = 0,currentVideoBitrate = 0,currentIFrameBitrate = 0;
103 int videoThreadId = 0;
104 int audioThreadId = 0;
106 if(aamp_pthread_setname(pthread_self(),
"MasterHarvestor"))
108 printf(
"%s:%d: aamp_pthread_setname failed\n",__FUNCTION__,__LINE__);
111 mHarvestor.getExecutablePath();
113 while(std::getline(ss, item,
' ')) {
114 params.push_back(item);
117 params.push_back(
"harvestCountLimit=9999999");
118 params.push_back(
"harvestConfig=65535");
119 params.push_back(
"defaultBitrate=9999999");
120 params.push_back(
"defaultBitrate4K=9999999");
121 params.push_back(
"abr");
122 params.push_back(
"suppressDecode=true");
124 for(std::string param : params)
126 mHarvestor.mPlayerInstanceAamp->mConfig.
ProcessConfigText(param, AAMP_DEV_CFG_SETTING);
127 mHarvestor.mPlayerInstanceAamp->mConfig.
DoCustomSetting(AAMP_DEV_CFG_SETTING);
129 std::size_t delimiterPos = param.find(
"=");
131 if(delimiterPos != std::string::npos)
133 cmdlineParams[ param.substr(0, delimiterPos) ] = param.substr(delimiterPos + 1);
137 if(cmdlineParams.find(
"harvestUrl") != cmdlineParams.end())
139 mHarvestor.mPlayerInstanceAamp->
Tune(cmdlineParams[
"harvestUrl"].c_str());
141 Harvestor::mHarvestPath = cmdlineParams[
"harvestPath"];
143 mHarvestor.mReportThread = std::thread(&Harvestor::startHarvestReport, &mHarvestor, (
char *) cmdlineParams[
"harvestUrl"].c_str());
144 }
catch(std::exception& e)
146 printf(
"%s:%d: Error at thread create: startHarvestReport thread : %s\n",__FUNCTION__,__LINE__, e.what());
149 std::string iFrameCommand;
150 if(Harvestor::exePathName[0] !=
'\0')
152 iFrameCommand.append(Harvestor::exePathName);
157 if(cmdlineParams.find(
"harvestPath") != cmdlineParams.end())
159 iFrameCommand = iFrameCommand+
" harvestPath="+cmdlineParams[
"harvestPath"];
162 printf(
"%s:%d: Start process of IFrame command %s \n",__FUNCTION__,__LINE__,iFrameCommand.c_str());
164 pIframe = popen(iFrameCommand.c_str(),
"r");
168 puts(
"Can't connect to bc");
174 mHarvestor.mSlaveIFrameThread = std::thread(&Harvestor::slaveDataOutput, pIframe);
175 }
catch (std::exception& e)
177 printf(
"%s:%d: Error at thread create: slaveDataOutput thread : %s\n",__FUNCTION__,__LINE__, e.what());
183 printf(
"%s:%d: Sucessfully launched harvest for IFrame\n",__FUNCTION__,__LINE__);
188 currentVideoBitrate = mHarvestor.mPlayerInstanceAamp->
GetVideoBitrate();
189 currentAudioBitrate = mHarvestor.mPlayerInstanceAamp->
GetAudioBitrate();
191 std::vector<long> cacheVideoBitrates,cacheAudioBitrates,cacheTextTracks;
196 std::vector<long> tempVideoBitrates,tempAudioBitrates;
197 std::vector<long> diffVideoBitrates,diffAudioBitrates;
198 long tempIFrameBitrate,cacheIFrameBitrate;
208 printf(
"%s:%d: Tune stopped\n",__FUNCTION__,__LINE__);
209 mHarvestor.mPlayerInstanceAamp->
Tune(cmdlineParams[
"harvestUrl"].c_str());
213 std::sort(tempAudioBitrates.begin(), tempAudioBitrates.end());
216 std::sort(tempVideoBitrates.begin(), tempVideoBitrates.end());
218 std::vector<long>::iterator position = std::find(tempVideoBitrates.begin(), tempVideoBitrates.end(), mHarvestor.mPlayerInstanceAamp->
GetVideoBitrate());
219 if (position != tempVideoBitrates.end())
220 tempVideoBitrates.erase(position);
222 if (cacheVideoBitrates.size() == 0)
224 diffVideoBitrates = tempVideoBitrates;
228 for (
long tempVideoBitrate: tempVideoBitrates)
230 if ( ! (std::find(cacheVideoBitrates.begin(), cacheVideoBitrates.end(), tempVideoBitrate) != cacheVideoBitrates.end()) )
232 diffVideoBitrates.push_back(tempVideoBitrate);
237 if (cacheAudioBitrates.size() == 0)
239 diffAudioBitrates = tempAudioBitrates;
243 for (
long tempAudioBitrate: tempAudioBitrates)
245 if ( ! (std::find(cacheAudioBitrates.begin(), cacheAudioBitrates.end(), tempAudioBitrate) != cacheAudioBitrates.end()) )
247 diffAudioBitrates.push_back(tempAudioBitrate);
252 if(diffVideoBitrates.size())
254 for(
auto bitrate:diffVideoBitrates)
259 std::string videoCommand;
260 if(Harvestor::exePathName[0] !=
'\0' )
262 videoCommand.append(Harvestor::exePathName);
267 if(cmdlineParams.find(
"harvestPath") != cmdlineParams.end())
269 videoCommand = videoCommand+
" harvestPath="+cmdlineParams[
"harvestPath"];
272 printf(
"%s:%d: Start process of video command %s \n",__FUNCTION__,__LINE__,videoCommand.c_str());
274 p = popen(videoCommand.c_str(),
"r");
278 puts(
"Can't connect to bc");
279 printf(
"%s:%d: Process fails ",__FUNCTION__,__LINE__);
283 bool failed = false ;
285 mHarvestor.mSlaveVideoThreads[videoThreadId] = std::thread(&Harvestor::slaveDataOutput, p);
286 }
catch (std::exception& e)
288 printf(
"%s:%d: Error at thread create: slaveDataOutput thread : %s\n",__FUNCTION__,__LINE__, e.what());
294 printf(
"%s:%d: Sucessfully launched harvest for video bitrate = %ld\n",__FUNCTION__,__LINE__,bitrate );
301 cacheVideoBitrates = tempVideoBitrates;
304 if(diffAudioBitrates.size())
306 for(
auto bitrate:diffAudioBitrates)
311 std::string audioCommand;
312 if(Harvestor::exePathName[0] !=
'\0' )
314 audioCommand.append(Harvestor::exePathName);
317 audioCommand = audioCommand +
" harvest harvestMode=Slave harvestUrl="+cmdlineParams[
"harvestUrl"]+
" harvestCountLimit=9999999"+
" harvestConfig="+std::to_string(
getHarvestConfigForMedia(
eMEDIATYPE_AUDIO))+
" abr suppressDecode=true defaultBitrate="+std::to_string(bitrate);
319 if(cmdlineParams.find(
"harvestPath") != cmdlineParams.end())
321 audioCommand = audioCommand+
" harvestPath="+cmdlineParams[
"harvestPath"];
324 printf(
"%s:%d: Start process Audio command %s \n",__FUNCTION__,__LINE__,audioCommand.c_str());
325 p = popen(audioCommand.c_str(),
"r");
329 puts(
"Can't connect to bc");
335 mHarvestor.mSlaveAudioThreads[audioThreadId] = std::thread (&Harvestor::slaveDataOutput, p);
336 }
catch (std::exception& e)
338 printf(
"%s:%d: Error at thread create: slaveDataOutput thread : %s\n",__FUNCTION__,__LINE__, e.what());
344 printf(
"%s:%d: Sucessfully launched harvest for audio bitrate = %ld\n ",__FUNCTION__,__LINE__,bitrate );
350 cacheAudioBitrates = tempAudioBitrates;
354 if (mHarvestor.mReportThread.joinable())
356 mHarvestor.mReportThread.join();
359 if (mHarvestor.mSlaveIFrameThread.joinable())
361 mHarvestor.mSlaveIFrameThread.join();
364 for(
int i = 0; i < videoThreadId; i++)
366 if (mHarvestor.mSlaveVideoThreads[i].joinable())
368 mHarvestor.mSlaveVideoThreads[i].join();
372 for(
int i =0; i < audioThreadId; i++)
374 if(mHarvestor.mSlaveAudioThreads[i].joinable())
376 mHarvestor.mSlaveAudioThreads[i].join();
382 printf(
"%s:%d: harvestUrl not found\n",__FUNCTION__,__LINE__);
388 void Harvestor::slaveHarvestor(
void * arg)
390 char * cmd = (
char *)arg;
391 std::map<std::string, std::string> cmdlineParams;
392 std::vector<std::string> params;
393 std::stringstream ss(cmd);
394 std::string item,harvestUrl;
396 if(aamp_pthread_setname(pthread_self(),
"SlaveHarvestor"))
398 printf(
"%s:%d: SlaveHarvestor_thread aamp_pthread_setname failed\n",__FUNCTION__,__LINE__);
401 while(std::getline(ss, item,
' ')) {
402 params.push_back(item);
405 params.push_back(
"suppressDecode=true");
407 for(std::string param : params)
410 mHarvestor.mPlayerInstanceAamp->mConfig.
ProcessConfigText(param, AAMP_DEV_CFG_SETTING);
411 mHarvestor.mPlayerInstanceAamp->mConfig.
DoCustomSetting(AAMP_DEV_CFG_SETTING);
413 std::size_t delimiterPos = param.find(
"=");
415 if(delimiterPos != std::string::npos)
417 cmdlineParams[ param.substr(0, delimiterPos) ] = param.substr(delimiterPos + 1);
422 int harvestConfig = 0;
425 mHarvestor.mPlayerInstanceAamp->
Tune(cmdlineParams[
"harvestUrl"].c_str());
430 mHarvestor.mPlayerInstanceAamp->
SetRate(rate);
440 printf(
"%s:%d: Tune completed exiting harvesting mode\n",__FUNCTION__,__LINE__);
446 mHarvestor.mPlayerInstanceAamp->
Tune(cmdlineParams[
"harvestUrl"].c_str());
451 mHarvestor.mPlayerInstanceAamp->
SetRate(rate);
460 void Harvestor::slaveDataOutput(
void * arg)
464 char buffer[500] = {
'\0'};
465 if(aamp_pthread_setname(pthread_self(),
"SlaveOutput"))
467 printf(
"%s:%d: slaveDataOutput aamp_pthread_setname failed\n",__FUNCTION__, __LINE__);
472 if (fgets(buffer, 500, pipe) != NULL)
474 mHarvestor.getHarvestReportDetails(buffer);
475 printf(
"%s:%d: [0x%p] %s",__FUNCTION__, __LINE__,pipe,buffer);
482 long Harvestor::getNumberFromString(std::string buffer)
484 std::stringstream strm;
490 if(std::stringstream(tempStr) >> value)
501 void Harvestor::startHarvestReport(
char * harvesturl)
505 std::string filename;
506 std::string errorFilename;
508 filename = Harvestor::mHarvestPath+
"/HarvestReport.txt";
509 errorFilename = Harvestor::mHarvestPath+
"/HarvestErrorReport.txt";
511 fp = fopen(filename.c_str(),
"w");
515 printf(
"Error opening the file %s\n", filename.c_str());
519 fprintf(fp,
"Harvest Profile Details\n\n");
520 fprintf(fp,
"Harvest url : %s\n",harvesturl);
521 fprintf(fp,
"Harvest mode : Master\n");
524 Harvestor::mHarvestReportFlag =
true;
526 errorfp = fopen(errorFilename.c_str(),
"w");
530 printf(
"Error opening the file %s\n", errorFilename.c_str());
534 fprintf(errorfp,
"Harvest Error Report\n\n");
535 fprintf(errorfp,
"Harvest url : %s\n",harvesturl);
540 bool Harvestor::getHarvestReportDetails(
char *buffer)
542 char *harvestPath = NULL;
544 std::thread::id threadId;
546 std::map<std::thread::id, HarvestProfileDetails>::iterator itr;
548 memset(&l_harvestProfileDetails,
'\0',
sizeof(l_harvestProfileDetails));
549 threadId = std::this_thread::get_id();
551 if(mHarvestInfo.find(threadId) == mHarvestInfo.end())
553 mHarvestInfo.insert( std::make_pair(threadId, l_harvestProfileDetails) );
554 mHarvestThreadId.push_back(threadId);
557 itr = mHarvestInfo.find(threadId);
559 if ((itr->second.harvestConfig == 0) && (strstr(buffer,
"harvestConfig -") != NULL))
561 token = strstr(buffer,
"harvestConfig -");
563 itr->second.harvestConfig = getNumberFromString(token);
565 if(itr->second.harvestConfig == 193)
566 strcpy(itr->second.media,
"IFrame");
568 if(itr->second.harvestConfig == 161)
569 strcpy(itr->second.media,
"Video");
571 if(itr->second.harvestConfig == 2)
572 strcpy(itr->second.media,
"Audio");
575 if ((itr->second.bitrate == 0) && (strstr(buffer,
"defaultBitrate -") != NULL))
577 token = strstr(buffer,
"defaultBitrate -");
578 itr->second.bitrate = getNumberFromString(token);
581 if (strstr(buffer,
"harvestCountLimit:") != NULL)
583 token = strstr(buffer,
"harvestCountLimit:");
584 itr->second.harvestFragmentsCount = getNumberFromString(token);
587 if ((strstr(buffer,
"error") != NULL) || (strstr(buffer,
"File open failed") != NULL) )
589 writeHarvestErrorReport(itr->second,buffer);
593 if ( (itr->second.harvestEndFlag ==
false) && (strstr(buffer,
"EndOfStreamReached") != NULL))
595 writeHarvestEndReport(itr->second,buffer);
596 itr->second.harvestEndFlag =
true;
606 std::string errorFilename;
607 errorFilename = Harvestor::mHarvestPath+
"/HarvestErrorReport.txt";
609 errorfp = fopen(errorFilename.c_str(),
"a");
613 printf(
"Error opening the file %s\n", errorFilename.c_str());
617 if (strstr(buffer,
"error") != NULL)
620 fprintf(errorfp,
"Error : %s",buffer);
623 if (strstr(buffer,
"File open failed") != NULL)
626 fprintf(errorfp,
"Failed : %s",buffer);
635 std::string filename;
636 int harvestCountLimit = 0;
638 filename = Harvestor::mHarvestPath+
"/HarvestReport.txt";
639 fp = fopen(filename.c_str(),
"a");
643 printf(
"Error opening the file %s\n", filename.c_str());
656 void Harvestor::harvestTerminateHandler(
int signal)
659 if((Harvestor::mHarvestReportFlag ==
true) && (!mHarvestThreadId.empty()))
662 std::string filename;
663 int harvestCountLimit = 0;
665 filename = Harvestor::mHarvestPath+
"/HarvestReport.txt";
666 fp = fopen(filename.c_str(),
"a");
670 printf(
"Error opening the file %s\n", filename.c_str());
674 for(
auto item: mHarvestThreadId)
676 auto itr = mHarvestInfo.find(item);
678 if((itr != mHarvestInfo.end()) && (itr->second.harvestEndFlag ==
false))
681 itr->second.harvestFragmentsCount = harvestCountLimit - itr->second.harvestFragmentsCount;
683 fprintf(fp,
"\nMedia : %s\nBitrate : %lu\nTotal fragments count : %d\nError fragments count : %d\nFailure fragments count : %d\n",itr->second.media,itr->second.bitrate,itr->second.harvestFragmentsCount,itr->second.harvesterrorCount,itr->second.harvestFailureCount);
685 itr->second.harvestEndFlag =
true;
692 printf(
"%s:%d: Signal handler\n",__FUNCTION__, __LINE__);
698 void Harvestor::getExecutablePath()
700 realpath(PROC_SELF_EXE, Harvestor::exePathName);
705 void Harvestor::getExecutablePath()
707 char rawPathName[PATH_MAX];
708 uint32_t rawPathSize = (uint32_t)
sizeof(rawPathName);
710 if(!_NSGetExecutablePath(rawPathName, &rawPathSize))
712 realpath(rawPathName, Harvestor::exePathName);