| Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date | |
| All threads index page 5 | |
in my developing software project, we use QImage as buffer and in QWidget::paintEvent, we copy the QImage to QWidget. we use QPainter::drawImage() to do this, but it is slow, especially for rapidlly updating situations and i can't find the second way to do the same thing. I have already set Qt::WA_NoSystemBackground and Qt::WA_OpaquePaintEvent, it is a little faster, but i still think it is too slow. is it because the qwidget's automatic double buffer? Is there alternative way to do this and make it faster? Thanks in Advance! llzhu1984 2007-10-25
On torsdag den 25. Oktober 2007, llzhu1984 wrote: > in my developing software project, we use QImage as buffer and in > QWidget::paintEvent, we copy the QImage to QWidget. we use > QPainter::drawImage() to do this, but it is slow, especially for rapidlly > updating situations and i can't find the second way to do the same thing. > > I have already set Qt::WA_NoSystemBackground and Qt::WA_OpaquePaintEvent, > it is a little faster, but i still think it is too slow. is it because the > qwidget's automatic double buffer? > > Is there alternative way to do this and make it faster? Please search the archives. This has been discussed many many times. Last time was about three weeks ago. Bo. -- [ signature omitted ]
hi Bo,
I am not new to qt and i am thinking on this for months, i've tried almost every possible ways to speed up, perhaps qt can do 1000*1000 pixels image copy to qwiget(paintEvent) at 25 frame per sec(core2 6300 @1.86G, 1G RAM), i still wanna double its speed
what i don't tried is qglwidget, i don't know whether using it can satisfy my requirement, can it be faster?
Thanks,
Reimand
llzhu1984
2007-10-25
发件人: Bo Thorsen
发送时间: 2007-10-25 14:58:55
收件人: qt-interest@xxxxxxxxxxxxx
抄送:
主题: Re: How to Make QWidget::paint faster?
On torsdag den 25. Oktober 2007, llzhu1984 wrote:
> in my developing software project, we use QImage as buffer and in
> QWidget::paintEvent, we copy the QImage to QWidget. we use
> QPainter::drawImage() to do this, but it is slow, especially for rapidlly
> updating situations and i can't find the second way to do the same thing.
>
> I have already set Qt::WA_NoSystemBackground and Qt::WA_OpaquePaintEvent,
> it is a little faster, but i still think it is too slow. is it because the
> qwidget's automatic double buffer?
>
> Is there alternative way to do this and make it faster?
Please search the archives. This has been discussed many many times. Last time
was about three weeks ago.
Bo.
--
[ signature omitted ]
On torsdag den 25. Oktober 2007, llzhu1984 wrote: > hi Bo, > I am not new to qt and i am thinking on this for months, i've tried > almost every possible ways to speed up, Ok, sorry. It sounded like one of the standard questions. > perhaps qt can do 1000*1000 pixels > image copy to qwiget(paintEvent) at 25 frame per sec(core2 6300 @1.86G, 1G > RAM), i still wanna double its speed > > what i don't tried is qglwidget, i don't know whether using it can satisfy > my requirement, can it be faster? Yes, it can be faster, but it carries some other disadvantages with it. It really is a 3D system, and using it for 2D movie painting is not what it is designed to do. In your case, I would suggest you start looking at platform specific painting methods. On Windows this would mean making a DirectX component and setting it's winhandle to be in the QWidget. This gives you a direct 2D rendering system. On X11, you should look at the XV extension, which allows you to do this painting. Qt is designed to be a general purpose tool, and the requirements you have go beyond what you can expect from such a framework. So in this case, it's time to switch to a non-Qt solution for the output and let Qt handle the rest of the application. I hope this helps. Bo. > åääï Bo Thorsen > åéæéï 2007-10-25 14:58:55 > æääï qt-interest@xxxxxxxxxxxxx > æéï > äéï Re: How to Make QWidget::paint faster? > > On torsdag den 25. Oktober 2007, llzhu1984 wrote: > > in my developing software project, we use QImage as buffer and in > > QWidget::paintEvent, we copy the QImage to QWidget. we use > > QPainter::drawImage() to do this, but it is slow, especially for rapidlly > > updating situations and i can't find the second way to do the same thing. > > > > I have already set Qt::WA_NoSystemBackground and Qt::WA_OpaquePaintEvent, > > it is a little faster, but i still think it is too slow. is it because > > the qwidget's automatic double buffer? > > > > Is there alternative way to do this and make it faster? > > Please search the archives. This has been discussed many many times. Last > time was about three weeks ago. > > Bo. -- [ signature omitted ]
Bo Thorsen schrub:
> On torsdag den 25. Oktober 2007, llzhu1984 wrote:
>> hi Bo,
>> I am not new to qt and i am thinking on this for months, i've tried
>> almost every possible ways to speed up,
>
> Ok, sorry. It sounded like one of the standard questions.
>
>> perhaps qt can do 1000*1000 pixels
>> image copy to qwiget(paintEvent) at 25 frame per sec(core2 6300 @1.86G, 1G
>> RAM), i still wanna double its speed
>>
>> what i don't tried is qglwidget, i don't know whether using it can satisfy
>> my requirement, can it be faster?
>
> Yes, it can be faster, but it carries some other disadvantages with it. It
> really is a 3D system, and using it for 2D movie painting is not what it is
> designed to do.
Off course the main goal of OpenGL is 3D graphics, but I would not sign
the statement that "it was not designed for 2D graphics".
With OpenGL you can very well handle 2D graphics as well. The question
is off course will you experience a noticeable performance gain?
Especially if you quickly (25 FPS) need to update a given image and
redraw it as fast as possible. I think OpenGL can only play its
advantages when it comes e.g. to /scaling/ (or generally transforming)
the pixmap), because this can be done in hardware.
Here's some sample code taken from one of my OS projects:
// base class: QGLWidget
// turn of depth_test (not needed for 2D graphics) - you could
// probably disable some other OpenGL features as well, I did not
// go into optimizations too much, because it draws "fast enough"
// for me ;)
void GLMapWidget::initializeGL() {
glShadeModel(GL_FLAT);
this->updateMapImage();
glDisable(GL_DEPTH_TEST);
}
// this is the interesting part: instead of setting up a 3D projection
// matrix we setup a 2D projection with gluOrtho2D: this allows us to
// specify the pixmap (raster) coordinates in "screen coordinates" later
// on
void GLMapWidget::resizeGL (int width, int height) {
glViewport(0, 0, static_cast<GLsizei>(width),
static_cast<GLsizei>(height));
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, static_cast<GLdouble>(width),
0.0, static_cast<GLdouble>(height));
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// in my case I simply draw an image (m_openGLFormat, converted from
// QImage with the utility method QGLWidget::convertToGLFormat()) into
// the GLWidget paint area, starting at bottom left (0/0) position
// (or was it /top/ left?! I always get confused myself ... ;)
void GLMapWidget::paintGL() {
glClear(GL_COLOR_BUFFER_BIT);
// draw background
glRasterPos2i(0, 0);
glDrawPixels(m_openGLFormat.width(), m_openGLFormat.height(),
GL_RGBA, GL_UNSIGNED_BYTE,
static_cast<GLubyte *>(m_glMapImage.bits()));
// draw some other objects on top of it
...
}
Off course drawing a pixmap with glDrawPixels can be very fast, but the
bottleneck (in your case) would be elsewhere: converting the QImage into
a GL format image with
QImage myQtImage(...);
QImage openGLFormat = QGLWidget::convertToGLFormat(myQtImage);
Also when you use a normal QPainter with a QImage the bottleneck is
always converting the image data into "displayable data"; in the case of
a QPainter that would be QPixmap (and this conversion is done implicitly
when you paint a QImage with a QPainter!):
// this is SLOOOOOW (compared to the actual drawing)
QPixmap pixmap = QPixmap::fromImage(QImage image);
So regardless of whether you are using an OpenGL or QPainter based
solution, what you want to speed up is the conversion to the "OpenGL
format QImage" respective the QPixmap - and there's probably nothing
much you can do, expect maybe "pre-converting" all your images you want
to display at 25 FPS and then only drawing the GL format images
respective QPixmaps (QPainter::drawPixmap() instead of
QPainter::drawImage()!) - but if we are talking about decoded movie
images this might not be feasible (first because of the required RAM,
second because you want to decode in real-time, and not prefetch the
whole movie before playing it).
Or if you are lucky your raw image data is already in "OpenGL format"
(what that means I don't know right now, would have to look into my
OpenGL book, but it involves the ordering of the RGB values and the byte
alignment of each "image line". But luckily OpenGL accepts a lot of
"RGBA" value formats).
> In your case, I would suggest you start looking at platform specific painting
> methods.
This is off course also always a good (but costly, since platform
dependent) alternative.
Cheers, Oliver
--
[ signature omitted ]
Till Oliver Knoll schrub:
> ...
> glDrawPixels(m_openGLFormat.width(), m_openGLFormat.height(),
> GL_RGBA, GL_UNSIGNED_BYTE,
> static_cast<GLubyte *>(m_glMapImage.bits()));
Ups, trying to make the example more understandable and renaming some of
my variables actually rendered it wrong. This should off course read:
glDrawPixels(m_openGLFormat.width(), m_openGLFormat.height(),
GL_RGBA, GL_UNSIGNED_BYTE,
static_cast<GLubyte *>(m_openGLFormat.bits()));
^^^^^^^^^^^^^^
So you are really simply passing your RGBA image data to OpenGL (the
QGLWidget::convertToGLFormat() will convert it to GL_RGBA,
GL_UNSIGNED_BYTE).
Cheers, Oliver
--
[ signature omitted ]
llzhu1984 schrieb: > [...] perhaps qt can do > 1000*1000 pixels image copy to qwiget(paintEvent) at 25 frame per > sec(core2 6300 @1.86G, 1G RAM), That's piece-of-cake when using OpenGL texturing on a box with a reasonable graphics card. Even the shared graphics stuff should be able to meet these requirements. If it does not, Qt native painting will neither. If it is only about showing (panning, zooming, rotating) this image, I strongly recommend to use native OpenGL instead of drawing using standard QWidget painting. Best Regards / Mit freundlichen Grüßen Rainer Wiesenfarth -- [ signature omitted ]
Attachment:
smime.p7s
Description: S/MIME Cryptographic Signature
Rainer Wiesenfarth schrub: > llzhu1984 schrieb: > ... > If it is only about showing (panning, zooming, rotating) this image, I > strongly recommend to use native OpenGL instead of drawing using > standard QWidget painting. That's true: you can expect an enormous performance gain if you really want to transform the image! But as I understand the OP he wanted to exchange the image quickly at 25 FPS (for example displaying a (short?) movie), and this is exactly where I believe the performance bottleneck is (converting the QImage data into "displayable" data such as QPixmap or GL format QImage), as described in my previous post. I don't expect OpenGL glDrawPixels() to be much faster than a simple QPainter::drawPixmap (QPixmap here, not QImage!), but I might be wrong. For a quick and dirty performance comparison one could use a QPainter on top of a QGLWidget, call drawPixmap() and measure the performance difference, compared to drawing onto a "normal" QWidget. Cheers, Oliver -- [ signature omitted ]
On Oct 25, 2007, at 4:16 AM, llzhu1984 wrote: > I am not new to qt and i am thinking on this for months, i've > tried almost every possible ways to speed up, perhaps qt can do > 1000*1000 pixels image copy to qwiget(paintEvent) at 25 frame per > sec(core2 6300 @1.86G, 1G RAM), i still wanna double its speed > > what i don't tried is qglwidget, i don't know whether using it can > satisfy my requirement, can it be faster? I have an Open/GL application that can do >100fps of an 1600x1200 display. It uses QGLFramebufferObject to record the data, and then simple texture operations to blit the data to the screen during update. Highly recommended. Brad -- [ signature omitted ]
Brad Howes schrub: > On Oct 25, 2007, at 4:16 AM, llzhu1984 wrote: > >> I am not new to qt and i am thinking on this for months, i've >> tried almost every possible ways to speed up, perhaps qt can do >> 1000*1000 pixels image copy to qwiget(paintEvent) at 25 frame per >> sec(core2 6300 @1.86G, 1G RAM), i still wanna double its speed >> >> what i don't tried is qglwidget, i don't know whether using it can >> satisfy my requirement, can it be faster? > > I have an Open/GL application that can do >100fps of an 1600x1200 > display. It uses QGLFramebufferObject to record the data, and then > simple texture operations to blit the data to the screen during update. > Highly recommended. Hmm, that sounds very interesting. According to the Qt docs this relies on the GL_EXT_framebuffer_object. I can test for this extension with QGLFramebufferObject::hasOpenGLFramebufferObjects(). It's been a while since I have actively implemented OpenGL code, so is this a widely available extension, also for "consumer" graphic cards from ATI and nVidia by now? :) And where do you get your image data from? From a QImage (e.g. previously loaded from disk)? So are you really saying that you get 100 FPS when converting the data from your QImage into the QGLFramebufferObject? (I don't know the implementation, but I believe at some point the QImage raw data has to be converted into "OpenGL format", and I assume this takes some while, especially at 1600x1200 resolution, no?) Or are you directly drawing into the QGLFramebufferObject with a QPainter (that is, your images are "rendered" or calculated instead e.g. decompressed movie bitmaps, read form disk or something), just like in the Qt example, hence no conversion QImage -> GL format necessary(??): http://doc.trolltech.com/4.3/opengl-framebufferobject.html Cheers, Oliver -- [ signature omitted ]
On Oct 25, 2007, at 3:04 PM, Till Oliver Knoll wrote: > Brad Howes schrub: >> I have an Open/GL application that can do >100fps of an 1600x1200 >> display. It uses QGLFramebufferObject to record the data, and then >> simple texture operations to blit the data to the screen during >> update. Highly recommended. > > Hmm, that sounds very interesting. According to the Qt docs this > relies on the GL_EXT_framebuffer_object. I can test for this > extension with QGLFramebufferObject::hasOpenGLFramebufferObjects(). > > It's been a while since I have actively implemented OpenGL code, so > is this a widely available extension, also for "consumer" graphic > cards from ATI and nVidia by now? :) I don't know. It is available on my 4 year old PowerBook G4. Has an ATI Mobility Radeon 9700 and 128M of video RAM. I actually started out using pbuffers since that was what Qt first supported. FBOs are much easier to work with. > And where do you get your image data from? My application takes in data samples from an external device and renders them on a screen in the form of a radar display. I image onto the FBO, and then periodically render the FBO texture to the screen. When I remove the refresh limit (currently set to ~30fps) I get > 100 fps on my desktop machine. > From a QImage (e.g. previously loaded from disk)? No. I'm getting ~5000 samples in each message, and messages arrive at ~360Hz. This is over a gigabit ethernet connection. > So are you really saying that you get 100 FPS when converting the > data from your QImage into the QGLFramebufferObject? (I don't know > the implementation, but I believe at some point the QImage raw data > has to be converted into "OpenGL format", and I assume this takes > some while, especially at 1600x1200 resolution, no?) You are correct. I'm not doing 1600x1200 blits of QImage. My point was, that for blitter speed, OpenGL can provide very high frame rates of 2D (texture) data. Of course, the bottleneck is then getting the data into the GPU. > Or are you directly drawing into the QGLFramebufferObject with a > QPainter (that is, your images are "rendered" or calculated instead > e.g. decompressed movie bitmaps, read form disk or something), just > like in the Qt example, hence no conversion QImage -> GL format > necessary(??): I'm actually doing native OpenGL calls (glDrawArrays for speed), though I could have used QPainter I guess. Brad -- [ signature omitted ]
I'm having a problem while working with Q Threads. I have a thread. I
initialize some values in it, start it and then if it doesn't come back
in 35 seconds. I terminate the thread. I've been having a couple core
dumps after I terminate the thread. I've got a gdb dump but it doesn't
seem very helpful.
(gdb) where
#0 0xb7e6d3d8 in _Unwind_Resume@plt () from /usr/lib/libisdinterface.so
#1 0xb7e6f576 in ISD_ProcessTransaction () from
/usr/lib/libisdinterface.so
#2 0x0806ca12 in UTCThread::run (this=0x80a6920) at isd.cpp:38
#3 0xb7353654 in QThreadPrivate::start () from /usr/lib/libQtCore.so.4
#4 0xb726f34b in start_thread () from /lib/libpthread.so.0
#5 0xb70f665e in clone () from /lib/libc.so.6
I define the thread as a global in a namespace such:
Namespace ISD {
UTCThread thread ;
QTimer threadTimer ;
}
The code where I start the thread is here.
thread.setISDParameters(card, auth, dllRef, TimeOut);
thread.start() ;
threadTimer.start(TimeOut * 1000);
Log::Log(CRAZY, "Thread has started. Timer has started\n");
while(thread.isRunning()) {
a.processEvents() ;
usleep(100);
}
a.processEvents() ;
Log::Log(CRAZY, "Thread has Finished.\n");
retcode = thread.retcode();
When threadTimer activates, it calls a slot that does this:
void AuthApp::threadCheck() {
Log::Log(HEADER, "into void AuthApp::threadCheck()\n");
if(ISD::thread.isRunning()) {
Log::Log(ERROR, "Killing Thread.\n");
ISD::thread.auth()->errCond = CTHREADKILL ;
ISD::thread.setRetcode(UTCERROR) ;
ISD::thread.terminate() ;
}
ISD::threadTimer.stop() ;
Log::Log(FOOTER, "out void AuthApp::threadCheck()\n");
}
My log tells me that I'm starting the thread and the timer, a couple
other 5 second "I'm still alive" timers go off, the threadTimer goes
off, my code enters threadCheck, logs that it's killing the thread,
kills the thread and then exits threadCheck. It dies immediately after
that with the core dump described in the gdb where information.
Now, near as I can see. At the "while(thread.isRunning())" the thread
must still be running. At the processEvents the thread timer ticks and
calls threadcheck. Threadcheck runs, kills/terminates the thread and
then exits. We do the usleep(which I can't imagine causing any problems)
and then hit the isRunning() again. After that is the processEvents
call.
I'm not sure which is more likely to cause problems. isRunning shouldn't
be able to cause a core dump. And processEvents might have weird "trying
to clean up the thread" issues.
Any thoughts from people?
You asked for "any thoughts", so this is what you get ... :-)
First, do not capture an existing (e-mail!) thread. Start a new one, as
for readers using threaded display, your post is put into the "How to
Make QWidget::paint faster?" thread.
Second, people might prefer plain ASCII instead of HTML, especially when
there is no reason to use HTML.
Third, talking about your problem ...
Allen, Matthew schrieb:
> I’m having a problem while working with Q Threads. I have a thread. I
> initialize some values in it, start it and then if it doesn’t come back
> in 35 seconds. I terminate the thread. I’ve been having a couple core
> dumps after I terminate the thread. I’ve got a gdb dump but it doesn’t
> seem very helpful.
> [...]
From the Qt docs on QThread::terminate():
Warning: This function is dangerous and its use is discouraged. The
thread can be terminate at any point in its code path. Threads can be
terminated while modifying data. There is no chance for the thread to
cleanup after itself, unlock any held mutexes, etc. In short, use this
function only if absolutely necessary.
So, the question is if there is a more elegant way to end the thread.
> [...]
> thread.start() ;
> threadTimer.start(TimeOut * 1000);
> Log::Log(CRAZY, "Thread has started. Timer has started\n");
>
> while(thread.isRunning()) {
> a.processEvents() ;
> usleep(100);
> }
> a.processEvents() ;
>
> Log::Log(CRAZY, "Thread has Finished.\n");
> retcode = thread.retcode();
Why don't you use the QThread signals started(), finished() and maybe
terminated()? Using busy waiting and processEvents() here has the major
pitfall of recursively executing the given code.
Next question: Why do you use a static QThread object? Is there a reason
why you do not create the thread object at runtime?
> [...]
> My log tells me that I’m starting the thread and the timer, a couple
> other 5 second “I’m still alive” timers go off, the threadTimer goes
> off, my code enters threadCheck, logs that it’s killing the thread,
> kills the thread and then exits threadCheck. It dies immediately after
> that with the core dump described in the gdb where information.
> [...]
As said in the above warning from the documentation: you do not have any
idea at which point your thread was terminated. Using _any_ data your
thread might be modifying by the time of its sudden death may lead to
crashes.
Sorry to be somewhat unspecific on your real problem, but I do not know
enough about the application, the thread, and possible ways how to end
the thread gracefully. I could just give some hints how to make the code
more robust.
Best Regards / Mit freundlichen Grüßen
Rainer Wiesenfarth
--
[ signature omitted ]
Attachment:
smime.p7s
Description: S/MIME Cryptographic Signature
Hi Rainer,
When you say the emails are in a "threaded display", how does the display
know which thread the emails belong to?
Why does replying to an existing message and changing the subject not cause
a different thread to be started? I always do this, as it saves me having to
tell Outlook to store the message in this mailing list's folder.
Also I note that this list has not been fixed to automatically reply to the
list, rather than the sender. Should I raise this as an issue at TrollTech?
Thanks for your assisstance.
Tony Rietwyk.
> -----Original Message-----
> From: Rainer Wiesenfarth [mailto:Rainer.Wiesenfarth@xxxxxxxx]
> Sent: Friday, 26 October 2007 16:50
> To: Qt Interest List
> Subject: Re: QThread issue. Thread causing core dumps.
>
>
>
> You asked for "any thoughts", so this is what you get ... :-)
>
> First, do not capture an existing (e-mail!) thread. Start a
> new one, as
> for readers using threaded display, your post is put into the "How to
> Make QWidget::paint faster?" thread.
>
> Second, people might prefer plain ASCII instead of HTML,
> especially when
> there is no reason to use HTML.
>
> Third, talking about your problem ...
>
> Allen, Matthew schrieb:
> > I’m having a problem while working with Q Threads. I have a
> thread. I
> > initialize some values in it, start it and then if it
> doesn’t come back
> > in 35 seconds. I terminate the thread. I’ve been having a
> couple core
> > dumps after I terminate the thread. I’ve got a gdb dump but
> it doesn’t
> > seem very helpful.
> > [...]
>
> From the Qt docs on QThread::terminate():
>
> Warning: This function is dangerous and its use is discouraged. The
> thread can be terminate at any point in its code path. Threads can be
> terminated while modifying data. There is no chance for the thread to
> cleanup after itself, unlock any held mutexes, etc. In short,
> use this
> function only if absolutely necessary.
>
> So, the question is if there is a more elegant way to end the thread.
>
> > [...]
> > thread.start() ;
> > threadTimer.start(TimeOut * 1000);
> > Log::Log(CRAZY, "Thread has started. Timer has started\n");
> >
> > while(thread.isRunning()) {
> > a.processEvents() ;
> > usleep(100);
> > }
> > a.processEvents() ;
> >
> > Log::Log(CRAZY, "Thread has Finished.\n");
> > retcode = thread.retcode();
>
> Why don't you use the QThread signals started(), finished() and maybe
> terminated()? Using busy waiting and processEvents() here has
> the major
> pitfall of recursively executing the given code.
>
> Next question: Why do you use a static QThread object? Is
> there a reason
> why you do not create the thread object at runtime?
>
> > [...]
> > My log tells me that I’m starting the thread and the timer,
> a couple
> > other 5 second “I’m still alive” timers go off, the
> threadTimer goes
> > off, my code enters threadCheck, logs that it’s killing the thread,
> > kills the thread and then exits threadCheck. It dies
> immediately after
> > that with the core dump described in the gdb where information.
> > [...]
>
> As said in the above warning from the documentation: you do
> not have any
> idea at which point your thread was terminated. Using _any_ data your
> thread might be modifying by the time of its sudden death may lead to
> crashes.
>
> Sorry to be somewhat unspecific on your real problem, but I
> do not know
> enough about the application, the thread, and possible ways
> how to end
> the thread gracefully. I could just give some hints how to
> make the code
> more robust.
>
> Best Regards / Mit freundlichen Grüßen
> Rainer Wiesenfarth
>
> --
> INPHO GmbH * Smaragdweg 1 * 70174 Stuttgart * Germany
> phone: +49 711 2288 10 * fax: +49 711 2288 111 * web: www.inpho.de
> place of business: Stuttgart * managing director: Johannes Saile
> commercial register: Stuttgart, HRB 9586
> Leader in Photogrammetry and Digital Surface Modelling
> Visit us at Trimble Dimensions 2007
>
>
--
[ signature omitted ]
Dnia piÄtek, 26 paÅdziernika 2007, Tony Rietwyk napisaÅ: > Hi Rainer, > > When you say the emails are in a "threaded display", how does the display > know which thread the emails belong to? Read this: http://cr.yp.to/immhf/thread.html Regards, -- [ signature omitted ]
Attachment:
signature.asc
Description: This is a digitally signed message part.