Ap4HintTrackReader.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:11k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /*****************************************************************
  2. |
  3. |    AP4 - Hint Track Reader
  4. |
  5. |    Copyright 2002-2005 Gilles Boccon-Gibod & Julien Boeuf
  6. |
  7. |
  8. |    This file is part of Bento4/AP4 (MP4 Atom Processing Library).
  9. |
  10. |    Unless you have obtained Bento4 under a difference license,
  11. |    this version of Bento4 is Bento4|GPL.
  12. |    Bento4|GPL is free software; you can redistribute it and/or modify
  13. |    it under the terms of the GNU General Public License as published by
  14. |    the Free Software Foundation; either version 2, or (at your option)
  15. |    any later version.
  16. |
  17. |    Bento4|GPL is distributed in the hope that it will be useful,
  18. |    but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20. |    GNU General Public License for more details.
  21. |
  22. |    You should have received a copy of the GNU General Public License
  23. |    along with Bento4|GPL; see the file COPYING.  If not, write to the
  24. |    Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  25. |    02111-1307, USA.
  26. |
  27. ****************************************************************/
  28. /*----------------------------------------------------------------------
  29. |       includes
  30. +---------------------------------------------------------------------*/
  31. #include <stdlib.h>
  32. #include <time.h>
  33. #include "Ap4HintTrackReader.h"
  34. #include "Ap4DataBuffer.h"
  35. #include "Ap4Track.h"
  36. #include "Ap4Movie.h"
  37. #include "Ap4SdpAtom.h"
  38. #include "Ap4RtpHint.h"
  39. #include "Ap4TrakAtom.h"
  40. #include "Ap4TrefTypeAtom.h"
  41. #include "Ap4TimsAtom.h"
  42. #include "Ap4Utils.h"
  43. /*----------------------------------------------------------------------
  44. |       AP4_HintTrackReader::AP4_HintTrackReader
  45. +---------------------------------------------------------------------*/
  46. AP4_HintTrackReader::AP4_HintTrackReader(AP4_Track& hint_track, 
  47.                                          AP4_Movie& movie, 
  48.                                          AP4_UI32 ssrc /* = 0 */) :
  49.     m_HintTrack(hint_track),
  50.     m_MediaTrack(NULL),
  51.     m_MediaTimeScale(0),
  52.     m_RtpSampleData(NULL),
  53.     m_Ssrc(ssrc),
  54.     m_SampleIndex(0),
  55.     m_PacketIndex(0),
  56.     m_RtpSequenceStart(0),
  57.     m_RtpTimeStampStart(0),
  58.     m_RtpTimeScale(0)
  59. {
  60.     // check the type
  61.     if (m_HintTrack.GetType() != AP4_Track::TYPE_HINT) 
  62.         throw AP4_Exception(AP4_ERROR_INVALID_TRACK_TYPE);
  63.     // get the media track
  64.     AP4_TrakAtom* hint_trak_atom = hint_track.GetTrakAtom();
  65.     AP4_Atom* atom = hint_trak_atom->FindChild("tref/hint");
  66.     if (atom != NULL) {
  67.         AP4_UI32 media_track_id = ((AP4_TrefTypeAtom*) atom)->m_TrackIds[0];
  68.         m_MediaTrack = movie.GetTrack(media_track_id);
  69.         // get the media time scale
  70.         m_MediaTimeScale = m_MediaTrack->GetMediaTimeScale();
  71.     }
  72.     // initiate random generator
  73.     srand(time(NULL));
  74.     // rtp sequence start init TODO!!
  75.     m_RtpSequenceStart = rand();
  76.     // rtp timestamp start init TODO!!
  77.     m_RtpTimeStampStart = rand();
  78.     // rtp time scale
  79.     atom = hint_trak_atom->FindChild("mdia/minf/stbl/rtp /tims");
  80.     if (atom) {
  81.         AP4_TimsAtom* tims = (AP4_TimsAtom*)atom;
  82.         m_RtpTimeScale = tims->GetTimeScale();
  83.     }
  84.     // generate a random ssrc if = 0
  85.     if (m_Ssrc == 0) {
  86.         m_Ssrc = rand();
  87.     }
  88.     // get the first sample
  89.     GetRtpSample(0);
  90. }
  91. /*----------------------------------------------------------------------
  92. |       AP4_HintTrackReader::~AP4_HintTrackReader
  93. +---------------------------------------------------------------------*/
  94. AP4_HintTrackReader::~AP4_HintTrackReader()
  95. {
  96.     delete m_RtpSampleData;
  97. }
  98. /*----------------------------------------------------------------------
  99. |       AP4_HintTrackReader::GetRtpSample
  100. +---------------------------------------------------------------------*/
  101. AP4_Result
  102. AP4_HintTrackReader::GetRtpSample(AP4_Ordinal index)
  103. {
  104.     // get the sample
  105.     AP4_Result result = m_HintTrack.GetSample(index, m_CurrentHintSample);
  106.     if (AP4_FAILED(result)) return result;
  107.     // renew the sample data
  108.     delete m_RtpSampleData;
  109.     AP4_ByteStream& rtp_data_stream = *m_CurrentHintSample.GetDataStream();
  110.     rtp_data_stream.Seek(m_CurrentHintSample.GetOffset());
  111.     m_RtpSampleData = new AP4_RtpSampleData(rtp_data_stream,
  112.                                             m_CurrentHintSample.GetSize());
  113.     // reinit the packet index
  114.     m_PacketIndex = 0;
  115.     // release the stream
  116.     rtp_data_stream.Release();
  117.     return AP4_SUCCESS;
  118. }
  119. /*----------------------------------------------------------------------
  120. |       AP4_HintTrackReader::GetCurrentTimeStampMs
  121. +---------------------------------------------------------------------*/
  122. AP4_TimeStamp
  123. AP4_HintTrackReader::GetCurrentTimeStampMs()
  124. {
  125.     return AP4_ConvertTime(m_CurrentHintSample.GetCts(), 
  126.                            m_HintTrack.GetMediaTimeScale(),
  127.                            1000);
  128. }
  129. /*----------------------------------------------------------------------
  130. |       AP4_HintTrackReader::Rewind
  131. +---------------------------------------------------------------------*/
  132. AP4_Result
  133. AP4_HintTrackReader::Rewind()
  134. {
  135.     m_SampleIndex = 0;
  136.     return GetRtpSample(m_SampleIndex);
  137. }
  138. /*----------------------------------------------------------------------
  139. |       AP4_HintTrackReader::GetSdpText
  140. +---------------------------------------------------------------------*/
  141. AP4_Result
  142. AP4_HintTrackReader::GetSdpText(AP4_String& sdp_text)
  143. {
  144.     AP4_Atom* sdp_atom = m_HintTrack.GetTrakAtom()->FindChild("udta/hnti/sdp ");
  145.     if (sdp_atom == NULL) return AP4_FAILURE;
  146.     // C cast is OK because we know the type of the atom
  147.     sdp_text = ((AP4_SdpAtom*) sdp_atom)->GetSdpText(); 
  148.     return AP4_SUCCESS;
  149. }
  150. /*----------------------------------------------------------------------
  151. |       AP4_HintTrackReader::SeekToTimeStampMs
  152. +---------------------------------------------------------------------*/
  153. AP4_Result
  154. AP4_HintTrackReader::SeekToTimeStampMs(AP4_TimeStamp desired_ts, 
  155.                                        AP4_TimeStamp& actual_ts)
  156. {
  157.     // get the sample index
  158.     AP4_Cardinal index;
  159.     AP4_Result result = m_HintTrack.GetSampleIndexForTimeStampMs(desired_ts, index);
  160.     if (AP4_FAILED(result)) return result;
  161.     // get the current sample based on the index and renew the sample data
  162.     result = GetRtpSample(index);
  163.     if (AP4_FAILED(result)) return result;
  164.     // set the actual ts
  165.     actual_ts = GetCurrentTimeStampMs();
  166.     return AP4_SUCCESS;
  167. }
  168. /*----------------------------------------------------------------------
  169. |       AP4_HintTrackReader::GetNextPacket
  170. +---------------------------------------------------------------------*/
  171. AP4_Result
  172. AP4_HintTrackReader::GetNextPacket(AP4_DataBuffer& packet_data, 
  173.                                    AP4_TimeStamp& ts_ms)
  174. {
  175.     AP4_Result result = AP4_SUCCESS;
  176.     // get the next rtp sample if needed
  177.     AP4_List<AP4_RtpPacket>* packets = &m_RtpSampleData->GetPackets();
  178.     while (m_PacketIndex == packets->ItemCount()) { // while: handle the 0 packet case
  179.         result = GetRtpSample(++m_SampleIndex);
  180.         if (AP4_FAILED(result)) return result;
  181.         packets = &m_RtpSampleData->GetPackets();
  182.     }
  183.     // get the packet
  184.     AP4_RtpPacket* packet;
  185.     result = packets->Get(m_PacketIndex++, packet);
  186.     if (AP4_FAILED(result)) return result;
  187.     // build it
  188.     result = BuildRtpPacket(packet, packet_data);
  189.     if (AP4_FAILED(result)) return result;
  190.     // set the time stamp
  191.     ts_ms = GetCurrentTimeStampMs();
  192.     return result;
  193. }
  194. /*----------------------------------------------------------------------
  195. |       AP4_HintTrackReader::BuildRtpPacket
  196. +---------------------------------------------------------------------*/
  197. AP4_Result
  198. AP4_HintTrackReader::BuildRtpPacket(AP4_RtpPacket* packet, 
  199.                                     AP4_DataBuffer& packet_data)
  200. {
  201.     // set the data size
  202.     AP4_Result result = packet_data.SetDataSize(packet->GetConstructedDataSize());
  203.     if (AP4_FAILED(result)) return result;
  204.     // now write
  205.     AP4_ByteStream* stream = 
  206.         new AP4_MemoryByteStream(packet_data.UseData(), packet_data.GetDataSize()); 
  207.     // header + ssrc
  208.     stream->WriteUI08(0x80 | (packet->GetPBit() << 5) | (packet->GetXBit() << 4));
  209.     stream->WriteUI08((packet->GetMBit() << 7) | packet->GetPayloadType());
  210.     stream->WriteUI16(m_RtpSequenceStart + packet->GetSequenceSeed());
  211.     stream->WriteUI32(m_RtpTimeStampStart + m_CurrentHintSample.GetCts() + packet->GetTimeStampOffset());
  212.     stream->WriteUI32(m_Ssrc);
  213.     AP4_List<AP4_RtpConstructor>::Item* constructors_it 
  214.         = packet->GetConstructors().FirstItem();
  215.     while (constructors_it != NULL) {
  216.         AP4_RtpConstructor* constructor = constructors_it->GetData();
  217.         // add data to the packet according to the constructor
  218.         switch (constructor->GetType()) {
  219.             case AP4_RTP_CONSTRUCTOR_TYPE_NOOP:
  220.                 // nothing to do here
  221.                 break;
  222.             case AP4_RTP_CONSTRUCTOR_TYPE_IMMEDIATE:
  223.                 result = WriteImmediateRtpData(
  224.                     (AP4_ImmediateRtpConstructor*) constructor, stream);
  225.                 if (AP4_FAILED(result)) return result;
  226.                 break;
  227.             case AP4_RTP_CONSTRUCTOR_TYPE_SAMPLE:
  228.                 result = WriteSampleRtpData(
  229.                     (AP4_SampleRtpConstructor*) constructor, stream);
  230.                 if (AP4_FAILED(result)) return result;
  231.                 break;
  232.             case AP4_RTP_CONSTRUCTOR_TYPE_SAMPLE_DESC:
  233.                 return AP4_ERROR_NOT_SUPPORTED_YET;
  234.             default:
  235.                 // unknown constructor type
  236.                 return AP4_FAILURE;
  237.         }
  238.         // iterate
  239.         constructors_it = constructors_it->GetNext();
  240.     }
  241.     // release the stream
  242.     stream->Release();
  243.     return result;
  244. }
  245. /*----------------------------------------------------------------------
  246. |       AP4_HintTrackReader::WriteImmediateRtpData
  247. +---------------------------------------------------------------------*/
  248. AP4_Result
  249. AP4_HintTrackReader::WriteImmediateRtpData(AP4_ImmediateRtpConstructor* constructor, 
  250.                                            AP4_ByteStream* data_stream)
  251. {
  252.     const AP4_DataBuffer& data_buffer = constructor->GetData();
  253.     return data_stream->Write(data_buffer.GetData(), data_buffer.GetDataSize());
  254. }
  255. /*----------------------------------------------------------------------
  256. |       AP4_HintTrackReader::WriteSampleRtpData
  257. +---------------------------------------------------------------------*/
  258. AP4_Result
  259. AP4_HintTrackReader::WriteSampleRtpData(AP4_SampleRtpConstructor* constructor, 
  260.                                         AP4_ByteStream* data_stream)
  261. {
  262.     AP4_Track* referenced_track = NULL;
  263.     if (constructor->GetTrackRefIndex() == 0xFF) {
  264.         // data is in the hint track
  265.         referenced_track = &m_HintTrack;
  266.     } else {
  267.         // check if we have a media track
  268.         if (m_MediaTrack == NULL) return AP4_FAILURE;
  269.         referenced_track = m_MediaTrack;
  270.     }
  271.     // write the sample data
  272.     AP4_Sample sample;
  273.     AP4_Result result = referenced_track->GetSample(constructor->GetSampleNum()-1, // adjust
  274.                                                     sample);
  275.     AP4_DataBuffer buffer(constructor->GetLength());
  276.     result = sample.ReadData(
  277.         buffer, constructor->GetLength(), constructor->GetSampleOffset());
  278.     if (AP4_FAILED(result)) return result;
  279.     // write the data
  280.     return data_stream->Write(buffer.GetData(), buffer.GetDataSize());
  281. }