Saturday, September 27, 2014

Video to DICOM (and back)

This is a story of a lost battle. For many years I refused to add MPEG to DICOM functionality in my DICOM SDK. The explanation I gave to myself and to my customers was that storing video in PACS is a bad idea because video streams are usually very big and nobody ever watches them. From an engineering point of view, the size of the video is not so much a matter of disk space but rather a network headache. The way that the DICOM network protocol works, with all the different levels of timeouts and with no failover mechanisms for PDU’s may cause such huge objects to fail over and over when stored and restored. For the clinical point of view, I consulted with Radiologists friends from whom I learned that the driving force behind keeping most of this stuff is not clinical but rather medico legal. These excuses held for some time but eventually, because I’m an engineer but also a businessman, I changed my mind. After all, the customer is always right, and when more and more customers asked to convert video to DICOM, I realized that winning this battle means loosing customers and that’s not something a businessman should do.

Videos were added to DICOM through the mechanism of Transfer Syntax. All together there are currently four (4) video transfer syntaxes for different types of MPEG’s. Here's the list of these transfer syntaxes:
  • MPEG2 Main Profile @ Main Level : "1.2.840.10008.1.2.4.100"
  • MPEG2 Main Profile @ High Level : "1.2.840.10008.1.2.4.101"
  • MPEG-4 AVC/H.264 High Profile / Level 4.1 : "1.2.840.10008.1.2.4.102"
  • MPEG-4 AVC/H.264 BD-compatible High Profile / Level 4.1 : "1.2.840.10008.1.2.4.103"


If I have to guess, there will probably be more added in the future as new formats of video gain take over. The embedded document option that was taken for PDF would probably be my choice but I admit that I didn’t investigate the reasons that led to the way the standard went and there may have

Wednesday, September 17, 2014

A short one on MPEG to DICOM

This is a quick post referencing our new release of RZDCX 2.0.4.2 that adds the option to convert MPEG to DICOM. I will post a longer article with all the information about MPEG and DICOM, video streams and audio hopefully by the end of this month. Meanwhile, check out this post on our web site and download the latest version of MODALIZER-SDK DICOM Toolkit.
Here's a short C++ code snippet that creates a DICOM encapsulated MPEG to start with:

static void CreateVideo(string filename)
{
    /// Create a DCXOBJ
    IDCXOBJPtr obj(__uuidof(DCXOBJ));

    /// Create an element pointer to place in the object for every tag
    IDCXELMPtr el(__uuidof(DCXELM));

IDCXUIDPtr id(__uuidof(DCXUID));

rzdcxLib::ENCAPSULATED_VIDEO_PROPS videoProps;
videoProps.width = 352;
videoProps.Height = 288;
videoProps.PixelAspectRatioX = 4;
videoProps.PixelAspectRatioY = 3;
videoProps.FrameDurationMiliSec; // 40 msec = 25 FPS
videoProps.NumberOfFrames = 1600; // 1600 frames
videoProps.VideoFormat = rzdcxLib::MPEG2_AT_MAIN_LEVEL;
obj->SetVideoStream(filename.c_str(), videoProps);


obj->TransferSyntax = rzdcxLib::TS_MPEG2_MAIN_PROFILE_AT_HIGH_LEVEL;
    /// You don't have to create an element every time, 
    /// just initialize it.
char pn[]="John^Doe";
    el->Init(rzdcxLib::PatientsName);
    el->PutCStringPtr((int)pn);
    obj->insertElement(el);

el->Init(rzdcxLib::patientID);
    el->Value = "123765";
    obj->insertElement(el);

el->Init(rzdcxLib::studyInstanceUID);
el->Value = id->CreateUID(UID_TYPE_STUDY);
obj->insertElement(el);

el->Init(rzdcxLib::seriesInstanceUID);
el->Value = id->CreateUID(UID_TYPE_SERIES);
obj->insertElement(el);
el->Init(rzdcxLib::sopInstanceUID);
el->Value = id->CreateUID(UID_TYPE_INSTANCE);
obj->insertElement(el);

el->Init(rzdcxLib::sopClassUid);
el->Value = "1.2.840.10008.5.1.4.1.1.77.1.4.1"; // Video Photographic Image Storage
obj->insertElement(el);

el->Init(rzdcxLib::NumberOfFrames);
el->Value = (short)1600;
obj->insertElement(el);

el->Init(rzdcxLib::FrameIncrementPointer);
el->Value = rzdcxLib::FrameTime;
obj->insertElement(el);

filename += ".dcm";
obj->saveFile(filename.c_str());

}

One last note: You should know your video properties because we don't open or validate the MPEG file. More on "why is it this way" in the longer post soon.