1 /* ***** BEGIN LICENSE BLOCK *****
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
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
36 * ***** END LICENSE BLOCK ***** */
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
;
53 getBufferSizeFroFrame ( SchroFrame
* frame
)
55 DIRAC_MESSAGE_ASSERT ( "frame cannot be null", 0 != frame
);
57 IDecoder::size_type ret
= 0;
58 for (int i
=0; i
<3; ++i
) ret
+= frame
->components
[i
].length
;
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 )
69 fetchSequenceHeader();
72 Schrodec::~Schrodec() {}
74 Schrodec::VideoFormatSharedPtr
75 Schrodec::getVideoFormat() const
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" );
88 schro_decoder_set_skip_ratio ( decoder_
.get(), 1.0 );
99 Schrodec::resetDecoder()
101 if ( decoder_
.get() ) {
104 numberOfDecodedFrames_
= 0;
105 fetchSequenceHeader();
110 Schrodec::deleteBuffer ( SchroBuffer
* schrobuffer
, void* inputBuffer
)
112 delete static_cast<dirac::decoder::IDecoder::InputBuffer
*> ( inputBuffer
);
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" );
123 schrobuffer
->priv
= buf
;
124 schrobuffer
->free
= deleteBuffer
;
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() );
134 if ( !parser_
->getNextSequenceHeader ( au
) || au
.empty() ) {
135 throw DecoderException ( "failed to parser sequence header" );
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" );
146 VideoFormatSharedPtr
tmp ( schro_decoder_get_video_format ( decoder_
.get() )
148 videoFormat_
.swap ( tmp
);
149 if ( !videoFormat_
.get() ) {
150 throw DecoderException ( "failed to extract video format" );
157 DIRAC_MESSAGE_ASSERT ( "decoder cannot be null", 0 != decoder_
.get() );
159 schro_decoder_push_end_of_stream ( decoder_
.get() );
163 Schrodec::getDecoderState()
165 DIRAC_MESSAGE_ASSERT ( "decoder cannot be null", 0 != decoder_
.get() );
167 return makeSchroState ( *this, schro_decoder_wait ( decoder_
.get() ) );
170 //! parse a picture and push it in the decoder
174 DIRAC_MESSAGE_ASSERT ( "parser and decoder cannot be null"
175 , 0 != parser_
.get() && 0 != decoder_
.get() );
177 // parse a picture, but check whether we reach the end of the sequence
180 if ( !parser_
->getNextAccessUnit ( au
) || au
.isLastEndOfSequence()
181 || !parser_
->moveCursorFwd() ) {
185 } while ( !au
.isPicture() );
187 SchroBuffer
* schrobuffer
= 0;
188 createSchroBuffer ( au
, schrobuffer
);
190 int it
= schro_decoder_push ( decoder_
.get(), schrobuffer
);
191 if ( SCHRO_DECODER_ERROR
== it
) {
192 throw DecoderException ( "failed to decode picture" );
196 //! static method used as a deleter for schro frame
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
);
203 static_cast<Schrodec
*> ( decoder
)->manager_
->release
204 ( static_cast<pointer
> ( frame
->components
[0].data
) );
207 //! allocate memory for a frame worth of data
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()
216 , chromaFormat() ) );
217 SchroFrame
* frame
= schro_frame_new_from_data_I420 ( buffer
220 schro_frame_set_free_callback ( frame
, deleteFrame
, this );
221 schro_decoder_add_output_picture ( decoder_
.get(), frame
);
225 Schrodec::pullFrameAndWrite()
227 DIRAC_MESSAGE_ASSERT ( "decoder and manager cannot be null"
228 , 0 != decoder_
.get() && 0 != manager_
.get() );
230 SchroFrame
* frame
= schro_decoder_pull ( decoder_
.get() );
232 ++numberOfDecodedFrames_
;
234 schro_frame_unref ( frame
);
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() );
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
) );
251 Schrodec::runDecoder()
253 DIRAC_MESSAGE_ASSERT ( "decoder cannot be null", 0 != decoder_
.get() );
255 std::auto_ptr
<IDecoderState
> decoderState
;
257 std::auto_ptr
<IDecoderState
> tmp ( getState() );
258 decoderState
= tmp
; // the previous DecoderState gets deleted here
259 decoderState
->doNextAction();
260 } while ( !decoderState
->isEndOfSequence() );
264 Schrodec::numberOfFrames() const
266 return numberOfDecodedFrames_
;
270 Schrodec::getFrameWidth() const
272 if ( videoFormat_
.get() ) {
273 return videoFormat_
->width
;
281 Schrodec::getFrameHeight() const
283 if ( videoFormat_
.get() ) {
284 return videoFormat_
->height
;
292 Schrodec::getChromaFormat() const
294 if ( videoFormat_
.get() ) {
295 switch ( videoFormat_
->chroma_format
) {
296 case ( SCHRO_CHROMA_444
) :
299 case ( SCHRO_CHROMA_422
) :
302 case ( SCHRO_CHROMA_420
) :