1
0

nsvdecode.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999
  1. #include <bfc/platform/platform.h>
  2. #include <bfc/platform/strcmp.h>
  3. #include <stdio.h>
  4. #include <locale.h>
  5. #include "audiostub.h"
  6. #include "api.h"
  7. #include "main.h"
  8. #include "subtitles.h"
  9. #include "../in_nsv/resource.h"
  10. extern int config_subtitles;
  11. #ifdef __APPLE__
  12. #include <sys/time.h>
  13. #include <unistd.h>
  14. uint32_t GetTickCount()
  15. {
  16. struct timeval newtime;
  17. gettimeofday(&newtime, 0);
  18. return newtime.tv_sec*1000 + newtime.tv_usec/1000;
  19. }
  20. int MulDiv(int a, int b, int d)
  21. {
  22. return int ((int64_t)a * (int64_t)b) / (int64_t)d;
  23. }
  24. #endif
  25. class NullAudioOutput : public IAudioOutput
  26. {
  27. public:
  28. NullAudioOutput() { m_pause=0; m_pause_t=0; m_start_t=GetTickCount64(); }
  29. ~NullAudioOutput(){}
  30. int canwrite() { return m_pause ? 0 : 65536; } // returns bytes writeable
  31. void write(void *buf, int len) { }
  32. ULONGLONG getpos() { return m_pause?m_pause_t:(GetTickCount64()-m_start_t); }
  33. int isplaying(void) { return -1; }
  34. ULONGLONG getwritepos() { return getpos(); }
  35. void flush(unsigned int newtime)
  36. {
  37. if (m_pause) m_pause_t=newtime;
  38. else m_start_t = GetTickCount64()-newtime;
  39. }
  40. void pause(int pause)
  41. {
  42. if (pause && !m_pause)
  43. {
  44. m_pause_t=GetTickCount64()-m_start_t;
  45. m_pause=1;
  46. }
  47. else if (!pause && m_pause)
  48. {
  49. m_start_t = GetTickCount64()-m_pause_t;
  50. m_pause=0;
  51. m_pause_t=0;
  52. }
  53. }
  54. private:
  55. int m_pause;
  56. ULONGLONG m_pause_t;
  57. ULONGLONG m_start_t;
  58. };
  59. void NSVDecoder::pause(int pause)
  60. {
  61. if (aud_output) aud_output->pause(pause);
  62. m_paused=pause;
  63. }
  64. ULONGLONG NSVDecoder::getpos()
  65. {
  66. return aud_output ? aud_output->getpos() : 0;
  67. }
  68. unsigned int NSVDecoder::getlen()
  69. {
  70. if (!fileheader.header_size || fileheader.file_lenms == 0xFFFFFFFF)
  71. {
  72. if (!file_reader || !avg_framesize_cnt || !avg_framesize_tot) return 0xFFFFFFFF;
  73. int s=(int)file_reader->getsize();
  74. if (s == 0xFFFFFFFF) return 0xFFFFFFFF;
  75. int bytespersec=(int)((double)avg_framesize_tot/(double)avg_framesize_cnt*getFrameRate());
  76. if (!bytespersec) return 0xFFFFFFFF;
  77. return MulDiv(s,1000,bytespersec);
  78. }
  79. return fileheader.file_lenms;
  80. }
  81. void NSVDecoder::seek(unsigned int newpos)
  82. {
  83. m_need_seek=newpos;
  84. m_again=0;
  85. }
  86. int NSVDecoder::canseek()
  87. {
  88. return file_reader ? file_reader->canseek() : 0;
  89. }
  90. char *NSVDecoder::getStatus()
  91. {
  92. if (m_prebuffer) return "Buffering";
  93. return NULL;
  94. }
  95. void NSVDecoder::SetBuffering(int total_ms, int initial_ms, int after_underrun)
  96. {
  97. if (m_prebuffer) m_prebuffer=initial_ms;
  98. m_pb_init=initial_ms;
  99. m_pb_init_ur=after_underrun;
  100. m_buffer_total=total_ms;
  101. }
  102. int64_t pdReadResolution(void)
  103. {
  104. int64_t myfeq;
  105. #ifdef _WIN32
  106. LARGE_INTEGER feq;
  107. QueryPerformanceFrequency( &feq);
  108. myfeq = feq.QuadPart;
  109. #else
  110. myfeq = 1000000;
  111. #endif
  112. return myfeq;
  113. }
  114. int64_t pdReadTimer(void)
  115. {
  116. int64_t mynow;
  117. #ifdef _WIN32
  118. LARGE_INTEGER now;
  119. QueryPerformanceCounter( &now );
  120. mynow = now.QuadPart;
  121. #else
  122. struct timeval newtime;
  123. gettimeofday(&newtime,NULL);
  124. mynow = (newtime.tv_sec * 1000000) + newtime.tv_usec ;
  125. #endif
  126. return mynow;
  127. }
  128. NSVDecoder::NSVDecoder(const char *url, IVideoOutput *output, char *subtitleurl)
  129. {
  130. m_precise_seeking=1;
  131. pcm_samplerate=0;
  132. seek_dumpframes=0;
  133. seek_dumpaudiosamples=0;
  134. m_avresync_time=0;
  135. nsvbitstream_search=0;
  136. m_paused=0;
  137. m_bufstate=0;
  138. hack_l_curpos=-1;
  139. hack_l_curpos_ot=0;
  140. vid_decoder_isnotnull=1;
  141. aud_decoder_isnotnull=1;
  142. video_frames_avail=0;
  143. audio_frames_avail=0;
  144. m_buffer_total=1000; // bufferahead
  145. m_pb_init=m_prebuffer=1500; // initial prebuffer
  146. m_pb_init_ur=1500; // after underrun
  147. m_buf_memlimit=32*1024*1024;
  148. m_pan=0;
  149. m_volume=192;
  150. m_title=0;
  151. m_audio_type[0]=m_video_type[0]=0;
  152. m_out_opened=0;
  153. m_out=output;
  154. vidout_ready=0;
  155. vidout=0;
  156. vidout_type=0;
  157. vidout_time=0;
  158. vidout_codec_width=0;
  159. vidout_codec_height=0;
  160. m_url=_strdup(url);
  161. m_need_seek=~0;
  162. needkf=1;
  163. aspect=1.0;
  164. framerate_override=0.0;
  165. use_framerate_override=0;
  166. vid_decoder=NULL;
  167. aud_decoder=NULL;
  168. aud_output=NULL;
  169. framecnt=0;
  170. hdrsearched=0;
  171. file_reader=CreateReader(url);
  172. if (!file_reader) m_err="Error opening input";
  173. else m_err=NULL;
  174. m_enable_subtitles=1;
  175. m_subs_fontsize=0;
  176. m_cur_subtitle=0;
  177. if (subtitleurl && *subtitleurl) insertSubtitlesItem("From subtitle file",subtitleurl);
  178. memset(&fileheader,0,sizeof(fileheader));
  179. avg_framesize_tot=0;
  180. avg_framesize_cnt=0;
  181. avg_framesize_tot_v=0;
  182. avg_framesize_cnt_v=0;
  183. avg_framesize_tot_a=0;
  184. avg_framesize_cnt_a=0;
  185. unpacket.setAudioOut(&audiobs);
  186. unpacket.setVideoOut(&videobs);
  187. unpacket.setAuxOut(&auxbs);
  188. proTimerStart = 1;
  189. proTimerEnd = 0;
  190. profiletime = 0.00;
  191. prostart = 0.00;
  192. proend = 0.00;
  193. timeref = (float)pdReadResolution();
  194. m_again = 0;
  195. }
  196. NSVDecoder::~NSVDecoder()
  197. {
  198. if (m_out_opened) m_out->close();
  199. if (WASABI_API_MEMMGR)
  200. WASABI_API_MEMMGR->Delete(vid_decoder);
  201. else
  202. delete vid_decoder;
  203. if (WASABI_API_MEMMGR)
  204. WASABI_API_MEMMGR->Delete(aud_decoder);
  205. else
  206. delete aud_decoder;
  207. delete aud_output;
  208. delete file_reader;
  209. free(fileheader.metadata);
  210. free(fileheader.toc);
  211. free(m_url);
  212. free(m_title);
  213. }
  214. char *NSVDecoder::get_error()
  215. {
  216. return m_err;
  217. }
  218. char *NSVDecoder::get_status()
  219. {
  220. return NULL;
  221. }
  222. char *NSVDecoder::getFromMeta(char *name)
  223. {
  224. if (file_reader)
  225. {
  226. char *t=(char*)malloc(strlen(name)+8);
  227. if (t)
  228. {
  229. strcpy(t,"x-nsv-");
  230. strcat(t,name);
  231. char *v=file_reader->getheader(t);
  232. free(t);
  233. if (v) return _strdup(v);
  234. }
  235. }
  236. return nsv_getmetadata(fileheader.metadata,name);
  237. }
  238. unsigned int NSVDecoder::getFileSize()
  239. {
  240. if (file_reader) return (unsigned int)file_reader->getsize();
  241. return ~0;
  242. }
  243. int NSVDecoder::getBitrate()
  244. {
  245. if (!fileheader.header_size || !fileheader.file_lenms || !fileheader.file_lenbytes ||
  246. fileheader.file_lenms == 0xFFFFFFFF || fileheader.file_lenbytes == 0xFFFFFFFF)
  247. {
  248. if (!avg_framesize_cnt) return 0;
  249. return (int) (8.0 * getFrameRate() * (double)avg_framesize_tot / (double)avg_framesize_cnt);
  250. }
  251. return MulDiv(fileheader.file_lenbytes,8000,fileheader.file_lenms);
  252. }
  253. const char *NSVDecoder::getServerHeader(char *name)
  254. {
  255. return file_reader?file_reader->getheader(name):NULL;
  256. }
  257. void NSVDecoder::getAudioDesc(char *buf)
  258. {
  259. char *t=getAudioType();
  260. if (t && *t)
  261. {
  262. if (strcmp(t, "VLB")==0)
  263. sprintf(buf,"Dolby AAC "); // special case; make sure the user never sees "VLB" name
  264. else if (strcmp(t, "AACP")==0)
  265. sprintf(buf,"HE-AAC ");
  266. else if (strcmp(t, "AAC")==0)
  267. sprintf(buf,"AAC LC ");
  268. else
  269. sprintf(buf,"%s ",t);
  270. char *p=buf+strlen(buf);
  271. if (aud_output) aud_output->getdescstr(p);
  272. if (!*p) *--p=0;
  273. int a=(getAudioBitrate()+500)/1000;
  274. if (a) sprintf(buf+strlen(buf)," ~%d%s",a,WASABI_API_LNGSTRING(IDS_KBPS));
  275. }
  276. else *buf=0;
  277. }
  278. void NSVDecoder::getVideoDesc(char *buf)
  279. {
  280. char *t=getVideoType();
  281. if (t && *t)
  282. {
  283. int fr=(int)(getFrameRate()*100.0);
  284. sprintf(buf,"%s %dx%d@%d.%02d%s",t,getWidth(),getHeight(),fr/100,fr%100,WASABI_API_LNGSTRING(IDS_FPS));
  285. int a=(getVideoBitrate()+500)/1000;
  286. if (a) sprintf(buf+strlen(buf)," ~%d%s",a,WASABI_API_LNGSTRING(IDS_KBPS));
  287. }
  288. else *buf=0;
  289. }
  290. int NSVDecoder::getAudioBitrate()
  291. {
  292. if (!avg_framesize_cnt_a) return 0;
  293. return (int) (8.0 * getFrameRate() * (double)avg_framesize_tot_a / (double)avg_framesize_cnt_a);
  294. }
  295. int NSVDecoder::getVideoBitrate()
  296. {
  297. if (!avg_framesize_cnt_v) return 0;
  298. return (int) (8.0 * getFrameRate() * (double)avg_framesize_tot_v / (double)avg_framesize_cnt_v);
  299. }
  300. char *NSVDecoder::getTitle()
  301. {
  302. char *v=getFromMeta("TITLE");
  303. if (v)
  304. {
  305. if (!m_title || strcmp(v,m_title))
  306. {
  307. free(m_title);
  308. m_title=v;
  309. }
  310. else free(v);
  311. return m_title;
  312. }
  313. if (file_reader)
  314. {
  315. v=file_reader->gettitle();
  316. if (v) return v;
  317. }
  318. if (!m_url) return "";
  319. v=m_url+strlen(m_url);
  320. while (v >= m_url && *v != '/' && *v != '\\' && *v != '=') v--;
  321. return ++v;
  322. }
  323. void NSVDecoder::ProcessSubtitleBlock(void *data, int len)
  324. {
  325. unsigned char *dataptr=(unsigned char *)data;
  326. while (len > 2)
  327. {
  328. int len_block=(dataptr[0] | ((unsigned short)dataptr[1] << 8));
  329. dataptr += 2;
  330. len -= 2;
  331. if (len_block > len) break;
  332. SUBTITLE_INFO sti={0,};
  333. sti.language = (char *)dataptr;
  334. while (len_block > 0 && *dataptr)
  335. {
  336. dataptr++;
  337. len_block--;
  338. len--;
  339. }
  340. dataptr++;
  341. len_block--;
  342. len--;
  343. if (len_block < 1) break;
  344. sti.utf8_text = (char *)dataptr;
  345. while (len_block > 0 && *dataptr)
  346. {
  347. dataptr++;
  348. len_block--;
  349. len--;
  350. }
  351. dataptr++;
  352. len_block--;
  353. len--;
  354. if (len_block < 6) break;
  355. sti.start_frame = framecnt + video_frames_avail + (dataptr[0] | ((int)dataptr[1] << 8));
  356. dataptr+=2;
  357. len-=2;
  358. len_block-=2;
  359. sti.end_frame = sti.start_frame + (dataptr[0] | ((int)dataptr[1] << 8) | ((int)dataptr[2] << 16) | ((int)dataptr[3] << 24));
  360. dataptr+=4;
  361. len-=4;
  362. len_block-=4;
  363. // set defaults for color/position
  364. sti.xPos=128;
  365. sti.yPos=255;
  366. sti.colorRed=255;
  367. sti.colorGreen=255;
  368. sti.colorBlue=255;
  369. sti.fontSize=0;
  370. if (len_block >= 2)
  371. {
  372. sti.xPos = *dataptr++;
  373. sti.yPos = *dataptr++;
  374. len-=2;
  375. len_block-=2;
  376. if (len_block >= 3)
  377. {
  378. sti.colorRed=*dataptr++;
  379. sti.colorGreen=*dataptr++;
  380. sti.colorBlue=*dataptr++;
  381. len-=3;
  382. len_block-=3;
  383. if (len_block > 0)
  384. {
  385. sti.fontSize=(signed char) *dataptr++;
  386. len--;
  387. len_block--;
  388. }
  389. if (len_block > 0)
  390. {
  391. sti.extraData=dataptr;
  392. sti.extraDataSize=len_block;
  393. }
  394. }
  395. }
  396. Subtitles *sub=findSubtitles(sti.language);
  397. if(!sub) sub=insertSubtitlesItem(sti.language,NULL);
  398. sub->addSubtitlePacket(&sti);
  399. if (len_block > 0)
  400. {
  401. len-=len_block;
  402. dataptr+=len_block;
  403. }
  404. }
  405. }
  406. int NSVDecoder::run(int * volatile quit) // returns -1 on error, 0 if no frames processed, 1 if frames processed, 2 if underrun
  407. {
  408. int retval=0;
  409. if (!file_reader) return -1;
  410. if (!aud_decoder_isnotnull && !vid_decoder_isnotnull && vid_decoder && aud_decoder)
  411. {
  412. m_err="Codec(s) not found";
  413. return -1;
  414. }
  415. if (aud_output && vidout_ready)
  416. {
  417. ULONGLONG curpos=aud_output->getpos();
  418. if (!m_paused)
  419. {
  420. if (!audio_frames_avail && curpos == hack_l_curpos && unpacket.getEof())
  421. {
  422. hack_l_curpos=curpos;
  423. curpos += GetTickCount64() - hack_l_curpos_ot;
  424. }
  425. else
  426. {
  427. hack_l_curpos_ot=GetTickCount64();
  428. hack_l_curpos=curpos;
  429. }
  430. }
  431. if (curpos >= vidout_time && !m_prebuffer)
  432. {
  433. if (vidout)
  434. {
  435. // send this to get the flip state updated so when toggled on-the-fly it will work with nsv
  436. m_out->extended(0x1002/*VIDUSER_SET_VFLIP*/,vid_flip,0);
  437. m_out->draw(vidout);
  438. }
  439. if (m_enable_subtitles)
  440. {
  441. SubtitlesItem *it=m_subtitles.get(m_cur_subtitle);
  442. if(it && config_subtitles) {
  443. it->m_subs->setFontSizeModifier(m_subs_fontsize);
  444. m_out->drawSubtitle(it->m_subs->getSubtitle((unsigned int)aud_output->getpos(),framecnt));
  445. }
  446. if ( it && !config_subtitles )
  447. {
  448. m_out->drawSubtitle(NULL);
  449. }
  450. }
  451. vidout=0;
  452. vidout_ready=0;
  453. }
  454. }
  455. if (hdrsearched && m_need_seek!=~0 && aud_output)
  456. {
  457. unsigned int newpos=m_need_seek;
  458. m_need_seek=~0;
  459. seek_dumpaudiosamples=0;
  460. seek_dumpframes=0;
  461. if (file_reader->canseek() && file_reader->getsize() != 0xFFFFFFFF)
  462. {
  463. int nbpos;
  464. if (!fileheader.toc_size || !fileheader.toc || !fileheader.file_lenms ||
  465. !fileheader.file_lenbytes ||
  466. fileheader.file_lenms == 0xFFFFFFFF || fileheader.file_lenbytes == 0xFFFFFFFF)
  467. {
  468. int avg_framesize=avg_framesize_tot/avg_framesize_cnt;
  469. int pos_frames=(int)(newpos*getFrameRate());
  470. nbpos=fileheader.header_size+MulDiv(pos_frames,avg_framesize,1000);
  471. }
  472. else // calculate offset using TOC
  473. {
  474. if (fileheader.toc_ex) // use extended toc, find next earliest time closest
  475. {
  476. int x;
  477. double scale;
  478. if (unpacket.isValid() && getFrameRate() > 0.0001)
  479. scale=1000.0 / getFrameRate();
  480. else scale = 1000.0 / 30.0;
  481. for (x = 0; x < (int)fileheader.toc_size; x ++)
  482. {
  483. if (newpos < (unsigned int) (fileheader.toc_ex[x]*scale)) break;
  484. }
  485. unsigned int hdr[2]={0,0};
  486. if (--x >= 0)
  487. {
  488. hdr[0]=fileheader.toc[x];
  489. hdr[1]=(unsigned int) (fileheader.toc_ex[x] * scale);
  490. }
  491. //hdr[1] is the time of that keyframe
  492. if (m_precise_seeking) // precise seek
  493. {
  494. int timediff = newpos - hdr[1];
  495. double fr;
  496. if (unpacket.isValid() && getFrameRate() >= 0.0001) fr = getFrameRate() / 1000.0;
  497. else fr = 30.0 / 1000.0;
  498. seek_dumpframes=(int) (timediff * fr);
  499. seek_dumpaudiosamples=MulDiv(timediff,pcm_samplerate,1000);
  500. }
  501. else
  502. {
  503. newpos=hdr[1];
  504. }
  505. nbpos = fileheader.header_size + hdr[0];
  506. }
  507. else
  508. {
  509. double tocpos=(newpos*(double)fileheader.toc_size)/(double)fileheader.file_lenms;
  510. unsigned int tocidx=(unsigned int)tocpos;
  511. if (tocidx > fileheader.toc_size)
  512. {
  513. nbpos=fileheader.header_size + fileheader.file_lenbytes;
  514. }
  515. else
  516. {
  517. unsigned int a,b;
  518. if (tocidx<0) tocidx=0;
  519. a = fileheader.toc[tocidx];
  520. if (tocidx < fileheader.toc_size-1)
  521. b = fileheader.toc[tocidx+1];
  522. else b=fileheader.file_lenbytes;
  523. double frac=tocpos-tocidx;
  524. nbpos = fileheader.header_size + (int) (a * (1.0 - frac) + b * frac);
  525. }
  526. }
  527. }
  528. if (!file_reader->seek(nbpos))
  529. {
  530. framecnt=(int)(newpos*getFrameRate()/1000.0);
  531. unpacket.reset(0);
  532. unpacket.setEof(0);
  533. hdrsearched=1;
  534. needkf=1;
  535. m_avresync_time=0;
  536. vidout=0;
  537. vidout_ready=0;
  538. video_frames_avail=0;
  539. audio_frames_avail=0;
  540. m_prebuffer=m_pb_init;
  541. inbs.clear();
  542. audiobs.clear();
  543. videobs.clear();
  544. auxbs.clear();
  545. if (aud_output) aud_output->flush(newpos);
  546. if (aud_decoder) aud_decoder->flush();
  547. if (vid_decoder) vid_decoder->flush();
  548. }
  549. }
  550. } // end of seeking
  551. if (!hdrsearched) // search for header
  552. {
  553. readagain_header:
  554. if (quit && *quit) return 0;
  555. int ret=nsv_readheader(inbs,&fileheader);
  556. if (ret <= 0)
  557. {
  558. hdrsearched++;
  559. if (!ret)
  560. {
  561. _locale_t C_locale = WASABI_API_LNG->Get_C_NumericLocale();
  562. char *v=getFromMeta("ASPECT");
  563. if (v)
  564. {
  565. aspect=_atof_l(v,C_locale);
  566. }
  567. free(v);
  568. v=getFromMeta("FRAMERATE");
  569. if (v)
  570. {
  571. framerate_override=_atof_l(v,C_locale);
  572. if (framerate_override >= 0.01) use_framerate_override=1;
  573. free(v);
  574. }
  575. }
  576. }
  577. else
  578. {
  579. char buf[8192] = {0};
  580. size_t ret2=file_reader->read(buf,sizeof(buf));
  581. if (file_reader->iseof()) unpacket.setEof(1);
  582. if (file_reader->geterror())
  583. {
  584. m_err=file_reader->geterror();
  585. return -1;
  586. }
  587. if (ret2>0)
  588. {
  589. inbs.add(buf, (int)ret2);
  590. goto readagain_header;
  591. }
  592. }
  593. }
  594. if (!hdrsearched) return 0;
  595. // end of header search
  596. // read from source
  597. if (m_prebuffer ||
  598. (((!unpacket.isValid() || audio_frames_avail < (int)((getFrameRate() * m_buffer_total)/1000.0)) || !videobs.avail()) &&
  599. (!m_buf_memlimit || ((int)(audiobs.avail()+videobs.avail()) < m_buf_memlimit*8))))
  600. {
  601. readagain_stream:
  602. if (quit && *quit) return 0;
  603. int lavail= (int)inbs.avail();
  604. int ret=unpacket.unpacket(inbs);
  605. inbs.compact();
  606. if (ret)
  607. {
  608. if (!unpacket.isValid() && nsvbitstream_search > 8*1024*1024) // only scan for 8mb max
  609. {
  610. m_err="Error synching to NSV stream";
  611. return -1;
  612. }
  613. if (unpacket.getEof())
  614. {
  615. if (!videobs.avail() && !video_frames_avail && (!aud_output || aud_output->isplaying() <= 0)) retval=-1;
  616. // do nothing
  617. }
  618. else
  619. {
  620. char buf[8192] = {0};
  621. size_t ret2=file_reader->read(buf,sizeof(buf));
  622. if (ret2 == 0 && file_reader->iseof())
  623. {
  624. m_prebuffer=0;
  625. unpacket.setEof(1);
  626. }
  627. if (file_reader->geterror())
  628. {
  629. m_err=file_reader->geterror();
  630. return -1;
  631. }
  632. if (ret2 > 0)
  633. {
  634. nsvbitstream_search+= (int)ret2;
  635. inbs.add(buf, (int)ret2);
  636. goto readagain_stream;
  637. }
  638. }
  639. }
  640. else
  641. {
  642. nsvbitstream_search=0;
  643. video_frames_avail++;
  644. audio_frames_avail++;
  645. nsv_type_to_string(unpacket.getAudFmt(),m_audio_type);
  646. nsv_type_to_string(unpacket.getVidFmt(),m_video_type);
  647. avg_framesize_cnt++;
  648. avg_framesize_tot+=lavail- (int)((inbs.avail())/8);
  649. if (avg_framesize_tot > 0x80000000)
  650. {
  651. avg_framesize_tot/=2;
  652. avg_framesize_cnt/=2;
  653. }
  654. if (1)
  655. {
  656. //parse aux packets
  657. while (auxbs.avail() >= 8*8)
  658. {
  659. size_t thislen = auxbs.getbits(32);
  660. unsigned int thistype = auxbs.getbits(32);
  661. if (thislen > auxbs.avail()/8) break;
  662. if (thistype == NSV_MAKETYPE('S','U','B','T') ) ProcessSubtitleBlock(auxbs.getcurbyteptr(), (int)thislen);
  663. else if (thistype == NSV_MAKETYPE('A','S','Y','N'))
  664. {
  665. //if (thislen == 0) // resyncpoint
  666. {
  667. audiobs.addint(-1);
  668. audiobs.addint(framecnt+video_frames_avail);
  669. }
  670. //else // handle other form [todo]
  671. //{
  672. //}
  673. }
  674. auxbs.seek(thislen*8);
  675. }
  676. }
  677. auxbs.clear();
  678. }
  679. }
  680. if (unpacket.isValid() && !m_prebuffer && !audiobs.avail() && aud_output)
  681. {
  682. if (aud_output->isplaying()) aud_output->write(0,0);
  683. else if (!unpacket.getEof())
  684. {
  685. m_prebuffer=m_pb_init_ur+(int)((video_frames_avail/getFrameRate())*1000.0);
  686. if (m_prebuffer < m_pb_init_ur) m_prebuffer=m_pb_init_ur;
  687. if (m_prebuffer > m_pb_init_ur*3) m_prebuffer=m_pb_init_ur*3;
  688. retval=2;
  689. }
  690. }
  691. if (video_frames_avail > (int)((m_prebuffer*getFrameRate())/1000.0))
  692. {
  693. m_bufstate=256;
  694. m_prebuffer=0;
  695. }
  696. else
  697. {
  698. int a = (int) (video_frames_avail * 256.0 / ((m_prebuffer*getFrameRate())/1000.0));
  699. if (a > 255) a=255;
  700. if (a < 0) a=0;
  701. m_bufstate=a;
  702. if (m_out) m_out->notifyBufferState(a);
  703. }
  704. if (unpacket.isValid() && !vidout_ready && videobs.avail() && !m_prebuffer) // decode frame
  705. {
  706. if (!vid_decoder)
  707. {
  708. vid_flip=0;
  709. vid_decoder = CreateVideoDecoder(unpacket.getWidth(),unpacket.getHeight(),
  710. getFrameRate(),unpacket.getVidFmt(),&vid_flip,&vid_decoder_isnotnull);
  711. }
  712. int kf=0;
  713. int l=videobs.getbits(32);
  714. unsigned int local_vidout_type[3] = { 1, 0, 0 };
  715. int ret=vid_decoder->decode(needkf,videobs.getcurbyteptr(),l,&vidout,local_vidout_type,&kf);
  716. vidout_type = local_vidout_type[0];
  717. if (ret == 0)
  718. {
  719. vidout_codec_width = local_vidout_type[1];
  720. vidout_codec_height = local_vidout_type[2];
  721. }
  722. if (kf) needkf=0;
  723. video_frames_avail--;
  724. videobs.seek(l*8);
  725. videobs.compact();
  726. avg_framesize_cnt_v++;
  727. avg_framesize_tot_v+=l;
  728. if (needkf || seek_dumpframes > 0)
  729. {
  730. vidout=NULL;
  731. if (seek_dumpframes>0) seek_dumpframes--;
  732. }
  733. else
  734. {
  735. if (!m_out_opened && vid_decoder_isnotnull)
  736. {
  737. m_out->extended(0x1008/*VIDUSER_SET_THREAD_SAFE*/, 1, 0);
  738. unsigned int vidwidth = vidout_codec_width, vidheight = vidout_codec_height;
  739. if (vidwidth && vidheight)
  740. {
  741. /* if the codec provided a width/height to use */
  742. double aspect_adjust = (double)vidwidth / (double)vidheight / ((double)unpacket.getWidth() / (double)unpacket.getHeight());
  743. if (m_out->open(vidwidth,vidheight,vid_flip,aspect * aspect_adjust,vidout_type))
  744. {
  745. m_err="Error opening video output";
  746. return -1;
  747. }
  748. }
  749. else
  750. {
  751. if (m_out->open(unpacket.getWidth(),unpacket.getHeight(),vid_flip,aspect,vidout_type))
  752. {
  753. m_err="Error opening video output";
  754. return -1;
  755. }
  756. }
  757. m_out_opened=1;
  758. }
  759. vidout_ready=1;
  760. vidout_time = (unsigned int)(framecnt++ / getFrameRate() * 1000.0) + (unsigned int)m_avresync_time;
  761. int offs=unpacket.getSyncOffset() + m_out->get_latency();
  762. if ((int)vidout_time <= offs) vidout_time=0;
  763. else vidout_time-=offs;
  764. //drop the image if we're late
  765. if(aud_output && vidout_time<aud_output->getpos()) {
  766. vidout=0;
  767. vidout_ready=0;
  768. }
  769. }
  770. retval=1;
  771. }
  772. if ( ( audiobs.avail() && !m_prebuffer ) || m_again )
  773. {
  774. if (needkf)
  775. {
  776. int l=audiobs.getbits(32);
  777. if (l == -1) audiobs.seek(32); // skip over 32 bits of our audiobs info
  778. else
  779. {
  780. audiobs.seek(l*8);
  781. audio_frames_avail--;
  782. }
  783. audiobs.compact();
  784. }
  785. else // decode some audio
  786. {
  787. char pcmbuf[16384] = {0};
  788. int outbufl=512;
  789. if (!aud_decoder)
  790. {
  791. aud_decoder=CreateAudioDecoder(unpacket.getAudFmt(),&aud_decoder_isnotnull,&aud_output);
  792. if (aud_output && m_paused) aud_output->pause(1);
  793. }
  794. if (aud_output) outbufl=aud_output->canwrite();
  795. if (outbufl)
  796. {
  797. unsigned int outfmt[8] = {0};
  798. retval=1;
  799. if (outbufl > sizeof(pcmbuf)) outbufl=sizeof(pcmbuf);
  800. int inl=audiobs.getbits(32);
  801. if (inl == -1)
  802. {
  803. int vidframe=audiobs.getbits(32);
  804. if (aud_output)
  805. {
  806. ULONGLONG audpos = aud_output->getwritepos();
  807. int vidpos = (int)(vidframe / getFrameRate() * 1000.0);
  808. m_avresync_time = audpos-vidpos;
  809. }
  810. }
  811. else
  812. {
  813. int ret=aud_decoder->decode(audiobs.getcurbyteptr(), inl, pcmbuf, &outbufl, outfmt);
  814. if ( !outbufl ) m_again = 0;
  815. else m_again =1;
  816. if (ret < 1)
  817. {
  818. avg_framesize_cnt_a++;
  819. avg_framesize_tot_a+=inl;
  820. audiobs.seek(inl*8);
  821. audiobs.compact();
  822. audio_frames_avail--;
  823. }
  824. else audiobs.seek(-32);
  825. if (outbufl || outfmt[0])
  826. {
  827. if (!aud_output)
  828. {
  829. aud_output=PCMOUT_CREATE(outfmt);
  830. pcm_samplerate=outfmt[1];
  831. if (!aud_output) aud_output = new NullAudioOutput;
  832. aud_output->setvolume(m_volume);
  833. aud_output->setpan(m_pan);
  834. if (aud_output && m_paused) aud_output->pause(1);
  835. }
  836. if (outbufl)
  837. {
  838. if (seek_dumpaudiosamples)
  839. {
  840. int nch=outfmt[2];
  841. int bps=outfmt[3];
  842. int dump=seek_dumpaudiosamples*nch*(bps/8);
  843. if (dump >= outbufl)
  844. {
  845. seek_dumpaudiosamples -= outbufl/nch/(bps/8);
  846. }
  847. else // partial write
  848. {
  849. aud_output->write(pcmbuf+dump,outbufl-dump);
  850. seek_dumpaudiosamples=0;
  851. }
  852. }
  853. else aud_output->write(pcmbuf,outbufl);
  854. }
  855. }
  856. }
  857. } // if can write
  858. } //end of decode
  859. } // audiobs avail
  860. if (m_prebuffer)
  861. #ifdef _WIN32
  862. Sleep(10);
  863. #else
  864. usleep(10000);
  865. #endif
  866. return retval;
  867. }
  868. Subtitles *NSVDecoder::insertSubtitlesItem(const char *language, const char *subfile) {
  869. Subtitles *sub=new Subtitles(subfile);
  870. m_subtitles.put(new SubtitlesItem(language, sub));
  871. return sub;
  872. }
  873. Subtitles *NSVDecoder::findSubtitles(const char *language) {
  874. for(int i=0;i<m_subtitles.getlen();i++) {
  875. SubtitlesItem *s=m_subtitles.get(i);
  876. if(!_stricmp(language,s->m_language) ) return s->m_subs;
  877. }
  878. return NULL;
  879. }
  880. const char *NSVDecoder::getSubLanguage(int index) {
  881. if(index>=m_subtitles.getlen()) return NULL;
  882. return m_subtitles.get(index)->m_language;
  883. }