/*! * \brief Read the albumart image from the file * * \param filename The filename for which we want to find the length. * \param type The type of image we want - front/back etc * \returns A pointer to a QImage owned by the caller or NULL if not found. */ QImage* MetaIOID3::getAlbumArt(QString filename, ImageType type) { QImage *picture = new QImage(); AttachedPictureFrame::Type apicType = AttachedPictureFrame::FrontCover; switch (type) { case IT_UNKNOWN : apicType = AttachedPictureFrame::Other; break; case IT_FRONTCOVER : apicType = AttachedPictureFrame::FrontCover; break; case IT_BACKCOVER : apicType = AttachedPictureFrame::BackCover; break; case IT_CD : apicType = AttachedPictureFrame::Media; break; case IT_INLAY : apicType = AttachedPictureFrame::LeafletPage; break; default: return picture; } QByteArray fname = filename.toLocal8Bit(); TagLib::MPEG::File *mpegfile = new TagLib::MPEG::File(fname.constData()); if (mpegfile) { if (mpegfile->isOpen() && !mpegfile->ID3v2Tag()->frameListMap()["APIC"].isEmpty()) { TagLib::ID3v2::FrameList apicframes = mpegfile->ID3v2Tag()->frameListMap()["APIC"]; for(TagLib::ID3v2::FrameList::Iterator it = apicframes.begin(); it != apicframes.end(); ++it) { AttachedPictureFrame *frame = static_cast<AttachedPictureFrame *>(*it); if (frame && frame->type() == apicType) { picture->loadFromData((const uchar *)frame->picture().data(), frame->picture().size()); return picture; } } } delete mpegfile; } delete picture; return NULL; }
/*! * \brief Read the albumart image from the file * * \param filename The filename for which we want to find the albumart. * \param type The type of image we want - front/back etc * \returns A pointer to a QImage owned by the caller or nullptr if not found. */ QImage* MetaIOID3::getAlbumArt(const QString &filename, ImageType type) { QImage *picture = new QImage(); AttachedPictureFrame::Type apicType = AttachedPictureFrame::FrontCover; switch (type) { case IT_UNKNOWN : apicType = AttachedPictureFrame::Other; break; case IT_FRONTCOVER : apicType = AttachedPictureFrame::FrontCover; break; case IT_BACKCOVER : apicType = AttachedPictureFrame::BackCover; break; case IT_CD : apicType = AttachedPictureFrame::Media; break; case IT_INLAY : apicType = AttachedPictureFrame::LeafletPage; break; case IT_ARTIST : apicType = AttachedPictureFrame::Artist; break; default: return picture; } if (OpenFile(filename)) { TagLib::ID3v2::Tag *tag = GetID3v2Tag(); if (tag && !tag->frameListMap()["APIC"].isEmpty()) { TagLib::ID3v2::FrameList apicframes = tag->frameListMap()["APIC"]; for(TagLib::ID3v2::FrameList::Iterator it = apicframes.begin(); it != apicframes.end(); ++it) { AttachedPictureFrame *frame = static_cast<AttachedPictureFrame *>(*it); if (frame && frame->type() == apicType) { picture->loadFromData((const uchar *)frame->picture().data(), frame->picture().size()); return picture; } } } } delete picture; return nullptr; }
/*! * \brief Find an APIC tag by type and optionally description * * \param tag Pointer to TagLib::ID3v2::Tag object * \param type Type of picture to search for * \param description Description of picture to search for (optional) * \returns Pointer to frame */ AttachedPictureFrame* MetaIOID3::findAPIC(TagLib::ID3v2::Tag *tag, const AttachedPictureFrame::Type &type, const String &description) { TagLib::ID3v2::FrameList l = tag->frameList("APIC"); for(TagLib::ID3v2::FrameList::Iterator it = l.begin(); it != l.end(); ++it) { AttachedPictureFrame *f = static_cast<AttachedPictureFrame *>(*it); if (f && f->type() == type && (description.isNull() || f->description() == description)) return f; } return nullptr; }
void ID3v2::Tag::setAlbumArt(const ByteVector &v, ID3v2::AttachedPictureFrame::Type arttype, String &mimetype) { if (v.isEmpty()) { removeFrames("APIC"); return; } else { if (!d->frameListMap["APIC"].isEmpty()) { removeFrames("APIC"); } else { // do nothing } AttachedPictureFrame *f = new AttachedPictureFrame("APIC"); f->setMimeType(mimetype); f->setType(arttype); f->setPicture(v); addFrame(f); } return; }
Frame *FrameFactory::createFrame(const ByteVector &data, uint version) const { Frame::Header *header = new Frame::Header(data, version); ByteVector frameID = header->frameID(); // A quick sanity check -- make sure that the frameID is 4 uppercase Latin1 // characters. Also make sure that there is data in the frame. if(!frameID.size() == (version < 3 ? 3 : 4) || header->frameSize() <= 0 || header->frameSize() > data.size()) { delete header; return 0; } for(ByteVector::ConstIterator it = frameID.begin(); it != frameID.end(); it++) { if( (*it < 'A' || *it > 'Z') && (*it < '1' || *it > '9') ) { delete header; return 0; } } // TagLib doesn't mess with encrypted frames, so just treat them // as unknown frames. #if HAVE_ZLIB == 0 if(header->compression()) { debug("Compressed frames are currently not supported."); return new UnknownFrame(data, header); } #endif if(header->encryption()) { debug("Encrypted frames are currently not supported."); return new UnknownFrame(data, header); } if(!updateFrame(header)) { header->setTagAlterPreservation(true); return new UnknownFrame(data, header); } // updateFrame() might have updated the frame ID. frameID = header->frameID(); // This is where things get necissarily nasty. Here we determine which // Frame subclass (or if none is found simply an Frame) based // on the frame ID. Since there are a lot of possibilities, that means // a lot of if blocks. // Text Identification (frames 4.2) if(frameID.startsWith("T")) { TextIdentificationFrame *f = frameID != "TXXX" ? new TextIdentificationFrame(data, header) : new UserTextIdentificationFrame(data, header); if(d->useDefaultEncoding) f->setTextEncoding(d->defaultEncoding); if(frameID == "TCON") updateGenre(f); return f; } // Comments (frames 4.10) if(frameID == "COMM") { CommentsFrame *f = new CommentsFrame(data, header); if(d->useDefaultEncoding) f->setTextEncoding(d->defaultEncoding); return f; } // Attached Picture (frames 4.14) if(frameID == "APIC") { AttachedPictureFrame *f = new AttachedPictureFrame(data, header); if(d->useDefaultEncoding) f->setTextEncoding(d->defaultEncoding); return f; } // Relative Volume Adjustment (frames 4.11) if(frameID == "RVA2") return new RelativeVolumeFrame(data, header); // Unique File Identifier (frames 4.1) if(frameID == "UFID") return new UniqueFileIdentifierFrame(data, header); // General Encapsulated Object (frames 4.15) if(frameID == "GEOB") return new GeneralEncapsulatedObjectFrame(data, header); return new UnknownFrame(data, header); }
bool MetaIOID3::changeImageType(const QString &filename, const AlbumArtImage* albumart, ImageType newType) { if (!albumart) return false; if (albumart->m_imageType == newType) return true; AttachedPictureFrame::Type type = AttachedPictureFrame::Other; switch (albumart->m_imageType) { case IT_FRONTCOVER: type = AttachedPictureFrame::FrontCover; break; case IT_BACKCOVER: type = AttachedPictureFrame::BackCover; break; case IT_CD: type = AttachedPictureFrame::Media; break; case IT_INLAY: type = AttachedPictureFrame::LeafletPage; break; case IT_ARTIST: type = AttachedPictureFrame::Artist; break; default: type = AttachedPictureFrame::Other; break; } if (!OpenFile(filename, true)) return false; TagLib::ID3v2::Tag *tag = GetID3v2Tag(); if (!tag) return false; AttachedPictureFrame *apic = findAPIC(tag, type, QStringToTString(albumart->m_description)); if (!apic) return false; // set the new image type switch (newType) { case IT_FRONTCOVER: apic->setType(AttachedPictureFrame::FrontCover); break; case IT_BACKCOVER: apic->setType(AttachedPictureFrame::BackCover); break; case IT_CD: apic->setType(AttachedPictureFrame::Media); break; case IT_INLAY: apic->setType(AttachedPictureFrame::LeafletPage); break; case IT_ARTIST: apic->setType(AttachedPictureFrame::Artist); break; default: apic->setType(AttachedPictureFrame::Other); break; } if (!SaveFile()) return false; return true; }
/*! * \brief Write the albumart image to the file * * \param filename The music file to add the albumart * \param albumart The Album Art image to write * \returns True if successful * * \note We always save the image in JPEG format */ bool MetaIOID3::writeAlbumArt(const QString &filename, const AlbumArtImage *albumart) { if (filename.isEmpty() || !albumart) return false; // load the image into a QByteArray QImage image(albumart->m_filename); QByteArray imageData; QBuffer buffer(&imageData); buffer.open(QIODevice::WriteOnly); image.save(&buffer, "JPEG"); AttachedPictureFrame::Type type = AttachedPictureFrame::Other; switch (albumart->m_imageType) { case IT_FRONTCOVER: type = AttachedPictureFrame::FrontCover; break; case IT_BACKCOVER: type = AttachedPictureFrame::BackCover; break; case IT_CD: type = AttachedPictureFrame::Media; break; case IT_INLAY: type = AttachedPictureFrame::LeafletPage; break; case IT_ARTIST: type = AttachedPictureFrame::Artist; break; default: type = AttachedPictureFrame::Other; break; } if (!OpenFile(filename, true)) return false; TagLib::ID3v2::Tag *tag = GetID3v2Tag(); if (!tag) return false; AttachedPictureFrame *apic = findAPIC(tag, type, QStringToTString(albumart->m_description)); if (!apic) { apic = new AttachedPictureFrame(); tag->addFrame(apic); apic->setType(type); } QString mimetype = "image/jpeg"; TagLib::ByteVector bytevector; bytevector.setData(imageData.data(), imageData.size()); apic->setMimeType(QStringToTString(mimetype)); apic->setPicture(bytevector); apic->setDescription(QStringToTString(albumart->m_description)); if (!SaveFile()) return false; return true; }
/*! * \brief Read the albumart images from the file * * \param tag The ID3v2 tag object in which to look for Album Art * \returns A QList containing a list of AlbumArtImage's * with the type and description of the APIC tag. */ AlbumArtList MetaIOID3::readAlbumArt(TagLib::ID3v2::Tag *tag) { AlbumArtList artlist; if (!tag->frameListMap()["APIC"].isEmpty()) { TagLib::ID3v2::FrameList apicframes = tag->frameListMap()["APIC"]; for(TagLib::ID3v2::FrameList::Iterator it = apicframes.begin(); it != apicframes.end(); ++it) { AttachedPictureFrame *frame = static_cast<AttachedPictureFrame *>(*it); // Assume a valid image would have at least // 100 bytes of data (1x1 indexed gif is 35 bytes) if (frame->picture().size() < 100) { LOG(VB_GENERAL, LOG_NOTICE, "Music Scanner - Discarding APIC frame " "with size less than 100 bytes"); continue; } AlbumArtImage *art = new AlbumArtImage(); if (frame->description().isEmpty()) art->m_description.clear(); else art->m_description = TStringToQString(frame->description()); art->m_embedded = true; art->m_hostname = gCoreContext->GetHostName(); QString ext = getExtFromMimeType( TStringToQString(frame->mimeType()).toLower()); switch (frame->type()) { case AttachedPictureFrame::FrontCover : art->m_imageType = IT_FRONTCOVER; art->m_filename = QString("front") + ext; break; case AttachedPictureFrame::BackCover : art->m_imageType = IT_BACKCOVER; art->m_filename = QString("back") + ext; break; case AttachedPictureFrame::Media : art->m_imageType = IT_CD; art->m_filename = QString("cd") + ext; break; case AttachedPictureFrame::LeafletPage : art->m_imageType = IT_INLAY; art->m_filename = QString("inlay") + ext; break; case AttachedPictureFrame::Artist : art->m_imageType = IT_ARTIST; art->m_filename = QString("artist") + ext; break; case AttachedPictureFrame::Other : art->m_imageType = IT_UNKNOWN; art->m_filename = QString("unknown") + ext; break; default: LOG(VB_GENERAL, LOG_ERR, "Music Scanner - APIC tag found " "with unsupported type"); delete art; continue; } artlist.append(art); } } return artlist; }
int internel_decoder::get_attached_images(char* url,stream_context *streamcontext){ stream_context *sc = streamcontext; AVInputFormat *format = sc->pFormatCtx->iformat; if(strcmp(format->name,"mp3") == 0){ sc->is_mp3 = 1; } /// If attached image of mp3 is not detected by ffmpeg then we use taglib to extract the attached image if(strcmp(format->name,"mp3") == 0 && sc->videostream == -1){ TagLib::MPEG::File mp3File(url); Tag * mp3Tag; FrameList listOfMp3Frames; AttachedPictureFrame * pictureFrame; AVPacket packet; //av_init_packet(&packet); mp3Tag= mp3File.ID3v2Tag(); if(mp3Tag) { listOfMp3Frames = mp3Tag->frameListMap()["APIC"]; if(!listOfMp3Frames.isEmpty()) { FrameList::ConstIterator it= listOfMp3Frames.begin(); // for(; it != listOfMp3Frames.end() ; it++) // { pictureFrame = static_cast<AttachedPictureFrame *> (*it); //cout <<"mime-type:"<<pictureFrame->mimeType()<<endl; AVCodec *codec; const char *mime_attached = pictureFrame->mimeType().toCString(false); const CodecMime *mime = ff_id3v2_mime_tags; while (mime->id != AV_CODEC_ID_NONE) { if (!av_strncasecmp(mime->str, mime_attached, sizeof(mime_attached))) { codec = avcodec_find_decoder(mime->id); cout <<"mime-type:"<<mime->str<<endl; break; } mime++; } if(mime->id != AV_CODEC_ID_NONE){ av_new_packet (&packet, pictureFrame->picture().size()); memcpy(packet.data,pictureFrame->picture().data(),pictureFrame->picture().size()); // packet.data = (uint8_t*)pictureFrame->picture().data(); packet.size = pictureFrame->picture().size(); packet.flags = AV_PKT_FLAG_KEY; pthread_mutex_lock(&sc->videolock); sc->videobuffer.push(packet); pthread_mutex_unlock(&sc->videolock); sc->videoctx = avcodec_alloc_context3(NULL); avcodec_open2(sc->videoctx,codec, NULL); sc->attachedimage = 1; AVFrame *frame = avcodec_alloc_frame(); int decode_ok; int len; while(true){ len = avcodec_decode_video2(sc->videoctx, frame, &decode_ok, &packet); if(decode_ok || len < 0){ break; } } if(len < 0){ sc->videoctx->width = 0; sc->videoctx->height = 0; sc->height = 0; sc->width = 0; av_free(frame); return -1; }else{ cout <<frame->height<<" - "<<frame->width<<endl; sc->videoctx->width = frame->width; sc->videoctx->height = frame->height; sc->height = frame->height; sc->width = frame->width; av_free(frame); } }else{ return -1; } //break; // } } else{ return -1; } } else { return -1; } } return 0; }