Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Images streaming using Indy client side
#4
I have an issue with images being sent from server. I am using Berlin Upd2 and FMX camera component.

The data received on client side is bigger than the one sent from the server. I don't know why?

Server Side:
Camera buffering
Code:
void __fastcall TMain::CameraComponentSampleBufferReady(TObject *Sender, const TMediaTime ATime)
{
bmp->Clear(0);
CameraComponent->SampleBufferToBitmap(bmp.get(), true);
}
//---------------------------------------------------------------------------

Server get:
Code:
if (ARequestInfo->Document == "/stream")
    {
    if (ARequestInfo->Command == "GET")
        {
        IsStreaming = true;
        AResponseInfo->ResponseNo = 200;
        AResponseInfo->ContentType = "multipart/x-mixed-replace; boundary=imgboundary";
        AResponseInfo->CloseConnection = false;
        AResponseInfo->WriteHeader();

        TIdIOHandler* IOHandler = AContext->Connection->IOHandler;
        IOHandler->LargeStream = true;

        IOHandler->WriteLn("--imgboundary");

        do
            {
            if (!AContext->Connection->Connected())
                return;

            unique_ptr<TMemoryStream> str(new TMemoryStream);
            bmp->SaveToStream(str.get());
            str->Position = 0;
            IOHandler->WriteLn("Content-type: image/png");
            IOHandler->WriteLn();
            IOHandler->Write(str.get());
            IOHandler->WriteLn();      //When client disconnects this raises exception
            IOHandler->WriteLn("--imgboundary");

            Sleep(5000);

            } while(IsStreaming);

        return;
        }

Client Side:
Code:
void __fastcall TMain::ButtonClick(TObject *Sender)
{
IdHTTP1->Get("http://localhost:1985/stream");

if (IdHTTP1->ResponseCode != 200 || !IsHeaderMediaType(IdHTTP1->Response->ContentType, "multipart/x-mixed-replace"))
    return;

String LBoundary = ExtractHeaderSubItem(IdHTTP1->Response->ContentType,"boundary", QuoteHTTP);
// String LBoundary = IdHTTP1->Response->RawHeaders->Params["Content-Type"][ "boundary"];

String LBoundaryStart = _D("--") + LBoundary;
String LBoundaryEnd = LBoundaryStart + _D("--");

unique_ptr<TIdTCPStream> Stream(new TIdTCPStream(IdHTTP1, 0));

do
    {
    String LLine = IdHTTP1->IOHandler->ReadLn();

    if (LLine == LBoundaryStart) break;
    if (LLine == LBoundaryEnd) return;
    }
while (true);

ThreadWait(FuncBind( &TMain::ProcessStreaming, this, Stream.get(), LBoundary));
}
//---------------------------------------------------------------------------

Code:
void TMain::ProcessImage(TMemoryStream *LMStream)
{
Image1->Bitmap->LoadFromStream(LMStream);
}
//---------------------------------------------------------------------------
void TMain::ProcessStreaming(TIdTCPStream* Stream, String LBoundary)
{
IdHTTP1->IOHandler->LargeStream = true;
TIdMessageDecoder* LDecoder = new TIdMessageDecoderMIME(nullptr);
try
    {
    bool LMsgEnd = false;

//    do
//        {
        static_cast<TIdMessageDecoderMIME*>(LDecoder)->MIMEBoundary = LBoundary;

        LDecoder->SourceStream = Stream;
        LDecoder->FreeSourceStream = false;
        LDecoder->ReadHeader();

        switch (LDecoder->PartType)
            {
            case mcptText:
            case mcptAttachment:
                {
                TMemoryStream *LMStream = new TMemoryStream;
                try
                    {
                    TIdMessageDecoder* LNewDecoder = LDecoder->ReadBody(LMStream, LMsgEnd);
                    LMStream->Position = 0;
                    LMStream->SaveToFile("image.png");

                    try
                        {

//                        SynchronizeUI(FuncBind( &TMain::ProcessImage, this, LMStream));
                        }
//                    catch (const Exception &)
//                        {
//                        delete LNewDecoder;
//                        throw;
//                        }
                    __finally
                        {
                        delete LDecoder;
                        LDecoder = LNewDecoder;
                        }

                    }
                __finally
                    {
                    delete LMStream;
                    }
                }
                break;
            case mcptIgnore:
                {
                FreeAndNil(LDecoder);
                LDecoder = new TIdMessageDecoderMIME(nullptr);
                static_cast<TIdMessageDecoderMIME*>(LDecoder)->MIMEBoundary = LBoundary;
                }
                break;
            case mcptEOF:
                {
                FreeAndNil(LDecoder);
                LMsgEnd = true;
                }
                break;
            }

//        } while (LDecoder && !LMsgEnd);
    }
__finally
    {
    delete LDecoder;
    }

You will find a lot of commented code because I was trying some other stuff in order to make it work.
When I save the image stream to a file on the server side before pushing it, it's ok and a valid image png file. But when I do save it the stream on the client side it shows that it is not a valid png file.

As you can see I am only testing with one frame and it is invalid file
Reply


Messages In This Thread
RE: Images streaming using Indy client side - by Ahmed Sayed - 05-03-2022, 06:51 AM

Forum Jump:


Users browsing this thread: 1 Guest(s)