示例#1
0
文件: mhi.cpp 项目: Olti/mythtv
// Called by the video player to redraw the image.
void MHIContext::UpdateOSD(InteractiveScreen *osdWindow,
                           MythPainter *osdPainter)
{
    if (!osdWindow || !osdPainter)
        return;

    QMutexLocker locker(&m_display_lock);
    m_updated = false;
    osdWindow->DeleteAllChildren();
    // Copy all the display items into the display.
    list<MHIImageData*>::iterator it = m_display.begin();
    for (int count = 0; it != m_display.end(); ++it, count++)
    {
        MHIImageData *data = *it;
        MythImage* image = osdPainter->GetFormatImage();
        if (!image)
            continue;

        image->Assign(data->m_image);
        MythUIImage *uiimage = new MythUIImage(osdWindow, QString("itv%1")
                                               .arg(count));
        if (uiimage)
        {
            uiimage->SetImage(image);
            uiimage->SetArea(MythRect(data->m_x, data->m_y,
                             data->m_image.width(), data->m_image.height()));
        }
        image->DecrRef();
    }
    osdWindow->OptimiseDisplayedArea();
    // N.B. bypasses OSD class hence no expiry set
    osdWindow->SetVisible(true);
}
示例#2
0
MythImage *MythPainter::GetImageFromString(const QString &msg,
                                           int flags, const QRect &r,
                                           const MythFontProperties &font)
{
    QString incoming = font.GetHash() + QString::number(r.width()) +
                       QString::number(r.height()) +
                       QString::number(flags) +
                       QString::number(font.color().rgba()) + msg;

    if (m_StringToImageMap.contains(incoming))
    {
        m_StringExpireList.remove(incoming);
        m_StringExpireList.push_back(incoming);
        return m_StringToImageMap[incoming];
    }

    MythImage *im = GetFormatImage();
    if (im)
    {
        DrawTextPriv(im, msg, flags, r, font);
        m_SoftwareCacheSize += im->bytesPerLine() * im->height();
        m_StringToImageMap[incoming] = im;
        m_StringExpireList.push_back(incoming);
        ExpireImages(m_MaxSoftwareCacheSize);
    }
    return im;
}
示例#3
0
文件: webpage.cpp 项目: Cougar/mythtv
void WebPage::slotIconChanged(void)
{
    QIcon icon = m_browser->GetIcon();

    if (icon.isNull())
    {
        //FIXME use a default icon here?
        m_listItem->setImage(NULL);
    }
    else
    {
        if (m_listItem)
        {
            QPixmap pixmap = icon.pixmap(32, 32);
            QImage image = pixmap.toImage();
            image = image.scaled(
                QSize(32,32), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
            MythImage *mimage = GetMythPainter()->GetFormatImage();
            mimage->Assign(image);

            m_listItem->setImage(mimage);
        }
    }

    m_parent->m_pageList->Refresh();
}
示例#4
0
void ZMEvents::eventVisible(MythUIButtonListItem *item)
{
    if (!item)
        return;

    if (item->HasImage())
        return;

    Event *event = qVariantValue<Event*> (item->GetData());

    if (event)
    {
        QImage image;
        if (ZMClient *zm = ZMClient::get())
        {
            zm->getAnalyseFrame(event, 0, image);
            if (!image.isNull())
            {
                MythImage *mimage = GetMythPainter()->GetFormatImage();
                mimage->Assign(image);
                item->SetImage(mimage);
                mimage->SetChanged();
                mimage->DecrRef();
            }
        }
    }
}
示例#5
0
void MythPainter::DrawTextLayout(const QRect & canvasRect,
                                 const LayoutVector & layouts,
                                 const FormatVector & formats,
                                 const MythFontProperties & font, int alpha,
                                 const QRect & destRect)
{
    if (canvasRect.isNull())
        return;

    QRect      canvas(canvasRect);
    QRect      dest(destRect);

    MythImage *im = GetImageFromTextLayout(layouts, formats, font,
                                           canvas, dest);
    if (!im)
    {
        LOG(VB_GENERAL, LOG_ERR, QString("MythPainter::DrawTextLayout: "
                                             "Unable to create image."));
        return;
    }
    if (im->isNull())
    {
        LOG(VB_GENERAL, LOG_DEBUG, QString("MythPainter::DrawTextLayout: "
                                           "Rendered image is null."));
        im->DecrRef();
        return;
    }

    QRect srcRect(0, 0, dest.width(), dest.height());
    DrawImage(dest, im, srcRect, alpha);

    im->DecrRef();
}
示例#6
0
void SubtitleScreen::AddScaledImage(QImage &img, QRect &pos)
{
    VideoOutput *vo = m_player->GetVideoOutput();
    if (!vo)
        return;

    QRect scaled = vo->GetImageRect(pos);
    if (scaled.size() != pos.size())
    {
        img = img.scaled(scaled.width(), scaled.height(),
                         Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    }

    MythPainter *osd_painter = vo->GetOSDPainter();
    MythImage* image = NULL;
    if (osd_painter)
         image = osd_painter->GetFormatImage();

    if (image)
    {
        image->Assign(img);
        MythUIImage *uiimage = new MythUIImage(this, "dvd_button");
        if (uiimage)
        {
            m_refreshArea = true;
            uiimage->SetImage(image);
            uiimage->SetArea(MythRect(scaled));
        }
    }
}
示例#7
0
MythImage* MythPainter::GetImageFromRect(const QRect &area, int radius,
                                         int ellipse,
                                         const QBrush &fillBrush,
                                         const QPen &linePen)
{
    if (area.width() <= 0 || area.height() <= 0)
        return NULL;

    uint64_t hash1 = ((0xfff & (uint64_t)area.width())) +
                     ((0xfff & (uint64_t)area.height())     << 12) +
                     ((0xff  & (uint64_t)fillBrush.style()) << 24) +
                     ((0xff  & (uint64_t)linePen.width())   << 32) +
                     ((0xff  & (uint64_t)radius)            << 40) +
                     ((0xff  & (uint64_t)linePen.style())   << 48) +
                     ((0xff  & (uint64_t)ellipse)           << 56);
    uint64_t hash2 = ((0xffffffff & (uint64_t)linePen.color().rgba())) +
                     ((0xffffffff & (uint64_t)fillBrush.color().rgba()) << 32);

    QString incoming("R");
    if (fillBrush.style() == Qt::LinearGradientPattern && fillBrush.gradient())
    {
        const QLinearGradient *gradient = static_cast<const QLinearGradient*>(fillBrush.gradient());
        if (gradient)
        {
            incoming = QString::number(
                             ((0xfff & (uint64_t)gradient->start().x())) +
                             ((0xfff & (uint64_t)gradient->start().y()) << 12) +
                             ((0xfff & (uint64_t)gradient->finalStop().x()) << 24) +
                             ((0xfff & (uint64_t)gradient->finalStop().y()) << 36));
            QGradientStops stops = gradient->stops();
            for (int i = 0; i < stops.size(); i++)
            {
                incoming += QString::number(
                             ((0xfff * (uint64_t)(stops[i].first * 100))) +
                             ((uint64_t)stops[i].second.rgba() << 12));
            }
        }
    }

    incoming += QString::number(hash1) + QString::number(hash2);

    if (m_StringToImageMap.contains(incoming))
    {
        m_StringExpireList.remove(incoming);
        m_StringExpireList.push_back(incoming);
        return m_StringToImageMap[incoming];
    }

    MythImage *im = GetFormatImage();
    if (im)
    {
        DrawRectPriv(im, area, radius, ellipse, fillBrush, linePen);
        m_SoftwareCacheSize += (im->bytesPerLine() * im->height());
        m_StringToImageMap[incoming] = im;
        m_StringExpireList.push_back(incoming);
        ExpireImages(m_MaxSoftwareCacheSize);
    }
    return im;
}
示例#8
0
MythImage *MythPainter::GetFormatImage(void)
{
    QMutexLocker locker(&m_allocationLock);
    MythImage *result = GetFormatImagePriv();
    result->SetFileName("GetFormatImage");
    m_allocatedImages.insert(result);
    return result;
}
示例#9
0
MythImage *AudioOutputGraph::GetImage(int64_t timecode) const
{
    QMutexLocker lock(&m_mutex);
    Buffer::range_t avail = m_buffer->Avail(timecode);

    LOG(VB_PLAYBACK, LOG_INFO, LOC +
        QString("(%1) using [%2..%3] avail [%4..%5]")
        .arg(timecode).arg(avail.first).arg(avail.second)
        .arg(m_buffer->First()).arg(m_buffer->Next()) );

    const int width = m_buffer->Samples(avail);
    if (width <= 0)
        return nullptr;

    const unsigned range = 1U << m_buffer->BitsPerChannel();
    const double threshold = 20 * log10(1.0 / range); // 16bit=-96.3296dB => ~6dB/bit
    const int height = (int)-ceil(threshold); // 96
    if (height <= 0)
        return nullptr;

    QImage image(width, height, QImage::Format_ARGB32);
    image.fill(0);

    const int channels = m_buffer->Channels();

    // Assume signed 16 bit/sample
    const int16_t *p = m_buffer->Data16(avail);

    for (int x = 0; x < width; ++x)
    {
        int left = p[0];
        int right = channels > 1 ? p[1] : left;
        p += channels;

        unsigned avg = qAbs(left) + qAbs(right);
        double db = 20 * log10( (double)(avg ? avg : 1) / range);

        int idb = (int)ceil(db);
        QRgb rgb = idb <= m_dBsilence ? qRgb(255, 255, 255)
                 : idb <= m_dBquiet   ? qRgb(  0, 255, 255)
                 : idb <= m_dBLoud    ? qRgb(  0, 255,   0)
                 : idb <= m_dbMax     ? qRgb(255, 255,   0)
                 :                      qRgb(255,   0,   0);

        int v = height - (int)(height * (db / threshold));
        if (v >= height)
            v = height - 1;
        else if (v < 0)
            v = 0;

        for (int y = 0; y <= v; ++y)
            image.setPixel(x, height - 1 - y, rgb);
    }

    MythImage *mi = new MythImage(m_painter);
    mi->Assign(image);
    return mi;
}
MythImage* MythQImagePainter::GetImageFromRect(const QSize &size, int radius,
                                               bool drawFill,
                                               const QColor &fillColor,
                                               bool drawLine,
                                               int lineWidth,
                                               const QColor &lineColor)
{
    if (size.width() <= 0 || size.height() <= 0)
        return NULL;

    QString incoming = QString("RECT") + QString::number(size.width()) +
                       QString::number(size.height()) +
                       QString::number(radius) + QString::number(drawFill) +
                       QString::number(fillColor.rgba()) +
                       QString::number(drawLine) + QString::number(lineWidth) +
                       QString::number(lineColor.rgba());

    if (m_StringToImageMap.contains(incoming))
    {
        m_StringExpireList.remove(incoming);
        m_StringExpireList.push_back(incoming);
        return m_StringToImageMap[incoming];
    }

    QImage image(QSize(size.width(), size.height()), QImage::Format_ARGB32);
    image.fill(0x00000000);
    QPainter painter(&image);
    painter.setRenderHint(QPainter::Antialiasing);

    if (drawLine)
        painter.setPen(QPen(lineColor, lineWidth));
    else
        painter.setPen(QPen(Qt::NoPen));

    if (drawFill)
        painter.setBrush(QBrush(fillColor));
    else
        painter.setBrush(QBrush(Qt::NoBrush));

    if ((size.width() / 2) < radius)
        radius = size.width() / 2;

    if ((size.height() / 2) < radius)
        radius = size.height() / 2;

    QRect r(lineWidth / 2, lineWidth / 2, size.width() - lineWidth,
            size.height() - lineWidth);
    painter.drawRoundedRect(r, (qreal)radius, qreal(radius));
    painter.end();

    MythImage *im = GetFormatImage();
    im->Assign(image);
    m_StringToImageMap[incoming] = im;
    m_StringExpireList.push_back(incoming);
    ExpireImages(MAX_CACHE_ITEMS);
    return im;
}
示例#11
0
void Player::updateFrame(const unsigned char* buffer)
{
    QImage image(buffer, m_monitor.width, m_monitor.height, QImage::Format_RGB888);

    MythImage *img = GetMythMainWindow()->GetCurrentPainter()->GetFormatImage();
    img->Assign(image);
    m_frameImage->SetImage(img);
    img->DecrRef();
}
示例#12
0
void ThumbFinder::updatePositionBar(int64_t frame)
{
    if (!m_positionImage)
        return;

    QSize size = m_positionImage->GetArea().size();
    QPixmap *pixmap = new QPixmap(size.width(), size.height());

    QPainter p(pixmap);
    QBrush brush(Qt::green);

    p.setBrush(brush);
    p.setPen(Qt::NoPen);
    p.fillRect(0, 0, size.width(), size.height(), brush);

    frm_dir_map_t::const_iterator it;

    brush.setColor(Qt::red);
    double startdelta, enddelta;

    for (it = m_deleteMap.begin(); it != m_deleteMap.end(); ++it)
    {
        if (it.key() != 0)
            startdelta = (m_archiveItem->duration * m_fps) / it.key();
        else
            startdelta = size.width();

        ++it;
        if (it == m_deleteMap.end())
        {
            LOG(VB_GENERAL, LOG_ERR, "ThumbFinder: found a start cut but no cut end");
            break;
        }

        if (it.key() != 0)
            enddelta = (m_archiveItem->duration * m_fps) / it.key();
        else
            enddelta = size.width();
        int start = (int) (size.width() / startdelta);
        int end = (int) (size.width() / enddelta);
        p.fillRect(start - 1, 0, end - start, size.height(), brush);
    }

    if (frame == 0)
        frame = 1;
    brush.setColor(Qt::yellow);
    int pos = (int) (size.width() / ((m_archiveItem->duration * m_fps) / frame));
    p.fillRect(pos, 0, 3, size.height(), brush);

    MythImage *image = GetMythMainWindow()->GetCurrentPainter()->GetFormatImage();
    image->Assign(*pixmap);
    m_positionImage->SetImage(image);

    p.end();
    delete pixmap;
}
示例#13
0
void MythPainter::DrawEllipse(const QRect &area, const QBrush &fillBrush,
                              const QPen &linePen, int alpha)
{
    MythImage *im = GetImageFromRect(area, 0, 1, fillBrush, linePen);
    if (im)
    {
        DrawImage(area.x(), area.y(), im, alpha);
        im->DecrRef();
    }
}
示例#14
0
/**
*  \copydoc MythUIType::customEvent()
*/
void MythUIImage::customEvent(QEvent *event)
{
    if (event->type() == ImageLoadEvent::kEventType)
    {
        ImageLoadEvent *le = dynamic_cast<ImageLoadEvent*>(event);

        if (le->GetParent() != this)
            return;

        MythImage *image = le->GetImage();

        if (!image)
            return;

        d->m_UpdateLock.lockForRead();
        if (le->GetBasefile() != m_Filename)
        {
            d->m_UpdateLock.unlock();
#if 0
            VERBOSE(VB_GUI|VB_FILE|VB_EXTRA, LOC +
                    QString("customEvent(): Expecting '%2', got '%3'")
                    .arg(m_Filename).arg(le->GetBasefile()));
#endif
            image->DownRef();
            return;
        }
        d->m_UpdateLock.unlock();

        QString filename = le->GetFilename();
        int number = le->GetNumber();

        d->m_UpdateLock.lockForWrite();
        if (m_ForceSize.isNull())
            SetSize(image->size());
        d->m_UpdateLock.unlock();

        m_ImagesLock.lock();
        if (m_Images[number])
        {
            // If we got to this point, it means this same MythUIImage
            // was told to reload the same image, so we use the newest
            // copy of the image.
            m_Images[number]->DownRef(); // delete the original
        }
        m_Images[number] = image;
        m_ImagesLock.unlock();

        SetRedraw();

        d->m_UpdateLock.lockForWrite();
        m_LastDisplay = QTime::currentTime();
        d->m_UpdateLock.unlock();
    }
}
示例#15
0
void TeletextScreen::OptimiseDisplayedArea(void)
{
    VideoOutput *vo = m_player->GetVideoOutput();
    if (!vo)
        return;
    MythPainter *osd_painter = vo->GetOSDPainter();
    if (!osd_painter)
        return;

    QHashIterator<int, QImage*> it(m_rowImages);
    while (it.hasNext())
    {
        it.next();
        MythImage* image = osd_painter->GetFormatImage();
        if (!image || !it.value())
            continue;

        int row = it.key();
        image->Assign(*(it.value()));
        MythUIImage *uiimage = new MythUIImage(this, QString("ttrow%1")
                                                        .arg(row));
        if (uiimage)
        {
            uiimage->SetImage(image);
            uiimage->SetArea(MythRect(0, row * m_rowHeight,
                                      m_safeArea.width(), m_rowHeight * 2));
        }
    }

    QRegion visible;
    QListIterator<MythUIType *> i(m_ChildrenList);
    while (i.hasNext())
    {
        MythUIType *img = i.next();
        visible = visible.united(img->GetArea());
    }

    if (visible.isEmpty())
        return;

    QRect bounding  = visible.boundingRect();
    bounding = bounding.translated(m_safeArea.topLeft());
    bounding = m_safeArea.intersected(bounding);
    int left = m_safeArea.left() - bounding.left();
    int top  = m_safeArea.top()  - bounding.top();
    SetArea(MythRect(bounding));

    i.toFront();;
    while (i.hasNext())
    {
        MythUIType *img = i.next();
        img->SetArea(img->GetArea().translated(left, top));
    }
}
示例#16
0
void MythPainter::DrawRoundRect(const QRect &area, int cornerRadius,
                                const QBrush &fillBrush, const QPen &linePen,
                                int alpha)
{
    MythImage *im = GetImageFromRect(area, cornerRadius, 0, fillBrush, linePen);
    if (im)
    {
        DrawImage(area.x(), area.y(), im, alpha);
        im->DecrRef();
    }
}
示例#17
0
/**
 *  \brief Assign a set of MythImages to the widget for animation.
 *         Use is strongly discouraged, use SetFilepattern() instead.
 *
 */
void MythUIImage::SetImages(QVector<MythImage *> &images)
{
    Clear();

    QWriteLocker updateLocker(&d->m_UpdateLock);
    QSize aSize = GetArea().size();

    QVector<MythImage *>::iterator it;
    for (it = images.begin(); it != images.end(); ++it)
    {
        MythImage *im = (*it);
        if (!im)
        {
            QMutexLocker locker(&m_ImagesLock);
            m_Images[m_Images.size()] = im;
            continue;
        }

        im->UpRef();

        if (!m_ForceSize.isNull())
        {
            int w = (m_ForceSize.width() <= 0) ? im->width() : m_ForceSize.width();
            int h = (m_ForceSize.height() <= 0) ? im->height() : m_ForceSize.height();

            im->Resize(QSize(w, h), m_preserveAspect);
        }

        if (m_isReflected && !im->IsReflected())
            im->Reflect(m_reflectAxis, m_reflectShear, m_reflectScale,
                         m_reflectLength, m_reflectSpacing);

        if (m_isGreyscale && !im->isGrayscale())
            im->ToGreyscale();

        m_ImagesLock.lock();
        m_Images[m_Images.size()] = im;
        m_ImagesLock.unlock();

        aSize = aSize.expandedTo(im->size());
    }

    SetImageCount(1, m_Images.size());

    if (m_ForceSize.isNull())
        SetSize(aSize);

    m_CurPos = 0;
    SetRedraw();
}
示例#18
0
void ZMEvents::eventChanged(MythUIButtonListItem *item)
{
    (void) item;

    if (m_eventNoText)
    {
        if (m_eventGrid->GetCount() > 0)
            m_eventNoText->SetText(QString("%1/%2")
                                   .arg(m_eventGrid->GetCurrentPos() + 1).arg(m_eventGrid->GetCount()));
        else
            m_eventNoText->SetText("0/0");
    }

    // update the images for all the visible items
    for (int x = m_eventGrid->GetCurrentPos() - m_eventGrid->GetVisibleCount();
            x < m_eventGrid->GetCurrentPos() + (int)m_eventGrid->GetVisibleCount(); x++)
    {
        if (x < 0 || x > (int)m_eventGrid->GetCount() - 1)
            continue;

        MythUIButtonListItem *gridItem = m_eventGrid->GetItemAt(x);
        if (gridItem && !gridItem->getImage())
        {
            if (x < 0 || x > (int)m_eventList->size() - 1)
                continue;

            Event *event = m_eventList->at(x);
            if (event)
            {
                QImage image;
                if (class ZMClient *zm = ZMClient::get())
                {
                    zm->getAnalyseFrame(event->monitorID,
                                        event->eventID,
                                        0, image);
                    if (!image.isNull())
                    {
                        MythImage *mimage = GetMythPainter()->GetFormatImage();
                        mimage->Assign(image);
                        gridItem->setImage(mimage);
                        mimage->SetChanged();
                    }
                }
            }
        }
    }
}
示例#19
0
void MythPainter::DrawText(const QRect &r, const QString &msg,
                           int flags, const MythFontProperties &font,
                           int alpha, const QRect &boundRect)
{
    MythImage *im = GetImageFromString(msg, flags, r, font);
    if (!im)
        return;

    QRect destRect(boundRect);
    QRect srcRect(0,0,r.width(),r.height());
    if (!boundRect.isEmpty() && boundRect != r)
    {
        int x = 0;
        int y = 0;
        int width = boundRect.width();
        int height = boundRect.height();

        if (boundRect.x() > r.x())
        {
            x = boundRect.x()-r.x();
        }
        else if (r.x() > boundRect.x())
        {
            destRect.setX(r.x());
            width = (boundRect.x() + boundRect.width()) - r.x();
        }

        if (boundRect.y() > r.y())
        {
            y = boundRect.y()-r.y();
        }
        else if (r.y() > boundRect.y())
        {
            destRect.setY(r.y());
            height = (boundRect.y() + boundRect.height()) - r.y();
        }

        if (width <= 0 || height <= 0)
            return;

        srcRect.setRect(x,y,width,height);
    }

    DrawImage(destRect, im, srcRect, alpha);
    im->DecrRef();
}
示例#20
0
void MythYUVAPainter::DrawRect(const QRect &area, const QBrush &fillBrush,
                               const QPen &linePen, int alpha)
{
    QBrush brush(fillBrush);

    switch (fillBrush.style())
    {
    case Qt::LinearGradientPattern:
    case Qt::RadialGradientPattern:
    case Qt::ConicalGradientPattern:
        {
        QGradient gradient = *fillBrush.gradient();
        QGradientStops stops = gradient.stops();
        for (QGradientStops::iterator it = stops.begin(); it != stops.end(); ++it)
        {
            it->second = rgb_to_yuv(it->second);
            it->second.setAlpha(alpha);
        }
        gradient.setStops(stops);
        brush = gradient;
        }
        break;
    default:
        brush.setColor(rgb_to_yuv(brush.color()));
        break;
    }

    QPen pen(linePen);
    pen.setColor(rgb_to_yuv(pen.color()));

    // We pull an image here, in the hopes that when DrawRect
    // pulls an image this will still be in the cache and have
    // the right properties.
    MythImage *im = GetImageFromRect(area, 0, 0, brush, pen);
    if (im)
    {
        im->SetToYUV();
        im->DecrRef();
        im = NULL;
    }

    MythQImagePainter::DrawRect(area, brush, pen, alpha);
}
示例#21
0
void ReferenceCounter::PrintDebug(void)
{
    QReadLocker locker(&leakLock);

    uint cnt = 0;
    QMap<ReferenceCounter*,LeakInfo>::iterator it = leakMap.begin();
    for (; it != leakMap.end(); ++it)
        cnt += (*it).name.startsWith("CommandLineArg") ? 0 : 1;

    LOG((cnt) ? VB_GENERAL : VB_REFCOUNT, LOG_INFO,
        QString("Leaked %1 reference counted objects").arg(cnt));

    for (it = leakMap.begin(); it != leakMap.end(); ++it)
    {
        if ((*it).name.startsWith("CommandLineArg"))
            continue;
        LOG(VB_REFCOUNT, LOG_INFO,
            QString("  Leaked %1(0x%2) reference count %3")
            .arg((*it).name)
            .arg(reinterpret_cast<intptr_t>(it.key()),0,16)
            .arg((*it).refCount));
/// This part will not work on some non-Linux machines..
#if defined(__linux__) || defined(__LINUX__)
        MythImage *img = NULL;
        if ((*it).name.startsWith("MythImage") ||
            (*it).name.startsWith("MythQtImage"))
        {
            img = reinterpret_cast<MythImage*>(it.key());
        }
        if (img)
        {
            LOG(VB_REFCOUNT, LOG_INFO,
                QString("  Image id %1 cache size %2 file '%3'")
                .arg(img->GetID())
                .arg(img->GetCacheSize())
                .arg(img->GetFileName()));
        }
#endif
///
    }
}
示例#22
0
void MythYUVAPainter::DrawEllipse(const QRect &area, const QBrush &fillBrush,
                                  const QPen &linePen, int alpha)
{
    QBrush brush(fillBrush);
    brush.setColor(rgb_to_yuv(brush.color()));
    QPen pen(linePen);
    pen.setColor(rgb_to_yuv(pen.color()));

    // We pull an image here, in the hopes that when DrawRect
    // pulls an image this will still be in the cache and have
    // the right properties.
    MythImage *im = GetImageFromRect(area, 0, 1, brush, pen);
    if (im)
    {
        im->SetToYUV();
        im->DecrRef();
        im = NULL;
    }

    MythQImagePainter::DrawEllipse(area, brush, pen, alpha);
}
示例#23
0
void MythPainter::ExpireImages(int64_t max)
{
    bool recompute = false;
    while (!m_StringExpireList.empty())
    {
        if (m_SoftwareCacheSize < max)
            break;

        QString oldmsg = m_StringExpireList.front();
        m_StringExpireList.pop_front();

        QMap<QString, MythImage*>::iterator it =
            m_StringToImageMap.find(oldmsg);
        if (it == m_StringToImageMap.end())
        {
            recompute = true;
            continue;
        }
        MythImage *oldim = *it;
        it = m_StringToImageMap.erase(it);

        if (oldim)
        {
            m_SoftwareCacheSize -= oldim->bytesPerLine() * oldim->height();
            if (m_SoftwareCacheSize < 0)
            {
                m_SoftwareCacheSize = 0;
                recompute = true;
            }
            oldim->DecrRef();
        }
    }
    if (recompute)
    {
        m_SoftwareCacheSize = 0;
        QMap<QString, MythImage*>::iterator it = m_StringToImageMap.begin();
        for (; it != m_StringToImageMap.end(); ++it)
            m_SoftwareCacheSize += (*it)->bytesPerLine() * (*it)->height();
    }
}
示例#24
0
void MythYUVAPainter::DrawText(const QRect &dest, const QString &msg, int flags,
                               const MythFontProperties &font, int alpha,
                               const QRect &boundRect)
{
    MythFontProperties *converted = GetConvertedFont(font);
    if (converted)
    {
        // We pull an image here, in the hopes that when DrawText
        // pulls an image this will still be in the cache and have
        // the right properties.
        MythImage *im = GetImageFromString(msg, flags, dest, *converted);
        if (im)
        {
            im->SetToYUV();
            im->DecrRef();
            im = NULL;
        }

        MythQImagePainter::DrawText(dest, msg, flags, *converted,
                                    alpha, boundRect);
    }
}
示例#25
0
void MythPainter::ExpireImages(int max)
{
    if (m_StringExpireList.size() < 1)
        return;

    while (m_SoftwareCacheSize > max)
    {
        QString oldmsg = m_StringExpireList.front();
        m_StringExpireList.pop_front();

        MythImage *oldim = NULL;
        if (m_StringToImageMap.contains(oldmsg))
            oldim = m_StringToImageMap[oldmsg];

        m_StringToImageMap.remove(oldmsg);

        if (oldim)
        {
            m_SoftwareCacheSize -= oldim->bytesPerLine() * oldim->height();
            oldim->DownRef();
        }
    }
}
示例#26
0
bool ThumbFinder::getFrameImage(bool needKeyFrame, int64_t requiredPTS)
{
    AVPacket pkt;
    AVFrame orig;
    AVFrame retbuf;
    memset(&orig, 0, sizeof(AVFrame));
    memset(&retbuf, 0, sizeof(AVFrame));

    av_init_packet(&pkt);

    int frameFinished = 0;
    int keyFrame;
    int frameCount = 0;
    bool gotKeyFrame = false;

    while (av_read_frame(m_inputFC, &pkt) >= 0 && !frameFinished)
    {
        if (pkt.stream_index == m_videostream)
        {
            frameCount++;

            keyFrame = pkt.flags & AV_PKT_FLAG_KEY;

            if (m_startPTS == -1 && pkt.dts != AV_NOPTS_VALUE)
            {
                m_startPTS = pkt.dts;
                m_frameTime = pkt.duration;
            }

            if (keyFrame)
                gotKeyFrame = true;

            if (!gotKeyFrame && needKeyFrame)
            {
                av_packet_unref(&pkt);
                continue;
            }

            if (m_firstIFramePTS == -1)
                m_firstIFramePTS = pkt.dts;

            av_frame_unref(m_frame);
            frameFinished = 0;
            int ret = avcodec_receive_frame(m_codecCtx, m_frame);
            if (ret == 0)
                frameFinished = 1;
            if (ret == 0 || ret == AVERROR(EAGAIN))
                ret = avcodec_send_packet(m_codecCtx, &pkt);
            if (requiredPTS != -1 && pkt.dts != AV_NOPTS_VALUE && pkt.dts < requiredPTS)
                frameFinished = false;

            m_currentPTS = pkt.dts;
        }

        av_packet_unref(&pkt);
    }

    if (frameFinished)
    {
        av_image_fill_arrays(retbuf.data, retbuf.linesize, m_outputbuf,
            AV_PIX_FMT_RGB32, m_frameWidth, m_frameHeight, IMAGE_ALIGN);
        AVFrame *tmp = m_frame;

        m_deinterlacer->DeinterlaceSingle(tmp, tmp);

        m_copy.Copy(&retbuf, AV_PIX_FMT_RGB32, tmp, m_codecCtx->pix_fmt,
                    m_frameWidth, m_frameHeight);

        QImage img(m_outputbuf, m_frameWidth, m_frameHeight,
                   QImage::Format_RGB32);

        QByteArray ffile = m_frameFile.toLocal8Bit();
        if (!img.save(ffile.constData(), "JPEG"))
        {
            LOG(VB_GENERAL, LOG_ERR, "Failed to save thumb: " + m_frameFile);
        }

        if (m_updateFrame)
        {
            MythImage *mimage =
                GetMythMainWindow()->GetCurrentPainter()->GetFormatImage();
            mimage->Assign(img);
            m_frameImage->SetImage(mimage);
            mimage->DecrRef();
        }

        updateCurrentPos();
    }

    return true;
}
示例#27
0
void SubtitleScreen::DisplayAVSubtitles(void)
{
    if (!m_player || !m_subreader)
        return;

    AVSubtitles* subs = m_subreader->GetAVSubtitles();
    QMutexLocker lock(&(subs->lock));
    if (subs->buffers.empty() && (kDisplayAVSubtitle != m_subtitleType))
        return;

    VideoOutput    *videoOut = m_player->GetVideoOutput();
    VideoFrame *currentFrame = videoOut ? videoOut->GetLastShownFrame() : NULL;

    if (!currentFrame || !videoOut)
        return;

    float tmp = 0.0;
    QRect dummy;
    videoOut->GetOSDBounds(dummy, m_safeArea, tmp, tmp, tmp);

    while (!subs->buffers.empty())
    {
        const AVSubtitle subtitle = subs->buffers.front();
        if (subtitle.start_display_time > currentFrame->timecode)
            break;

        ClearDisplayedSubtitles();
        subs->buffers.pop_front();
        for (std::size_t i = 0; i < subtitle.num_rects; ++i)
        {
            AVSubtitleRect* rect = subtitle.rects[i];

            bool displaysub = true;
            if (subs->buffers.size() > 0 &&
                subs->buffers.front().end_display_time <
                currentFrame->timecode)
            {
                displaysub = false;
            }

            if (displaysub && rect->type == SUBTITLE_BITMAP)
            {
                // AVSubtitleRect's image data's not guaranteed to be 4 byte
                // aligned.

                QSize img_size(rect->w, rect->h);
                QRect img_rect(rect->x, rect->y, rect->w, rect->h);
                QRect display(rect->display_x, rect->display_y,
                              rect->display_w, rect->display_h);

                // XSUB and some DVD/DVB subs are based on the original video
                // size before the video was converted. We need to guess the
                // original size and allow for the difference

                int right  = rect->x + rect->w;
                int bottom = rect->y + rect->h;
                if (subs->fixPosition || (currentFrame->height < bottom) ||
                   (currentFrame->width  < right))
                {
                    int sd_height = 576;
                    if ((m_player->GetFrameRate() > 26.0f) && bottom <= 480)
                        sd_height = 480;
                    int height = ((currentFrame->height <= sd_height) &&
                                  (bottom <= sd_height)) ? sd_height :
                                 ((currentFrame->height <= 720) && bottom <= 720)
                                   ? 720 : 1080;
                    int width  = ((currentFrame->width  <= 720) &&
                                  (right <= 720)) ? 720 :
                                 ((currentFrame->width  <= 1280) &&
                                  (right <= 1280)) ? 1280 : 1920;
                    display = QRect(0, 0, width, height);
                }

                QRect scaled = videoOut->GetImageRect(img_rect, &display);
                QImage qImage(img_size, QImage::Format_ARGB32);
                for (int y = 0; y < rect->h; ++y)
                {
                    for (int x = 0; x < rect->w; ++x)
                    {
                        const uint8_t color = rect->pict.data[0][y*rect->pict.linesize[0] + x];
                        const uint32_t pixel = *((uint32_t*)rect->pict.data[1]+color);
                        qImage.setPixel(x, y, pixel);
                    }
                }

                if (scaled.size() != img_size)
                {
                    qImage = qImage.scaled(scaled.width(), scaled.height(),
                             Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
                }

                MythPainter *osd_painter = videoOut->GetOSDPainter();
                MythImage* image = NULL;
                if (osd_painter)
                   image = osd_painter->GetFormatImage();

                long long displayfor = subtitle.end_display_time -
                                       subtitle.start_display_time;
                if (displayfor == 0)
                    displayfor = 60000;
                displayfor = (displayfor < 50) ? 50 : displayfor;
                long long late = currentFrame->timecode -
                                 subtitle.start_display_time;
                MythUIImage *uiimage = NULL;
                if (image)
                {
                    image->Assign(qImage);
                    QString name = QString("avsub%1").arg(i);
                    uiimage = new MythUIImage(this, name);
                    if (uiimage)
                    {
                        m_refreshArea = true;
                        uiimage->SetImage(image);
                        uiimage->SetArea(MythRect(scaled));
                        m_expireTimes.insert(uiimage,
                                     currentFrame->timecode + displayfor);
                    }
                }
                if (uiimage)
                {
                    LOG(VB_PLAYBACK, LOG_INFO, LOC +
                        QString("Display %1AV subtitle for %2ms")
                        .arg(subtitle.forced ? "FORCED " : "")
                        .arg(displayfor));
                    if (late > 50)
                        LOG(VB_PLAYBACK, LOG_INFO, LOC +
                            QString("AV Sub was %1ms late").arg(late));
                }
            }
#ifdef USING_LIBASS
            else if (displaysub && rect->type == SUBTITLE_ASS)
            {
                InitialiseAssTrack(m_player->GetDecoder()->GetTrack(kTrackTypeSubtitle));
                AddAssEvent(rect->ass);
            }
#endif
        }
        m_subreader->FreeAVSubtitle(subtitle);
    }
#ifdef USING_LIBASS
    RenderAssTrack(currentFrame->timecode);
#endif
}
示例#28
0
/**
 * Update the various fields of a MythNotificationScreen.
 */
void MythNotificationScreen::Init(void)
{
    if (!m_refresh) // nothing got changed so far, return
        return;

    AdjustYPosition();

    if (m_artworkImage && (m_update & kImage))
    {
        if (!m_imagePath.isNull())
        {
            // We have a path to the image, use it
            m_artworkImage->SetFilename(m_imagePath);
            m_artworkImage->Load();
        }
        else if (!m_image.isNull())
        {
            // We don't have a path to the image, but the image itself
            MythImage *img = m_artworkImage->GetPainter()->GetFormatImage();
            img->Assign(m_image);
            m_artworkImage->SetImage(img);
            img->DecrRef();
        }
        else
        {
            // Will default to displaying whatever placeholder image is defined
            // in the xml by the themer, means we can show _something_ rather than
            // a big empty hole. Generally you always want to call Reset() in
            // these circumstances
            m_artworkImage->Reset();
        }
    }

    if (m_update != kNone)
    {
        InfoMap tmap;

        tmap["title"]               = m_title;
        if (m_update & kImage)
        {
            tmap["image"]           = m_imagePath;
        }
        tmap["origin"]              = m_origin;
        tmap["description"]         = m_description;
        tmap["extra"]               = m_extra;
        if (m_update & kDuration)
        {
            tmap["progress_text"]   = m_progresstext;
            tmap["progress"]        = QString("%1").arg((int)(m_progress * 100));
        }
        SetTextFromMap(tmap);
    }

    if (m_update & kMetaData)
    {
        if (m_titleText && m_title.isNull())
        {
            m_titleText->Reset();
        }
        if (m_originText && m_origin.isNull())
        {
            m_originText->Reset();
        }
        if (m_descriptionText && m_description.isNull())
        {
            m_descriptionText->Reset();
        }
        if (m_extraText && m_extra.isNull())
        {
            m_extraText->Reset();
        }
    }

    if (m_update & kDuration)
    {
        if (m_progresstextText && m_progresstext.isEmpty())
        {
            m_progresstextText->Reset();
        }
        if (m_progressBar)
        {
            if (m_progress >= 0)
            {
                m_progressBar->SetStart(0);
                m_progressBar->SetTotal(100);
                m_progressBar->SetUsed(100 * m_progress);
            }
            else
            {
                // Same as above, calling Reset() allows for a sane, themer defined
                //default to be displayed
                m_progressBar->Reset();
            }
        }
    }

    if (m_progressBar)
    {
        m_progressBar->SetVisible((m_content & kDuration) != 0);

    }

    SetErrorState();

    if (m_mediaState && (m_update & kImage))
    {
        m_mediaState->DisplayState(m_update & kNoArtwork ? "noartwork" : "ok");
        LOG(VB_GUI, LOG_DEBUG, LOC + QString("Init: Set media state to %1").arg(m_update & kNoArtwork ? "noartwork" : "ok"));
    }

    // No field will be refreshed the next time unless specified otherwise
    m_update = kNone;

    if (GetScreenStack() && !m_added)
    {
        GetScreenStack()->AddScreen(this);
        m_added = true;
    }
    m_refresh = false;
}
示例#29
0
void BDOverlayScreen::DisplayBDOverlay(BDOverlay *overlay)
{
    if (!overlay || !m_player)
        return;

    if (!overlay->m_data)
    {
        m_overlayArea = overlay->m_position;
        SetArea(MythRect(m_overlayArea));
        DeleteAllChildren();
        m_overlayMap.clear();
        SetRedraw();
        LOG(VB_PLAYBACK, LOG_INFO, LOC +
            QString("Initialised Size: %1x%2 (%3+%4) Plane: %5 Pts: %6")
                .arg(overlay->m_position.width())
                .arg(overlay->m_position.height())
                .arg(overlay->m_position.left())
                .arg(overlay->m_position.top())
                .arg(overlay->m_plane)
                .arg(overlay->m_pts));
        BDOverlay::DeleteOverlay(overlay);
        return;
    }

    if (!m_overlayArea.isValid())
    {
        LOG(VB_GENERAL, LOG_ERR, LOC +
            "Error: Overlay image submitted before initialisation.");
    }

    VideoOutput *vo = m_player->GetVideoOutput();
    if (!vo)
        return;

    QRect   rect = overlay->m_position;
    QString hash = QString("%1+%2+%3x%4")
                    .arg(rect.left()).arg(rect.top())
                    .arg(rect.width()).arg(rect.height());

    // remove if we already have this overlay
    if (m_overlayMap.contains(hash))
    {
        LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Removing %1 (%2 left)")
            .arg(hash).arg(m_overlayMap.size()));
        MythUIImage *old = m_overlayMap.take(hash);
        DeleteChild(old);
    }

    // convert the overlay palette to ARGB
    uint32_t *origpalette = (uint32_t *)(overlay->m_palette);
    QVector<unsigned int> palette;
    for (int i = 0; i < 256; i++)
    {
        int y  = (origpalette[i] >> 0) & 0xff;
        int cr = (origpalette[i] >> 8) & 0xff;
        int cb = (origpalette[i] >> 16) & 0xff;
        int a  = (origpalette[i] >> 24) & 0xff;
        int r  = int(y + 1.4022 * (cr - 128));
        int b  = int(y + 1.7710 * (cb - 128));
        int g  = int(1.7047 * y - (0.1952 * b) - (0.5647 * r));
        if (r < 0) r = 0;
        if (g < 0) g = 0;
        if (b < 0) b = 0;
        if (r > 0xff) r = 0xff;
        if (g > 0xff) g = 0xff;
        if (b > 0xff) b = 0xff;
        palette.push_back((a << 24) | (r << 16) | (g << 8) | b);
    }

    // convert the image to QImage
    QImage img(rect.size(), QImage::Format_Indexed8);
    memcpy(img.bits(), overlay->m_data, rect.width() * rect.height());
    img.setColorTable(palette);
    img.convertToFormat(QImage::Format_ARGB32);

    // add to screen
    QRect scaled = vo->GetImageRect(rect);
    if (scaled.size() != rect.size())
    {
        img = img.scaled(scaled.width(), scaled.height(),
                         Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    }

    MythPainter *osd_painter = vo->GetOSDPainter();
    MythImage* image = NULL;
    if (osd_painter)
         image = osd_painter->GetFormatImage();

    if (image)
    {
        image->Assign(img);
        MythUIImage *uiimage = new MythUIImage(this, "bdoverlay");
        if (uiimage)
        {
            uiimage->SetImage(image);
            uiimage->SetArea(MythRect(scaled));
            m_overlayMap.insert(hash, uiimage);
            LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Added %1 (%2 tot)")
                .arg(hash).arg(m_overlayMap.size()));
        }
    }

    SetRedraw();
    BDOverlay::DeleteOverlay(overlay);
}
示例#30
0
MythImage *MythUIHelper::LoadCacheImage(QString srcfile, QString label,
                                        MythPainter *painter,
                                        ImageCacheMode cacheMode)
{
    LOG(VB_GUI | VB_FILE, LOG_INFO, LOC +
        QString("LoadCacheImage(%1,%2)").arg(srcfile).arg(label));

    if (srcfile.isEmpty() || label.isEmpty())
        return NULL;

    if (!(kCacheForceStat & cacheMode))
    {
        // Some screens include certain images dozens or even hundreds of
        // times.  Even if the image is in the cache, there is still a
        // stat system call on the original file to see if it has changed.
        // This code relaxes the original-file check so that the check
        // isn't repeated if it was already done within kImageCacheTimeout
        // seconds.

        // This only applies to the MEMORY cache
        const uint kImageCacheTimeout = 60;
        uint now = MythDate::current().toTime_t();

        QMutexLocker locker(d->m_cacheLock);

        if (d->imageCache.contains(label) &&
            d->CacheTrack[label] + kImageCacheTimeout > now)
        {
            d->imageCache[label]->IncrRef();
            return d->imageCache[label];
        }
    }

    MythImage *ret = NULL;

    // Check Memory Cache
    ret = GetImageFromCache(label);

    // If the image is in the memory or we are not ignoring the disk cache
    // then proceed to check whether the source file is newer than our cached
    // copy
    if (ret || !(cacheMode & kCacheIgnoreDisk))
    {
        // Create url to image in disk cache
        QString cachefilepath = GetThemeCacheDir() + '/' + label;
        QFileInfo cacheFileInfo(cachefilepath);

        // If the file isn't in the disk cache, then we don't want to bother
        // checking the last modified times of the original
        if (!cacheFileInfo.exists())
            return NULL;

        // Now compare the time on the source versus our cached copy
        QDateTime srcLastModified;

        // For internet images this involves querying the headers of the remote
        // image. This is slow even without redownloading the whole image
        if ((srcfile.startsWith("http://")) ||
            (srcfile.startsWith("https://")) ||
            (srcfile.startsWith("ftp://")))
        {
            // If the image is in the memory cache then skip the last modified
            // check, since memory cached images are loaded in the foreground
            // this can cause an intolerable delay. The images won't stay in
            // the cache forever and so eventually they will be checked.
            if (ret)
                srcLastModified = cacheFileInfo.lastModified();
            else
            {
                srcLastModified =
                    GetMythDownloadManager()->GetLastModified(srcfile);
            }
        }
        else if (srcfile.startsWith("myth://"))
            srcLastModified = RemoteFile::LastModified(srcfile);
        else
        {
            if (!FindThemeFile(srcfile))
                return NULL;

            QFileInfo original(srcfile);

            if (original.exists())
                srcLastModified = original.lastModified();
        }

        // Now compare the timestamps, if the cached image is newer than the
        // source image we can use it, otherwise we want to remove it from the
        // cache
        if (cacheFileInfo.lastModified() >= srcLastModified)
        {
            // If we haven't already loaded the image from the memory cache
            // and we're not ignoring the disk cache, then it's time to load
            // it from there instead
            if (!ret && (cacheMode == kCacheNormal))
            {

                if (painter)
                    ret = painter->GetFormatImage();

                // Load file from disk cache to memory cache
                if (ret->Load(cachefilepath))
                {
                    // Add to ram cache, and skip saving to disk since that is
                    // where we found this in the first place.
                    CacheImage(label, ret, true);
                }
                else
                {
                    LOG(VB_GUI | VB_FILE, LOG_WARNING, LOC +
                        QString("LoadCacheImage: Could not load :%1")
                        .arg(cachefilepath));

                    ret->SetIsInCache(false);
                    ret->DecrRef();
                    ret = NULL;
                }
            }
        }
        else
        {
            ret = NULL;
            // If file has changed on disk, then remove it from the memory
            // and disk cache
            RemoveFromCacheByURL(label);
        }
    }

    return ret;
}