Exemple #1
0
static PassRefPtr<Evas_Object> readImageFromStdin(Evas* evas, long imageSize)
{
    OwnArrayPtr<unsigned char> imageBuffer = adoptArrayPtr(new unsigned char[imageSize]);
    if (!imageBuffer)
        abortWithErrorMessage("cannot allocate image");

    const size_t bytesRead = fread(imageBuffer.get(), 1, imageSize, stdin);
    if (!bytesRead)
        return PassRefPtr<Evas_Object>();

    Evas_Object* image = evas_object_image_filled_add(evas);
    evas_object_image_colorspace_set(image, EVAS_COLORSPACE_ARGB8888);
    evas_object_image_memfile_set(image, imageBuffer.get(), bytesRead, 0, 0);

    resizeEcoreEvasIfNeeded(image);

    return adoptRef(image);
}
void CalaosCameraView::requestCompleted()
{
    if (single_frame)
    {
        evas_object_image_memfile_set(camImage, &buffer[0], buffer.size(), NULL, NULL);

        Evas_Load_Error err = evas_object_image_load_error_get(camImage);
        if (err != EVAS_LOAD_ERROR_NONE)
            cErrorDom("camera") << "could not load image. error string is \"%s\"" << evas_load_error_str(err);
    }

    if (format_error)
        return;

    EcoreTimer::singleShot(0, [=]()
    {
        if (!single_frame)
            cWarningDom("camera") << "Restarting request to camera...";
        play();
    });
}
void CalaosCameraView::processData()
{
    if (!formatDetected)
    {
        //first frame, we need to look for the boundary
        //and for content-type/content-length if present
        if (buffer.size() < 4)
            return; //need more data

        if (buffer[0] != '-' || buffer[1] != '-')
        {
            //try to detect of the data is directly the jpeg picture
            if (buffer[0] == 0xFF && buffer[1] == 0xD8)
            {
                cWarningDom("camera") << "Data seems to be a single frame.";
                single_frame = true;
            }
            else
            {
                cWarningDom("camera") << "Wrong start of frame, give up!";
                format_error = true;
            }

            formatDetected = true;
            return;
        }

        //search for the line end after the boundary to get the boundary text
        int end, next;
        if (!readEnd(2, end, next))
        {
            if (buffer.size() > 500)
            {
                cWarningDom("camera") << "Boundary not found, give up!";
                format_error = true;
            }

            return; //need more data;
        }

        //get boundary
        boundary = string((char *)&buffer[0], end);

        cDebugDom("camera") << "Found boundary \"" << boundary << "\"";

        int i = next;
        while (readEnd(next, end, next))
        {
            int len = end - i;

            if (len == 0)
            {
                //line is empty, data starts now
                nextDataStart = next;
                formatDetected = true;
                scanpos = 0;
                break;
            }

            if (len > 15)
            {
                string s((char *)&buffer[i], len);
                if (Utils::strStartsWith(s, "Content-Length", Utils::CaseInsensitive))
                {
                    Utils::from_string(s.substr(15), nextContentLength);
                    cDebugDom("camera") << "Found content length header: \"" << nextContentLength << "\"";
                    //nextContentLength = -1; //to test code without content-length header
                }
            }

            i = next;
        }

        if (!formatDetected)
        {
            cWarningDom("camera") << "need more data...";
            return;
        }
    }

    if (formatDetected && !single_frame)
    {
        //we should be positionned at the start of data
        //small check to be sure
        if (buffer.size() <= nextDataStart)
        {
            cWarningDom("camera") << "need more data...";
            return;
        }

        if (!(buffer[nextDataStart] == 0xFF && buffer[nextDataStart + 1] == 0xD8))
        {
            cWarningDom("camera") << "Wrong image data.";
            format_error = true;

            EcoreTimer::singleShot(0, [=]()
            {
                cDebugDom("camera") << "Cancel stream";
                ecore_con_url_free(ecurl);
                ecurl = nullptr;
            });

            return;
        }

        if (nextContentLength >= 0)
        {
            //the content-length is known, fast path
            if ((int)buffer.size() < nextContentLength + nextDataStart + 2)
                return; //need more data

            cDebugDom("camera") << "Set new frame";

            evas_object_image_memfile_set(camImage, &buffer[nextDataStart], nextContentLength, NULL, NULL);
            //evas_object_image_size_get(camImage, &w, &h);

            if (buffer[nextDataStart + nextContentLength] == '\r') //assume a \n always follows \r
                nextContentLength += 2;
            else if (buffer[nextDataStart + nextContentLength] == '\n')
                nextContentLength += 1;

            //remove unused data from buffer
            auto iter = buffer.begin();
            buffer.erase(iter, iter + (nextDataStart + nextContentLength));

            //reset for next frame
            nextContentLength = -1;
            formatDetected = false;
            nextDataStart = 0;
            scanpos = 0;
        }
        else
        {
            uint i = 0;
            cDebugDom("camera") << "scanpos: " << scanpos;
            for (i = nextDataStart + scanpos;
                 i < buffer.size() - boundary.length();i++)
            {
                if (buffer[i] == '-' && buffer[i + 1] == '-' &&
                    !boundary.compare(0, boundary.length(), (const char *)&buffer[i], boundary.length()))
                {
                    //boundary found
                    //check for newline between boundary and data
                    nextContentLength = i - nextDataStart;
                    if (buffer[i - 2] == '\r')
                        nextContentLength -= 2;
                    else if (buffer[i - 1] == '\n')
                        nextContentLength -= 1;

                    evas_object_image_memfile_set(camImage, &buffer[nextDataStart], nextContentLength, NULL, NULL);
                    //evas_object_image_size_get(camImage, &w, &h);

                    if (buffer[nextDataStart + nextContentLength] == '\r') //assume a \n always follows \r
                        nextContentLength += 2;
                    else if (buffer[nextDataStart + nextContentLength] == '\n')
                        nextContentLength += 1;

                    //remove unused data from buffer
                    auto iter = buffer.begin();
                    buffer.erase(iter, iter + (nextDataStart + nextContentLength));

                    //reset for next frame
                    nextContentLength = -1;
                    formatDetected = false;
                    nextDataStart = 0;
                    scanpos = 0;
                    cDebugDom("camera") << "scanpos: " << scanpos << " --> return";
                    return;
                }
            }

            scanpos = i - nextDataStart;
            cDebugDom("camera") << "--> scanpos: " << scanpos;
        }
    }
}