Parse files consisting of multiple concatenated sequences.
[dirac_parser.git] / src / decoder / .svn / text-base / Schrodec.cpp.svn-base
blob95c0f473c4516be5f5dec6c489204c8dcad4876d
1 /* ***** BEGIN LICENSE BLOCK *****
3 * $Id:  $
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License
8 * Version 1.1 (the "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
14 * the specific language governing rights and limitations under the License.
16 * The Original Code is BBC Research code.
18 * The Initial Developer of the Original Code is the British Broadcasting
19 * Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 2007.
21 * All Rights Reserved.
23 * Contributor(s): Andrea Gabriellini (Original Author)
25 * Alternatively, the contents of this file may be used under the terms of
26 * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
27 * Public License Version 2.1 (the "LGPL"), in which case the provisions of
28 * the GPL or the LGPL are applicable instead of those above. If you wish to
29 * allow use of your version of this file only under the terms of the either
30 * the GPL or LGPL and not to allow others to use your version of this file
31 * under the MPL, indicate your decision by deleting the provisions above
32 * and replace them with the notice and other provisions required by the GPL
33 * or LGPL. If you do not delete the provisions above, a recipient may use
34 * your version of this file under the terms of any one of the MPL, the GPL
35 * or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
42 #include <decoder/Schrodec.hpp>
44 #include <parser/AccessUnit.hpp>
45 #include <decoder/SchroState.hpp>
47 using namespace ::dirac::decoder;
48 using namespace ::dirac::parser_project;
50 namespace  
52   IDecoder::size_type
53   getBufferSizeFroFrame ( SchroFrame* frame )
54   {
55     DIRAC_MESSAGE_ASSERT ( "frame cannot be null", 0 != frame );
56     
57     IDecoder::size_type ret = 0;
58     for (int i=0; i<3; ++i) ret += frame->components[i].length;
59     return ret;
60   }
61 } /*   */
63 //! init schro, parse and decode sequence header and obtain video format params
64 Schrodec::Schrodec  ( IDecoder::ParserAutoPtr parser
65                     , IDecoder::FrameManagerAutoPtr manager )
66 : IDecoder ( parser, manager ), numberOfDecodedFrames_ ( 0 )
68   initSchro();
69   fetchSequenceHeader();
72 Schrodec::~Schrodec() {}
74 Schrodec::VideoFormatSharedPtr                  
75 Schrodec::getVideoFormat() const
77   return videoFormat_;
80 void
81 Schrodec::createDecoder()
83   DecoderSharedPtr tmp ( schro_decoder_new(), schro_decoder_free );
84   decoder_.swap ( tmp );
85   if ( !decoder_.get() ) {
86     throw DecoderException ( "failed to create schro decoder" );
87   }
88   schro_decoder_set_skip_ratio ( decoder_.get(), 1.0 );  
91 void
92 Schrodec::initSchro()
94   schro_init();
95   createDecoder();
98 void
99 Schrodec::resetDecoder()
101   if ( decoder_.get() ) {
102     decoder_.reset();
103     createDecoder();
104     numberOfDecodedFrames_ = 0;
105     fetchSequenceHeader();
106   }
109 void
110 Schrodec::deleteBuffer ( SchroBuffer* schrobuffer, void* inputBuffer )
112   delete static_cast<dirac::decoder::IDecoder::InputBuffer*> ( inputBuffer );
115 void
116 Schrodec::createSchroBuffer(IDecoder::AU& au, SchroBuffer*& schrobuffer )
118   InputBuffer* buf = au.releaseBuffer();
119   schrobuffer = schro_buffer_new_with_data ( &(*buf)[0] , buf->size() );
120   if ( !schrobuffer ) {
121     throw DecoderException ( "failed to create input buffer for schodec" );
122   }
123   schrobuffer->priv = buf;
124   schrobuffer->free = deleteBuffer;
127 void
128 Schrodec::fetchSequenceHeader()
130   DIRAC_MESSAGE_ASSERT ( "parser cannot be null", 0 != parser_.get() );
131   DIRAC_MESSAGE_ASSERT ( "decoder cannot be null", 0 != decoder_.get() );
132   
133   AccessUnit au;
134   if ( !parser_->getNextSequenceHeader ( au ) || au.empty() ) {
135     throw DecoderException ( "failed to parser sequence header" );
136   }
138   SchroBuffer* schrobuffer = 0;
139   createSchroBuffer ( au, schrobuffer );
141   if ( SCHRO_DECODER_FIRST_ACCESS_UNIT != 
142                       schro_decoder_push ( decoder_.get(), schrobuffer ) )  {
143     throw DecoderException ( "failed to decode sequence header" );
144   }
146   VideoFormatSharedPtr tmp ( schro_decoder_get_video_format ( decoder_.get() )
147                            , free );
148   videoFormat_.swap ( tmp );
149   if ( !videoFormat_.get() ) {
150     throw DecoderException ( "failed to extract video format" );
151   }
154 void
155 Schrodec::signOff()
157   DIRAC_MESSAGE_ASSERT ( "decoder cannot be null", 0 != decoder_.get() );
158   
159   schro_decoder_push_end_of_stream ( decoder_.get() );
162 IDecoderState*                         
163 Schrodec::getDecoderState()
165   DIRAC_MESSAGE_ASSERT ( "decoder cannot be null", 0 != decoder_.get() );
166   
167   return makeSchroState   ( *this, schro_decoder_wait ( decoder_.get() ) );
170 //! parse a picture and push it in the decoder
171 void                                
172 Schrodec::pushBits() 
174   DIRAC_MESSAGE_ASSERT  ( "parser and decoder cannot be null"
175                         , 0 != parser_.get() && 0 != decoder_.get() );
176   
177   // parse a picture, but check whether we reach the end of the sequence
178   AccessUnit au;
179   do {
180     if ( !parser_->getNextAccessUnit ( au ) || au.isLastEndOfSequence()
181       || !parser_->moveCursorFwd() ) {
182       signOff();
183       return;
184     }
185   }  while ( !au.isPicture() );
186   
187   SchroBuffer* schrobuffer = 0;
188   createSchroBuffer ( au, schrobuffer );
189   
190   int it = schro_decoder_push ( decoder_.get(), schrobuffer );
191   if ( SCHRO_DECODER_ERROR == it ) {
192     throw DecoderException ( "failed to decode picture" );
193   }
196 //! static method used as a deleter for schro frame
197 void
198 Schrodec::deleteFrame ( SchroFrame* frame, void* decoder )
200   DIRAC_MESSAGE_ASSERT ( "frame cannot be null", 0 != frame );
201   DIRAC_MESSAGE_ASSERT ( "decoder cannot be null", 0 != decoder );
202   
203   static_cast<Schrodec*> ( decoder )->manager_->release 
204                   ( static_cast<pointer> ( frame->components[0].data ) );
207 //! allocate memory for a frame worth of data
208 void
209 Schrodec::setFrame()
211   DIRAC_MESSAGE_ASSERT  ( "parser, decoder and video format cannot be null"
212                         ,  0 != parser_.get() && 0 != decoder_.get()
213                         && 0 != videoFormat_.get() );
214   pointer buffer = manager_->allocate ( getFrameBufferSize( frameWidth()
215                                                           , frameHeight()
216                                                           , chromaFormat() ) );
217   SchroFrame* frame = schro_frame_new_from_data_I420  ( buffer
218                                                       , frameWidth()
219                                                       , frameHeight() );
220   schro_frame_set_free_callback ( frame, deleteFrame, this );
221   schro_decoder_add_output_picture ( decoder_.get(), frame );
224 void
225 Schrodec::pullFrameAndWrite()
227   DIRAC_MESSAGE_ASSERT  ( "decoder and manager cannot be null"
228                         , 0 != decoder_.get() && 0 != manager_.get() );
229   
230   SchroFrame* frame = schro_decoder_pull ( decoder_.get() );
231   if ( frame ) {
232     ++numberOfDecodedFrames_;
233     write ( frame );
234     schro_frame_unref ( frame );
235   }
238 bool
239 Schrodec::write ( SchroFrame* frame )
241   DIRAC_MESSAGE_ASSERT ( "frame cannot be null", 0 != frame );
242   DIRAC_MESSAGE_ASSERT ( "videoformat cannot be null", 0 != videoFormat_.get() );
243   DIRAC_MESSAGE_ASSERT ( "frame manager cannot be null", 0 != manager_.get() );
244   
245   // here we can format the data for output, if required
246   return manager_->write ( static_cast<pointer> ( frame->components[0].data )
247                         , getBufferSizeFroFrame ( frame ) );
250 void
251 Schrodec::runDecoder()
253   DIRAC_MESSAGE_ASSERT ( "decoder cannot be null", 0 != decoder_.get() );
254   
255   std::auto_ptr<IDecoderState> decoderState;
256   do {
257     std::auto_ptr<IDecoderState> tmp ( getState() );
258     decoderState = tmp; // the previous DecoderState gets deleted here
259     decoderState->doNextAction();
260   } while ( !decoderState->isEndOfSequence() );    
263 IDecoder::size_type
264 Schrodec::numberOfFrames() const
266   return numberOfDecodedFrames_;
269 Schrodec::size_type
270 Schrodec::getFrameWidth() const
272   if ( videoFormat_.get() ) {
273     return videoFormat_->width;
274   }
275   else {
276     return 0;
277   }
280 IDecoder::size_type
281 Schrodec::getFrameHeight() const
283   if ( videoFormat_.get() ) {
284     return videoFormat_->height;
285   }
286   else {
287     return 0;
288   }
291 ChromaFormat
292 Schrodec::getChromaFormat() const
294   if ( videoFormat_.get() ) {
295     switch ( videoFormat_->chroma_format ) {
296       case ( SCHRO_CHROMA_444 ) :
297         return CHROMA_444;
298         // break;
299       case ( SCHRO_CHROMA_422 ) :
300         return CHROMA_422;
301         // break;
302       case ( SCHRO_CHROMA_420 ) :
303         return CHROMA_420;
304         // break;
305       default :
306         return UNDEFINED;
307         // break;
308     }
309   }
310   else {
311     return UNDEFINED;
312   }