Hi everybody,

Although my problem concerning the compilation of libschroedinger 1.0-7 on
Windows has not been resolved yet (see the last mail I sent to this list), I
managed to get to work a video streaming application using libschroedinger
on Linux. So far, I am able to receive the stream and decode it, but, as I
decode, I get strange and very unpleasant video artifacts at my decoder's
output, i.e. the image will turn all grey (after maybe 100 - 130 decoded
frames) and will only be updated after a few other incoming frames have been
decoded then will turn grey again and so on...

I outputed the pictures number and I noticed that the artifacts would happen
when one picture is missing (e.g. 101, 102, 104) or when I get the same
picture's number twice (e.g. 101, 102, 102, 103, etc.) Last thing: I get
from time to time this message outputed from the schroedinger's API: "SCHRO:
ERROR: schrodecoder.c(3275): schro_decoder_reference_add: auto-retiring
reference picture".

Since I'm really bugged out and that I cannot see what I'm doing wrong, I'm
new to this codec and I mostly followed the implementations done in the
API's examples, ffmpeg and VLC, I'm asking for your help to know where these
artifacts are coming from or if I'm doing something wrong with the
implementation, as I pasted at the end of the mail.

Here's how I work to encode my frames to stream to the client :

/************************************/
initialize();

...
// encoding routine
linkDataToEncoderInput();
encode();
getEncoderOutput();
SendOnNetwork();
/************************************/
... and here's how I implemented those functions:

bool SchroedingerEncoder::initializeEncoder(const unsigned int width,
                                            const unsigned int height){

    width_ = width;
    height_ = height;

    // Must be called before all other schroedinger functions.
    schro_init();

    if(encoder_)
        schro_encoder_free (encoder_);
    encoder_ = schro_encoder_new();

    if (!encoder_){
       cerr << "Unrecoverable Error: schro_encoder_new failed." << endl;
       return false;
    }

    format_ = schro_encoder_get_video_format(encoder_);
    format_->width = width;
    format_->height = height;
    format_->frame_rate_numerator = 25;
    format_->frame_rate_denominator = 1;

    schro_encoder_setting_set_double(encoder_, "rate_control",

SCHRO_ENCODER_RATE_CONTROL_CONSTANT_BITRATE);
    // bitrate of 2 Mb...
    schro_encoder_setting_set_double(encoder_,
                                     "bitrate",
                                     2000000);

    /* FIXME: Signal range hardcoded to 8-bit data until both
libschroedinger
     * and libdirac support other bit-depth data.
     * ???? */
    schro_video_format_set_std_signal_range(format_,
SCHRO_SIGNAL_RANGE_8BIT_VIDEO);

    schro_encoder_set_video_format(encoder_, format_);

    free (format_);
    schro_encoder_start(encoder_);

    cout << "Initialize done !" << endl;

    return true;
}


void SchroedingerEncoder::linkEncoderInput(void* inputData){


    frame_ = schro_frame_new_from_data_I420 (inputData, width_, height_);

}

void* SchroedingerEncoder::getEncoderOutput(){
    return buffer_->data;
}

int SchroedingerEncoder::encodeFrame(){

    int go = 1;
    int encodedBytes = 0;
    int nDecodableFrames;
    int parseCode;

    // Push next frame to the encoder for it to encode
    schro_encoder_push_frame(encoder_, frame_);

    while(go){
        SchroStateEnum encoderState;
        encoderState = schro_encoder_wait(encoder_);

        switch(encoderState){
            case SCHRO_STATE_HAVE_BUFFER:

                // The encoder has an image to retrieve

                buffer_ = schro_encoder_pull(encoder_, &nDecodableFrames);
                if(buffer_->length <= 0){
                    cerr << "Error: length of buffer <= 0 !" << endl;
                    return buffer_->length;
                }
                parseCode = buffer_->data[4];

                if (SCHRO_PARSE_CODE_IS_INTRA(parseCode) &&
                    SCHRO_PARSE_CODE_IS_REFERENCE(parseCode)){
                    // key frame !
                }

                encodedBytes = buffer_->length;
                cout << "encodedBytes: " << encodedBytes << endl;
                go = 0;
                break;
            case SCHRO_STATE_END_OF_STREAM:
                schro_encoder_end_of_stream (encoder_);
                cout << "End of Stream..testing.." << endl;
                go = 0;
                break;

            case SCHRO_STATE_NEED_FRAME:
                break;

            case SCHRO_STATE_AGAIN:
                break;
        }
    }

    return encodedBytes;
}

Same pattern for my decoder:

/************************************/
initialize();

