Ich versuche, eine kleine App zu erstellen, die Frames von Inoming h264 Stream speichern wird. Ich nahm ein TestRTSP-Programm als Beispiel und machte mehrere Änderungen in DummySink::afterGettingFrame
Funktion, um Frames mit Hilfe von ffmpeg Bibliothek zu decodieren. Wie ich von frameSize verstehe, sind meine ersten beiden Frames SPS-Einheiten, so dass ich sie mit meinem dritten Frame verkette und dann einen neuen großen Frame an den ffmpeg-Decoder sende. Aber das funktioniert nicht. ffmpeg sagt mir, dass mein erster Frame zu groß für SPS ist und dann sagt er mir, dass es keinen Frame gibt ... Ich weiß nicht, was ich hier ändern muss.LIVE555 wie h264 Framer-Klasse zu verwenden, um nal Einheiten für ffmpeg
void DummySink::afterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes,
struct timeval presentationTime, unsigned /*durationInMicroseconds*/)
{
u_int8_t start_code[4] = { 0x00, 0x00, 0x00, 0x01 };
int stCodeLen = 4;
if (frameSize == 50)
{
//add start code
memcpy(bufferWithStartCode, start_code, stCodeLen);
shiftPtr += stCodeLen;
memcpy(bufferWithStartCode + shiftPtr, fReceiveBuffer, frameSize);
shiftPtr += frameSize;
}
else if (frameSize == 4)
{
memcpy(bufferWithStartCode + shiftPtr, fReceiveBuffer, frameSize);
shiftPtr += frameSize;
}
else
{
if (shiftPtr == 0)
{
memcpy(bufferWithStartCode, start_code, stCodeLen);
shiftPtr += stCodeLen;
}
memcpy(bufferWithStartCode + shiftPtr, fReceiveBuffer, frameSize);
avpkt.size = frameSize + shiftPtr;
avpkt.data = bufferWithStartCode;
shiftPtr = 0;
if (!avcodec_send_packet(cContext, &avpkt))
{
envir() << "error sending to decoder";
}
if (!avcodec_receive_frame(cContext, picture))
{
envir() << "error rx from decoder";
}
if (picture)
{
FILE *f;
char buffer[32]; // The filename buffer.
snprintf(buffer, sizeof(char) * 32, "file%i.txt", frame_num);
f = fopen(buffer, "w");
fprintf(f, "P5\n%d %d\n%d\n", fSubsession.videoWidth(), fSubsession.videoHeight(), 255);
for (int i = 0;i < fSubsession.videoHeight();i++)
fwrite(picture->data[0] + i * (picture->linesize[0]), 1, fSubsession.videoWidth(), f);
fclose(f);
}
}
envir() << frameSize << "\n";
frame_num++;
// Then continue, to request the next frame of data:
continuePlaying();
Sind SPS- und PPS-Daten 50 und 4 Byte groß? Vielleicht sind das meine ersten beiden "Frames"? Und wie könnte ich zwei verschiedene Variablen in "Extradata" referenzieren? – Aleksey
Die Größe von sps und pps ist nicht so festgelegt, wie in der gelöschten Antwort erwähnt, Sie können keine Annahmen basierend auf der Größe machen - Sie müssen den tatsächlichen nal-Typ überprüfen (die fünf rechten Bits des ersten Bytes in der NAL-Einheit).Wie für die "Extradata" - wenn mein Speicher korrekt ist, übergeben Sie sie einfach in einem einzigen Puffer geteilt durch den Präfix-Code, den Sie bereits verwenden, und setzen Sie die 'extradata_size' entsprechend. Übrigens, wenn Sie möchten, dass ffmpeg den Stream entschlüsselt, warum nicht auch ffmpeg (avio_open) für die RTSP-Behandlung verwenden? Dann hättest du dich nicht darum kümmern müssen und alles würde intern erledigt werden. –