Domanda

Apprezzerei molto qualche aiuto con il seguente numero:

Ho un gadget con una fotocamera, che produce fotogrammi video compressi H264, questi frame vengono inviati alla mia applicazione. Questi frame non sono in un contenitore, solo dati grezzi.

Voglio utilizzare le funzioni FFMPEG e Libav per creare un file video, che può essere utilizzato in seguito.

Se decodifico i frame, quindi codifica, tutto funziona bene, ottengo un file video valido. (I passaggi decodifica/codifica sono i soliti comandi libv, niente di speciale qui, li ho presi dall'onnipotente Internet, sono solidi in roccia) ... Tuttavia, perdo molto tempo decodificando e codifica, quindi mi piacerebbe farlo Salta questo passaggio e metti direttamente i frame nel flusso di output. Ora, i problemi arrivano.

Ecco il codice che mi è venuto in mente per produrre la codifica:

AVFrame* picture;

avpicture_fill((AVPicture*) picture, (uint8_t*)frameData, 
                 codecContext->pix_fmt, codecContext->width,
                 codecContext->height);
int outSize = avcodec_encode_video(codecContext, videoOutBuf, 
                 sizeof(videoOutBuf), picture);
if (outSize > 0) 
{
    AVPacket packet;
    av_init_packet(&packet);
    packet.pts = av_rescale_q(codecContext->coded_frame->pts,
                  codecContext->time_base, videoStream->time_base);
    if (codecContext->coded_frame->key_frame) 
    {
        packet.flags |= PKT_FLAG_KEY;
    }
    packet.stream_index = videoStream->index;
    packet.data =  videoOutBuf;
    packet.size =  outSize;

    av_interleaved_write_frame(context, &packet);
    put_flush_packet(context->pb);
}

Dove sono le variabili:

frameData è i dati del frame decodificato, provenienti dalla fotocamera, sono stati decodificati in un passaggio precedente e videoOutBuf è un semplice buffer Uint8_t per tenere i dati

Ho modificato l'applicazione per non decodificare i frame, ma semplicemente passare attraverso i dati come:

    AVPacket packet;
    av_init_packet(&packet);

    packet.stream_index = videoStream->index;
    packet.data = (uint8_t*)frameData;
    packet.size = currentFrameSize;

    av_interleaved_write_frame(context, &packet);
    put_flush_packet(context->pb);

dove

frameData è il frame H264 grezzo e currentFrameSize è la dimensione del telaio H264 grezzo, cioè. Il numero di byte che ottengo dal gadget per ogni frame.

E improvvisamente l'applicazione non funziona più correttamente, il video prodotto è ingiocabile. Questo è ovvio, dal momento che non stavo impostando un PTS corretto per il pacchetto. Quello che ho fatto è stato il seguente (sono disperato, puoi vederlo da questo approccio :))

    packet.pts = timestamps[timestamp_counter ++];

dove timestamps è in realtà un elenco di PT prodotto dal codice di lavoro sopra e scritto in un file (sì, lo hai letto correttamente, ho registrato tutti i PT per una sessione di 10 minuti e volevo usarli).

L'applicazione non funziona ancora.

Ora, eccomi qui senza idea di cosa fare, quindi ecco la domanda:

Vorrei creare un flusso video "MPEGTS" utilizzando le funzioni LiBav, inserire nel flusso già codificato i fotogrammi video e creare un file video con esso. Come lo faccio?

Grazie, f.

Nessuna soluzione corretta

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top