ffmpeg
Dekodierung
Suche…
Einführung
Holen Sie sich das rohe Video / Audio aus codierten Medienströmen.
Finde einen Stream
Medien-Stream-Container verfügen normalerweise über mehrere Streams, beispielsweise einen Videostream und einen Audiostream. Zum Beispiel können Sie den Audiostream folgendermaßen erhalten:
// A Format Context - see Reading Data for more info
AVFormatContext *formatContext;
// Inspect packets of stream to determine properties
if (avformat_find_stream_info(formatContext, NULL) < 0){
// Error finding info
}
// Find the stream and its codec
AVCodec* audioCodec;
int audioStreamIndex = av_find_best_stream(
formatContext, // The media stream
AVMEDIA_TYPE_AUDIO, // The type of stream we are looking for - audio for example
-1, // Desired stream number, -1 for any
-1, // Number of related stream, -1 for none
&audioCodec, // Gets the codec associated with the stream, can be NULL
0 // Flags - not used currently
);
if(audioStreamIndex = AVERROR_STREAM_NOT_FOUND || !audioCodec){
// Error finding audio (ie. no audio stream?)
}
Um andere Stream-Typen zu erhalten, müssen Sie nur den Stream-Typ ersetzen. Folgende Typen sind gültig:
AVMEDIA_TYPE_VIDEO,
AVMEDIA_TYPE_AUDIO,
AVMEDIA_TYPE_SUBTITLE,
AVMEDIA_TYPE_DATA, // Usually continuous
AVMEDIA_TYPE_ATTACHMENT, // Usually sparse
Öffnen Sie einen Codec-Kontext
Wenn Sie einen Stream-Format-Kontext und den zugehörigen Codec haben, können Sie ihn mit folgendem Code zum Dekodieren öffnen:
// The format context and codec, given - see Find a stream for how to get these
AVFormatContext *formatContext;
AVCodec* codec;
int streamIndex;
// Get the codec context
AVCodecContext *codecContext = avcodec_alloc_context3(codec);
if (!codecContext){
// Out of memory
avformat_close_input(&formatContext);
}
// Set the parameters of the codec context from the stream
int result = avcodec_parameters_to_context(
codecContext,
formatContext->streams[streamIndex]->codecpar
);
if(result < 0){
// Failed to set parameters
avformat_close_input(&formatContext);
avcodec_free_context(&codecContext);
}
// Ready to open stream based on previous parameters
// Third parameter (NULL) is optional dictionary settings
if (avcodec_open2(codecContext, codec, NULL) < 0){
// Cannot open the video codec
codecContext = nullptr;
}
// Do something with the opened codec context... (ie decode frames through the context)
Frames dekodieren
Mit einem Codec-Kontext und codierten Paketen aus einem Medienstrom können Sie beginnen, Medien in Raw-Frames zu decodieren. Um einen einzelnen Frame zu decodieren, können Sie den folgenden Code verwenden:
// A codec context, and some encoded data packet from a stream/file, given.
AVCodecContext *codecContext; // See Open a codec context
AVPacket *packet; // See the Reading Media topic
// Send the data packet to the decoder
int sendPacketResult = avcodec_send_packet(codecContext, packet);
if (sendPacketResult == AVERROR(EAGAIN)){
// Decoder can't take packets right now. Make sure you are draining it.
}else if (sendPacketResult < 0){
// Failed to send the packet to the decoder
}
// Get decoded frame from decoder
AVFrame *frame = av_frame_alloc();
int decodeFrame = avcodec_receive_frame(codecContext, frame);
if (decodeFrame == AVERROR(EAGAIN)){
// The decoder doesn't have enough data to produce a frame
// Not an error unless we reached the end of the stream
// Just pass more packets until it has enough to produce a frame
av_frame_unref(frame);
av_freep(frame);
}else if (decodeFrame < 0){
// Failed to get a frame from the decoder
av_frame_unref(frame);
av_freep(frame);
}
// Use the frame (ie. display it)
Wenn Sie alle Frames decodieren möchten, können Sie den vorherigen Code einfach in einer Schleife platzieren und aufeinander folgende Pakete einführen.