// decoding routine
receiveFrameFromServer();
decodeFrame();
linkToDecoderOutput();
displayOutput();

/************************************/

Decoder's functions implementation:
bool SchroedingerDecoder::initializeDecoder(cadens::DecoderStats* stats){

    // Must be called prior using other schroedinger functions.
    schro_init();

    // Creating new decoded object
    decoder_ = schro_decoder_new();

    // The default skip ratio is 1.0, indicating that all pictures should be
decoded.
    // A skip ratio of 0.0 indicates that no pictures should be decoded
    schro_decoder_set_skip_ratio(decoder_, 1.0);

    if(!decoder_){
        cerr << "Error: Cannot create new schroedinger decoder object..." <<
endl;
        return false;
    }

    // Setting the statistics object to compute decoded bytes and / or fps
    this->fpsStats_ = stats;

    return true;
}

void SchroedingerDecoder::setVideoFormat(SchroDecoder* decoder){
    // Getting video format from decoder object
    format_ = schro_decoder_get_video_format(decoder);

    if(width_ != format_->width || height_ != format_->height){
        // Setting new dimensions values
        width_ = format_->width;
        height_ = format_->height;

        if(resizeWindow_)
            resizeWindow_->resizeWindow(width_, height_);
        else{
            // No resizeWindow function was defined...
            cerr << "resizeWindow function was not defined." << endl;
        }
    }
}


int SchroedingerDecoder::decodeFrame(char* buffer, int bufferSize){
    int decode = 1;
    int decoderState = 0;
    int decodedBytes = 0;
    int pictureNumber = 0;

    if(bufferSize == 0){
        schro_decoder_push_end_of_stream(decoder_);
    }
    else{
        // Creating new buffer from the data
        buffer_ = schro_buffer_new_with_data(buffer, bufferSize);
    }

    if(schro_decoder_push_ready (decoder_) == TRUE){
        decoderState = schro_decoder_push (decoder_, buffer_);
        if (decoderState == SCHRO_DECODER_FIRST_ACCESS_UNIT) {
            setVideoFormat(decoder_);
            return bufferSize;
        }
    }

    while(decode){
        decoderState = schro_decoder_autoparse_wait(decoder_);

        switch(decoderState){
            case SCHRO_DECODER_NEED_BITS:
                decode = 0;
                break;
            case SCHRO_DECODER_NEED_FRAME:
                // Creating new frame of format I420 (8 bits depth)
                frame_ = schro_frame_new_and_alloc (NULL,
SCHRO_FRAME_FORMAT_U8_420 ,width_, height_);
                if(!frame_){
                    cerr << "Error: Was not able to allocate picture for
decoder." << endl;
                    return -1;
                }
                schro_decoder_add_output_picture (decoder_, frame_);

                break;
            case SCHRO_DECODER_OK:
                cout << "picture number: " <<
schro_decoder_get_picture_number(decoder_) << endl;
                schro_decoder_set_earliest_frame (decoder_,
pictureNumber++);

                // means the decoder is O.K., we will be able to link the
output
                frame_ = schro_decoder_pull (decoder_);

                // updates statistics here... number of frames received,
time taken, etc.

                fpsStats_->increaseFrames();
                pictureNumber_ = schro_decoder_get_picture_number(decoder_);
                decodedBytes =  buffer_->length;

                decode = 0;
                break;
            case SCHRO_DECODER_EOS:
              cout << "got eos" << endl;
              decode = 0;
              break;
            case SCHRO_DECODER_ERROR:
                return -1;
                break;
            case SCHRO_DECODER_FIRST_ACCESS_UNIT:
                setVideoFormat(decoder_);
                return bufferSize;
            default:
                cerr << "Unknown schroedinger decoder state : " <<
decoderState << endl;
                break;
        }
    }

    return decodedBytes;
}

void SchroedingerDecoder::linkDecoderOutput(unsigned char** outputBuffer,
int numberOfPlanes,
                          int* pitch){
    if(frame_ != 0){
        for(int i = 0; i < numberOfPlanes; i++){
           memcpy(outputBuffer[i], frame_->components[i].data,
frame_->components[i].length);
        }
    }
}

Any inputs on this would be greatly appreciated. Thank you very much for
your assistance.

Regards,

Jérôme
------------------------------------------------------------------------------
Throughout its 18-year history, RSA Conference consistently attracts the
world's best and brightest in the field, creating opportunities for Conference
attendees to learn about information security's most important issues through
interactions with peers, luminaries and emerging and established companies.
http://p.sf.net/sfu/rsaconf-dev2dev
_______________________________________________
Schrodinger-devel mailing list
Schrodinger-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/schrodinger-devel

Reply via email to