Exemplo n.º 1
0
void mpgfile::initaudiocodeccontext(int aud)
{
  stream &S=s[audiostream(aud)];
  S.infostring="Audio ";

  {
    char number[16];
    snprintf(number,16,"%d",aud);
    S.infostring+=number;
  }

  switch (S.type)
  {
  case streamtype::mpegaudio:
    S.infostring+=" (MPEG)";
    break;
  case streamtype::ac3audio:
    S.infostring+=" (AC3)";
    break;
  default:
    S.infostring+=" (unknown)";
    break;
  }
}
Exemplo n.º 2
0
void mpgfile::savempg(muxer &mux, int start, int stop, int savedpics, int savepics, logoutput *log)
{
  if (start<0)
    start=0;
  if (start>pictures)
    start=pictures;
  if (stop<0)
    stop=0;
  if (stop>pictures)
    stop=pictures;
  if (start==stop)
    return;
  if (stop<start)
  {
    int x=start;
    start=stop;
    stop=x;
  }

  int seekpic=idx.indexnr(start);
  int framerate = mpgfile::frameratescr[idx[seekpic].getframerate()];
  bool fixedstart=true;

  if (mux.isempty())
  {
    fixedstart=false;
    mux.unsetempty();
    pts_t startpts = framerate / 300;
    for (int i=0;i<MAXAVSTREAMS;++i)
      mux.setpts(i,startpts);
  }

  pts_t videostartpts=idx[seekpic].getpts();
  pts_t videostoppts=idx[idx.indexnr(stop)].getpts();
  pts_t videooffset=videostartpts-mux.getpts(VIDEOSTREAM);
  pts_t audiopts[MAXAUDIOSTREAMS];
  pts_t audiostartpts[MAXAUDIOSTREAMS];
  pts_t audiooffset[MAXAUDIOSTREAMS];
  for(int a=0;a<MAXAUDIOSTREAMS;++a)
  {
    audiooffset[a]=videooffset;
    audiostartpts[a]=audiopts[a]=videostartpts;
  }
  pts_t shift=0;

  {
    dvbcut_off_t start_pos = idx[idx.indexnr(start)].getpos().fileposition();
    dvbcut_off_t stop_pos = idx[idx.indexnr(stop)].getpos().fileposition();
    dvbcut_off_t bytes = stop_pos - start_pos;
    pts_t delta_pts = (pts_t)(stop - start) * framerate / 300;
    double mux_rate = (double)bytes * 9e4 / (double)delta_pts;
    if (log) {
      //: Placeholder will be replaced with floating point number
      log->printinfo(QCoreApplication::translate("mpgfile", "Estimated mux rate: %1 MB/s").arg(mux_rate * 1e-6, 0, 'f', 2));
    }
  }

  while (seekpic>0 && idx[seekpic].getpts()>=videostartpts-180000)
    --seekpic;

  dvbcut_off_t tpos;
  {
    int stoppic=idx.indexnr(start);
    while (stoppic<pictures &&
           (idx[stoppic].getpts()<videostartpts+180000 || !idx[stoppic].getseqheader()))
      ++stoppic;
    tpos=idx[stoppic].getpos().packetposition();
  }

  streamhandle sh(idx[seekpic].getpos().packetposition());
  streamdata *vsd=sh.newstream(VIDEOSTREAM,s[VIDEOSTREAM].type,istransportstream());
  for (int a=0;a<MAXAUDIOSTREAMS;++a)
    if (mux.streampresent(audiostream(a)))
      sh.newstream(audiostream(a),s[audiostream(a)].type,istransportstream());

  while (sh.fileposition<tpos)
    if (streamreader(sh)<0)
      break;

  for (int a=0;a<MAXAUDIOSTREAMS;++a)
    if (streamdata *sd=sh.stream[audiostream(a)])
    {
      pts_t tpts=videostartpts-mux.getpts(VIDEOSTREAM)+mux.getpts(audiostream(a));
      sd->audio_addpts();
      uint32_t startbufferpos=sd->ptsbufferpos(tpts);
      if (startbufferpos>sd->getoffset())
        sd->discard(startbufferpos-sd->getoffset());
      sd->audio_addpts(0,true);
      startbufferpos=sd->closestptsbufferpos(tpts);
      if (startbufferpos>sd->getoffset())
        sd->discard(startbufferpos-sd->getoffset());

      pts_t apts=sd->itemlist().front().headerpts(tpts);
      audiostartpts[a]=apts;
      if (apts>=0)
      {
        if (fixedstart)
          audiooffset[a]=videooffset-tpts+apts;
        else if (tpts-apts>shift)
          shift=tpts-apts;
      }

    }

  if (!fixedstart)
  {
    videooffset-=shift;
    for(int a=0;a<MAXAUDIOSTREAMS;++a)
      audiooffset[a]=videooffset;
  }

  pts_t audiostoppts[MAXAUDIOSTREAMS];
  for(int a=0;a<MAXAUDIOSTREAMS;++a)
    audiostoppts[a]=videostoppts-videooffset+audiooffset[a];

  int firstseqhdr=nextseqheader(start);
  {
    filepos_t copystart=idx[idx.indexnr(firstseqhdr)].getpos();
    vsd->discard(vsd->fileposbufferpos(copystart)-vsd->getoffset());
  }
  bool isfirstpic=true, isfirstseq=true;
  int firstseqnr=idx[idx.indexnr(firstseqhdr)].getsequencenumber();

  if (firstseqhdr>start)
  {
    recodevideo(mux,start,firstseqhdr,videooffset,savedpics,savepics,log);
    savedpics+=firstseqhdr-start;
  }

  int copystop=stop; // first picture not to write to stream
  while (copystop<pictures && idx[idx.indexnr(copystop)].isbframe())
    ++copystop;
  copystop=idx.indexnr(copystop);

  int streampic=idx.indexnr(firstseqhdr);

  while (!log || !log->cancelled())
  {
    int packetsread;
    for (packetsread=0;packetsread<20;++packetsread)
      if (streamreader(sh)<=0)
        break;
    if (packetsread==0)
      break;

    // copy video
    if (vsd)
      for(;;)
      {
        if (streampic>=copystop)
        {
          vsd=0;
          sh.delstream(VIDEOSTREAM);
          break;
        }

        uint32_t picsize=vsd->fileposbufferpos(idx[streampic+1].getpos())-vsd->getoffset();
        if (picsize>=vsd->inbytes())
          break;

        if (!isfirstpic && idx[streampic].getseqheader())
          isfirstseq=false;
        isfirstpic=false;

        int seqoff=0;
        if (!isfirstseq || idx[streampic].getsequencenumber()>=firstseqnr)
        {
          if (isfirstseq && firstseqnr>0) // need to subtract offset from picture sequence number
          {
            uint8_t *d=(uint8_t*) vsd->getdata();

            for (unsigned int j=0;j+5<picsize;)
            {
              if (d[2]&0xfe)
                j+=3;
              else
                if (*(u_int32_t*)&d[j]==mbo32(0x00000100))
                {
                  int seqpic=(d[j+4]<<2)|((d[j+5]>>6)&0x03);
                  seqpic-=firstseqnr;
                  d[j+4]=seqpic>>2;
                  d[j+5]=(d[j+5]&0x3f)|((seqpic<<6)&0xc0);
                  break;
                }
                else
                  ++j;
            }
            seqoff=firstseqnr;
          }
          pts_t vidpts=idx[streampic].getpts()-videooffset;
          pts_t viddts=vidpts;
          if (!idx[streampic].isbframe())
          {
            viddts=mux.getdts(VIDEOSTREAM);
            mux.setdts(VIDEOSTREAM,vidpts);
          }
          if (idx[streampic].getseqheader())
          {
            int tcpic=streampic;
            while (tcpic < copystop && idx[tcpic].getsequencenumber() != seqoff)
              ++tcpic;
            pts_t tcpts=idx[tcpic].getpts()-videooffset;
            fixtimecode((uint8_t*)vsd->getdata(),picsize,tcpts);
          }
          if (!mux.putpacket(VIDEOSTREAM,vsd->getdata(),picsize,vidpts,viddts,
                             idx[streampic].isiframe() ? MUXER_FLAG_KEY:0  ))
            {
              if (log) {
                //: Placeholder will be replaced with streampic number
                log->printwarning(QCoreApplication::translate("mpgfile", "putpacket(streampic=%1) returned false").arg(streampic));
              } else {
                fprintf(stderr,"WARN: putpacket(streampic=%d) returned false\n",streampic);
              }
            }
        }
Exemplo n.º 3
0
void mpgfile::playaudio(int aud, int picture, int ms)
{
  if (aud>=audiostreams || ms==0)
    return;

  pts_t startpts=idx[idx.indexnr(picture)].getpts();
  pts_t stoppts=startpts;

  if (ms<0)
    startpts+=ms*90;
  else
    stoppts+=ms*90;

  int seekpic=idx.indexnr(picture);
  while (seekpic>0 && idx[seekpic].getpts()>=startpts-180000)
    --seekpic;
  int stopreadpic=idx.indexnr(picture);
  while (stopreadpic<pictures-1 && idx[stopreadpic].getpts()<stoppts+180000)
    ++stopreadpic;
  dvbcut_off_t stopreadpos=idx[stopreadpic].getpos().packetposition();

  streamhandle sh(idx[seekpic].getpos().packetposition());
  streamdata *sd=sh.newstream(audiostream(aud),s[audiostream(aud)].type,istransportstream());

  while (sd->empty())
  {
    if (sh.fileposition > stopreadpos || streamreader(sh)<=0)
      return; // data does not reach the point in time from which we like to start playing
    while (!sd->empty() && !sd->itemlist().begin()->headerhaspts())
      sd->pop();
  }

  for(;;)
  {
    if (sh.fileposition > stopreadpos || streamreader(sh)<=0)
      return; // data does not reach the point in time from which we like to start playing
    if (sd->empty())
      continue;

    streamdata::itemlisttype::const_iterator it=sd->itemlist().begin();
    int pop=1;
    pts_t pts=AV_NOPTS_VALUE;
    for(++it;it!=sd->itemlist().end();++it,++pop)
      if (it->headerhaspts()) //if (streamdata::headerhaspts(it->header))
      {
        pts=it->headerpts(startpts);
        break;
      }
    if (pts==(pts_t)AV_NOPTS_VALUE)
      continue;
    if (pts<=startpts)
      sd->pop(pop);
    if (pts>=startpts)
      break;
  }

  while (streamreader(sh)>0)
  {
    streamdata::itemlisttype::const_reverse_iterator it=sd->itemlist().rbegin();
    while(it!=sd->itemlist().rend())
      if (it->headerhaspts())
        break;
      else
        --it;

    if (it==sd->itemlist().rend())
      continue;

    if (it->headerpts(stoppts)>stoppts)
      break;
  }

  sd->audio_addpts();

  uint32_t startbufferpos=sd->closestptsbufferpos(startpts);
  uint32_t stopbufferpos=sd->closestptsbufferpos(stoppts);

  if (stopbufferpos>startbufferpos)
  {
    const stream &S=s[audiostream(aud)];

    if (S.type==streamtype::ac3audio)
      playaudio_ac3(sd->getdata(startbufferpos),stopbufferpos-startbufferpos);
    else
      playaudio_mp2(sd->getdata(startbufferpos),stopbufferpos-startbufferpos);
  }
}
Exemplo n.º 4
0
mpegmuxer::mpegmuxer(uint32_t audiostreammask, mpgfile &mpg, const char *filename, bool dvd,
                     int packsize_bytes, int muxrate_bitsps) :
    fd(-1), st(), muxrate(muxrate_bitsps/400), packsize(packsize_bytes), ptsoffset(0), aucounter(0),
    systemhdr(0), systemhdrlen(0), pespacket_setlength(true),scr(0)
{
    if (packsize<MINPACKSIZE)
        packsize=0;
    scrpack=int(27.e6/double(muxrate*50)*packsize+0.9999);

    st[VIDEOSTREAM]=new stream(streamtype::mpeg2video,0xe0,232<<10,232<<10,true);
    strpres[VIDEOSTREAM]=true;

    int audiobuffersize=dvd?(4<<10):(48<<10);
    for (int i=0;i<mpg.getaudiostreams();++i)
        if (audiostreammask & (1u<<i)) {
            streamtype::type t = mpg.getstreamtype(audiostream(i));
            if (t==streamtype::ac3audio)
                st[audiostream(i)]=new stream(t, 0x180+i,
                                              audiobuffersize,58<<10,true);
            /* not supported yet:
      else if (t==streamtype::dtsaudio)
        st[audiostream(i)]=new stream(t, 0x188+i,
                                      audiobuffersize,58<<10,true);
      */
            else
                st[audiostream(i)]=new stream(t, 0xc0+i,
                                              audiobuffersize,audiobuffersize,false);
            strpres[audiostream(i)]=true;
        }

    systemhdrlen=dvd ? 2034 : 24; // include DVD navigation packets if dvd set
    systemhdr = (void*) calloc(1, systemhdrlen);
    bzero(systemhdr,systemhdrlen);

    {
        systemhdr_s *value = (systemhdr_s*) systemhdr;
        *value = {
                mbo32(0x000001bb),mbo16(18),
                //1,muxrate,1,mpg.getaudiostreams(),0,0,
                htom32(0x80000100 | ((muxrate&0x3fffff)<<9) | (mpg.getaudiostreams()<<2)),
                //1,1,1,1,
                0xe1,
                //0,0x7f,
                0x7f,
                0xb9,mbo16(0xe000|232),0xb8,mbo16(0xc000|32),
                0xbd,mbo16(0xe000|58),0xbf,mbo16(0xe000|2)
        };
    }
    if (dvd) { // dvd nav packets
        *(uint32_t*)((char*)systemhdr+24)=mbo32(0x000001bf);
        *(uint16_t*)((char*)systemhdr+28)=mbo16(980);
        *(uint32_t*)((char*)systemhdr+1010)=mbo32(0x000001bf);
        *(uint16_t*)((char*)systemhdr+1014)=mbo16(1018);
    }

    // total size of all buffers: 232kB video + 4kB per mpeg audio stream
    double allbuffers(double((232<<10)+mpg.getaudiostreams()*(4<<10)));
    allbuffers*=1.05; // 5% assumed muxing overhead
    ptsoffset=pts_t(90000.*(allbuffers/50./muxrate))+90;

    if (!strncmp(filename, "pipe:", 5))
        fd = atoi(filename+5);
    else
        fd=::open(filename,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666);
}