Le décodage h264 des images à partir de flux RTP
Je suis en utilisant live555 et des bibliothèques ffmpeg pour obtenir et décoder RTP H264 flux de serveur; flux Vidéo a été codée par ffmpeg, à l'aide de profil de Base et
x264_param_default_preset(m_params, "veryfast", "zerolatency")
J'ai lu cette rubrique et ajouter SPS et PPS de données dans la chaque image que je reçois de réseau;
void ClientSink::NewFrameHandler(unsigned frameSize, unsigned numTruncatedBytes,
timeval presentationTime, unsigned durationInMicroseconds)
{
...
EncodedFrame tmp;
tmp.m_frame = std::vector<unsigned char>(m_tempBuffer.data(), m_tempBuffer.data() + frameSize);
tmp.m_duration = durationInMicroseconds;
tmp.m_pts = presentationTime;
//Add SPS and PPS data into the frame; TODO: some devices may send SPS and PPs data already into frame;
tmp.m_frame.insert(tmp.m_frame.begin(), m_spsPpsData.cbegin(), m_spsPpsData.cend());
emit newEncodedFrame( SharedEncodedFrame(tmp) );
m_frameCounter++;
this->continuePlaying();
}
Et ce images que je reçois dans le décodeur.
bool H264Decoder::decodeFrame(SharedEncodedFrame orig_frame)
{
...
while(m_packet.size > 0)
{
int got_picture;
int len = avcodec_decode_video2(m_decoderContext, m_picture, &got_picture, &m_packet);
if (len < 0)
{
emit criticalError(QString("Decoding error"));
return false;
}
if (got_picture)
{
std::vector<unsigned char> result;
this->storePicture(result);
if ( m_picture->format == AVPixelFormat::AV_PIX_FMT_YUV420P )
{
//QImage img = QImage(result.data(), m_picture->width, m_picture->height, QImage::Format_RGB888);
Frame_t result_rgb;
if (!convert_yuv420p_to_rgb32(result, m_picture->width, m_picture->height, result_rgb))
{
emit criticalError( QString("Failed to convert YUV420p image into rgb32; can't create QImage!"));
return false;
}
unsigned char* copy_img = new unsigned char[result_rgb.size()];
//this needed because QImage shared buffer, which used, and it will crash, if i use this qimage after result_rgb deleting
std::copy(result_rgb.cbegin(), result_rgb.cend(), copy_img);
QImage img = QImage(copy_img, m_picture->width, m_picture->height, QImage::Format_RGB32,
[](void* array)
{
delete[] array;
}, copy_img);
img.save(QString("123.bmp"));
emit newDecodedFrame(img);
}
avcodec_decode_video2 décoder les trames sans aucun message d'erreur, mais trames décodées, après la conversion de celui-ci (de yuv420p en rgb32) n'est pas valide. Exemple d'image disponible sur ce lien
Avez-vous des idées de ce que je fais de mal?
OriginalL'auteur Dmitry Bakhtiyarov | 2013-09-17
Vous devez vous connecter pour publier un commentaire.
Je crois que l'erreur est dans le convert_yuv420p_to_rgb32() code. Essayez ceci:
Vous aurez besoin d'inclure/lien swscale si vous ne l'avez pas fait déjà.
Remarque: vous n'avez pas besoin SPS/PPS chaque image (sur des images clés est assez bon). Mais il ne fait pas de mal non plus.
Pas sûr, mais je devine qu'il a à faire avec la façon dont vous êtes l'insertion SPS/PPS. Est le codeur de produire plus que l'on tranche par image? Si oui, l'insertion de la SPS/PPS int le milieu de l'UA, le décodeur doit penser le cadre achève avant.
Je ne sais pas combien de tranches par frame l'encodeur produire(comment je peux vérifier ça?). Mais toutes les images d'entrée ne sont pas fragmentés - je utiliser la fonction "int fragment_type = Data[0] & 0x1F;" et fragment_type est pas égal à 28. Si j'ajoute SPS et PPS de données pour le début de frame - décodeur décode seulement la moitié de l'image 🙁 Si je ne suis pas d'ajouter SPS et PPS décodeur ne pas décoder n'importe quelle image;
Ok. J'ai corrigé le problème. - Je ajouter cette ligne au décodeur méthode d'initialisation: m_decoderContext->flags2 |= CODEC_FLAG2_CHUNKS;
OriginalL'auteur szatmary
Ok. Mon exemple simple, qui décoder le H264 stream, qui a reçu du liveMedia de la bibliothèque. Il peut décoder des images, qui sont tronqués non seulement à la limite de cadres.
Et c'est réalisation:
- Je envoyer newDecodedFrame de thread GUI, où ce QImage sera tiré à un certain widget.
P. S: Ce commentaire est très long pour poster en commentaire du commentaire
OriginalL'auteur Dmitry Bakhtiyarov