Example #1
0
  virtual bool GetVideoInformation(unsigned int &width, unsigned int &height) override
  {
    if (pictureId == pictureIdPrev)
      return false;
    pictureIdPrev = pictureId;

    if (AP4_AvcSampleDescription *avc = AP4_DYNAMIC_CAST(AP4_AvcSampleDescription, sample_description))
    {
      AP4_Array<AP4_DataBuffer>& buffer = avc->GetPictureParameters();
      AP4_AvcPictureParameterSet pps;
      for (unsigned int i(0); i < buffer.ItemCount(); ++i)
      {
        if (AP4_SUCCEEDED(AP4_AvcFrameParser::ParsePPS(buffer[i].GetData(), buffer[i].GetDataSize(), pps)) && pps.pic_parameter_set_id == pictureId)
        {
          buffer = avc->GetSequenceParameters();
          AP4_AvcSequenceParameterSet sps;
          for (unsigned int i(0); i < buffer.ItemCount(); ++i)
          {
            if (AP4_SUCCEEDED(AP4_AvcFrameParser::ParseSPS(buffer[i].GetData(), buffer[i].GetDataSize(), sps)) && sps.seq_parameter_set_id == pps.seq_parameter_set_id)
            {
              sps.GetInfo(width, height);
              return true;
            }
          }
          break;
        }
      }
    }
    return false;
  };
int8_t Mp4Writer::WriteFile(int frameRate)
{
    // frameRate should be in frames/second

    // adjust the sample CTS/DTS offsets based on the sample orders
        if (m_sample_orders.ItemCount() > 1) {
            unsigned int start = 0;
            for (unsigned int i=1; i<=m_sample_orders.ItemCount(); i++) {
                if (i == m_sample_orders.ItemCount() || m_sample_orders[i].m_DisplayOrder == 0) {
                    // we got to the end of the GOP, sort it by display order
                    mp_sample_storage->SortSamples(&m_sample_orders[start], i-start);
                    start = i;
                }
            }
        }
        unsigned int max_delta = 0;
        for (unsigned int i=0; i<m_sample_orders.ItemCount(); i++) {
            if (m_sample_orders[i].m_DecodeOrder > i) {
                unsigned int delta =m_sample_orders[i].m_DecodeOrder-i;
                if (delta > max_delta) {
                    max_delta = delta;
                }
            }
        }
        for (unsigned int i=0; i<m_sample_orders.ItemCount(); i++) {
            mp_sample_table->UseSample(m_sample_orders[i].m_DecodeOrder).SetCts(1000ULL*(AP4_UI64)(i+max_delta));
        }

        // check the video parameters
        AP4_AvcSequenceParameterSet* sps = NULL;
        for (unsigned int i=0; i<=AP4_AVC_SPS_MAX_ID; i++) {
            if (m_parser.GetSequenceParameterSets()[i]) {
                sps = m_parser.GetSequenceParameterSets()[i];
                break;
            }
        }
        if (sps == NULL) {
            m_errorMsg = "ERROR: no sequence parameter set found in video";
            return -1;
        }
        unsigned int video_width = 0;
        unsigned int video_height = 0;
        sps->GetInfo(video_width, video_height);


        // collect the SPS and PPS into arrays
        AP4_Array<AP4_DataBuffer> sps_array;
        for (unsigned int i=0; i<=AP4_AVC_SPS_MAX_ID; i++) {
            if (m_parser.GetSequenceParameterSets()[i]) {
                sps_array.Append(m_parser.GetSequenceParameterSets()[i]->raw_bytes);
            }
        }
        AP4_Array<AP4_DataBuffer> pps_array;
        for (unsigned int i=0; i<=AP4_AVC_PPS_MAX_ID; i++) {
            if (m_parser.GetPictureParameterSets()[i]) {
                pps_array.Append(m_parser.GetPictureParameterSets()[i]->raw_bytes);
            }
        }

        // setup the video the sample descripton
        AP4_AvcSampleDescription* sample_description =
            new AP4_AvcSampleDescription(AP4_SAMPLE_FORMAT_AVC1,
                                         video_width,
                                         video_height,
                                         24,
                                         "h264",
                                         sps->profile_idc,
                                         sps->level_idc,
                                         sps->constraint_set0_flag<<7 |
                                         sps->constraint_set1_flag<<6 |
                                         sps->constraint_set2_flag<<5 |
                                         sps->constraint_set3_flag<<4,
                                         4,
                                         sps_array,
                                         pps_array);
        mp_sample_table->AddSampleDescription(sample_description);

        // TODO: set frame rate here
        m_frameRate = frameRate * 1000;

        AP4_UI32 movie_timescale      = 1000;
        AP4_UI32 media_timescale      = m_frameRate;
        AP4_UI64 video_track_duration = AP4_ConvertTime(1000*mp_sample_table->GetSampleCount(), media_timescale, movie_timescale);
        AP4_UI64 video_media_duration = 1000*mp_sample_table->GetSampleCount();

        // create a video track
        AP4_Track* track = new AP4_Track(AP4_Track::TYPE_VIDEO,
                                         mp_sample_table,
                                         0,                    // auto-select track id
                                         movie_timescale,      // movie time scale
                                         video_track_duration, // track duration
                                         m_frameRate,          // media time scale
                                         video_media_duration, // media duration
                                         "und",                // language
                                         video_width<<16,      // width
                                         video_height<<16      // height
                                         );

        // update the brands list
        m_brands.Append(AP4_FILE_BRAND_AVC1);


        mp_movie->AddTrack(track);




        // open the output
            AP4_Result result;
            AP4_ByteStream* output = NULL;
            result = AP4_FileByteStream::Create(m_outputFilename.c_str(),
                                                AP4_FileByteStream::STREAM_MODE_WRITE, output);
            if (AP4_FAILED(result)) {
                m_errorMsg = "ERROR: cannot open output file";
                return -1;
            }

            // create a multimedia file
            AP4_File file(mp_movie);

            // set the file type
            file.SetFileType(AP4_FILE_BRAND_MP42, 1, &m_brands[0], m_brands.ItemCount());

            // write the file to the output
            AP4_FileWriter::Write(file, *output);

            // cleanup
            output->Release();


}