Parse files consisting of multiple concatenated sequences.
[dirac_parser.git] / src / decoder / Diracdec.cpp
blobeec7656deef8f5e9c727d68552faed70b873af8a
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 #include <iostream>
40 #ifdef HAVE_CONFIG_H
41 #include "config.h"
42 #endif
44 #include <decoder/Diracdec.hpp>
45 #include <decoder/DiracState.hpp>
48 using namespace ::dirac::decoder;
49 using ::dirac::parser_project::AccessUnit;
51 Diracdec::Diracdec ( IDecoder::ParserAutoPtr parser
52 , IDecoder::FrameManagerAutoPtr manager )
53 : IDecoder ( parser, manager ), numberOfDecodedFrames_ ( 0 )
54 , canPushBits_ ( true ), eos_ ( false )
56 yuv_[0] = yuv_[1] = yuv_[2] = static_cast<pointer> ( 0 );
57 initDirac();
58 fetchSequenceHeader();
59 setFrame();
62 Diracdec::~Diracdec()
64 delete [] yuv_[0];
67 void
68 Diracdec::initDirac()
70 const int VERBOSE_MODE = 0; // set to 1 if you wish to log messages to stdout
71 DecoderSharedPtr tmp ( dirac_decoder_init ( VERBOSE_MODE )
72 , dirac_decoder_close );
73 if ( !tmp.get() ) {
74 throw DecoderException ( "failed to create dirac decoder" );
76 decoder_.swap ( tmp );
79 void
80 Diracdec::fetchSequenceHeader()
82 AccessUnit au;
83 if ( !parser_->getNextSequenceHeader ( au ) || au.empty() ) {
84 throw DecoderException ( "Dirac decoder: failed to parser sequence header" );
86 dirac_buffer ( decoder_.get(), const_cast<AU::pointer> ( au.begin() )
87 , const_cast<AU::pointer> ( au.end() ) );
88 if ( !parser_->moveCursorFwd() ) {
89 throw DecoderException ( "Dirac decoder: failed to parse access unit" );
91 if ( !parser_->getNextAccessUnit ( au ) || au.empty() ) {
92 throw DecoderException ( "Dirac decoder: failed to parse access unit" );
94 dirac_buffer ( decoder_.get(), const_cast<AU::pointer> ( au.begin() )
95 , const_cast<AU::pointer> ( au.end() ) );
96 // dirac_buffer ( decoder_.get(), aux, aux + 16 ); // FIXME
97 if ( STATE_SEQUENCE != dirac_parse ( decoder_.get() ) ) {
98 throw DecoderException ( "Dirac decoder: failed to decode sequence header" );
102 void
103 Diracdec::resetDecoder()
105 delete [] yuv_[0];
106 canPushBits_ = true;
107 eos_ = false;
108 numberOfDecodedFrames_ = 0;
109 decoder_.reset();
110 initDirac();
111 fetchSequenceHeader();
112 setFrame();
115 //! push an access unit into dirac's input buffer
116 //! \r true if successful, false if end of stream
117 void
118 Diracdec::pushBits()
120 DIRAC_MESSAGE_ASSERT ( "parser and decoder cannot be null", 0 != parser_.get()
121 && 0 != decoder_.get() );
122 AccessUnit au;
123 if ( parser_->getNextAccessUnit ( au ) ) {
124 if ( canPushBits_ ) {
125 dirac_buffer ( decoder_.get(), const_cast<AU::pointer> ( au.begin() )
126 , const_cast<AU::pointer> ( au.end() ) );
128 if ( au.isLastEndOfSequence() || !parser_->moveCursorFwd() ) {
129 if ( !canPushBits_ ) eos_ = true;
130 canPushBits_ = false;
133 else {
134 if ( !canPushBits_ ) eos_ = true;
135 else canPushBits_ = false;
139 void
140 Diracdec::setFrame()
142 DIRAC_MESSAGE_ASSERT ( "parser and decoder cannot be null"
143 , 0 != parser_.get() && 0 != decoder_.get() );
144 size_type bufferSize = getFrameBufferSize ( frameWidth(), frameHeight()
145 , chromaFormat() );
146 if ( !bufferSize )
147 throw DecoderException ( "failed to create frame buffer" );
148 yuv_[0] = new value_type [ bufferSize ];
149 yuv_[1] = yuv_[0] + frameWidth() * frameHeight();
150 size_type chromaWidth = decoder_->src_params.chroma_width,
151 chromaHeight = decoder_->src_params.chroma_height;
152 yuv_[2] = yuv_[1] + chromaWidth * chromaHeight;
153 dirac_set_buf ( decoder_.get(), yuv_, NULL );
156 void
157 Diracdec::pullFrameAndWrite()
159 DIRAC_MESSAGE_ASSERT ( "decoder and frame manager cannot be null"
160 , 0 != decoder_.get() && 0 != manager_.get() );
161 if ( !decoder_->fbuf || !decoder_->fbuf->buf[0] ) {
162 throw
163 DecoderException ( "Dirac decoder: invalid frame buffer in dirac decoder" );
165 ++numberOfDecodedFrames_;
166 writeFrame();
169 void
170 Diracdec::writeFrame()
172 size_type count = getFrameBufferSize ( frameWidth(), frameHeight()
173 , chromaFormat() );
174 // this is a safe cast
175 pointer buffer = const_cast<pointer> ( manager_->allocate ( count ) );
176 memcpy(static_cast<void*> ( buffer ), yuv_[0], count );
177 manager_->write ( buffer, count );
178 manager_->release ( buffer );
181 IDecoder::size_type
182 Diracdec::getFrameWidth() const
184 DIRAC_MESSAGE_ASSERT ( "decoder cannot be null", 0 != decoder_.get() );
185 return decoder_->src_params.width;
188 IDecoder::size_type
189 Diracdec::getFrameHeight() const
191 DIRAC_MESSAGE_ASSERT ( "decoder cannot be null", 0 != decoder_.get() );
192 return decoder_->src_params.height;
195 ::dirac::decoder::ChromaFormat
196 Diracdec::getChromaFormat() const
198 DIRAC_MESSAGE_ASSERT ( "decoder cannot be null", 0 != decoder_.get() );
199 switch ( decoder_->src_params.chroma ) {
200 case ( format444 ) :
201 return CHROMA_444;
202 // break;
203 case ( format422 ) :
204 return CHROMA_422;
205 // break;
206 case ( format420 ) :
207 return CHROMA_420;
208 // break;
209 default :
210 return UNDEFINED;
211 // break;
215 void
216 Diracdec::runDecoder()
218 DIRAC_MESSAGE_ASSERT ( "decoder cannot be null", 0 != decoder_.get() );
220 std::auto_ptr<IDecoderState> decoderState;
221 do {
222 std::auto_ptr<IDecoderState> tmp ( getState() );
223 decoderState = tmp;
224 decoderState->doNextAction();
225 } while ( !decoderState->isEndOfSequence() );
228 IDecoder::size_type
229 Diracdec::numberOfFrames() const
231 return numberOfDecodedFrames_;
234 IDecoderState*
235 Diracdec::getDecoderState()
237 DIRAC_MESSAGE_ASSERT ( "decoder cannot be null", 0 != decoder_.get() );
239 return makeDiracState ( *this, dirac_parse ( decoder_.get() ) );
242 void
243 Diracdec::signOff()
245 // do nothing