I have written a routine that converts a file from one file format to
another - the code is very strongly based on output_example.c. A
problem occurs the second time I attempt to encode a buffer that has
been read and decoded from the input file. avcodec_encode_video always
returns -1. This always happen on the second call - regardless of the
input file. Can someone please explain what I am doing wrong?
The routine code is as follows:
int frameFinished;
AVFormatContext* pInputFormatCtx;
AVFrame* pInputFrame;
AVPacket inputPacket;
AVCodec* pInputVideoCodec;
AVCodecContext* pInputVideoCodecCtx;
int inputVideoStreamPos = -1;
uint8_t* pOutputBuffer;
AVOutputFormat* pOutputFormat;
AVFormatContext* pOutputFormatCtx;
AVCodec* pOutputVideoCodec;
AVCodecContext* pOutputVideoCodecCtx;
AVStream* pOutputVideoStream;
av_register_all();
// Open the input file
if (av_open_input_file(&pInputFormatCtx, pInput, NULL, 0,
NULL) != 0) return FileConverterEngine::UnableToOpenInputFile;
try
{
// Get the stream information
if (av_find_stream_info(pInputFormatCtx) < 0) return
FileConverterEngine::UnableToRetrieveStreamInformation;
for (unsigned int i=0; i < pInputFormatCtx->nb_streams; i++)
{
if (pInputFormatCtx->streams[i]->codec->codec_type ==
CODEC_TYPE_VIDEO)
{
inputVideoStreamPos = i;
break;
}
}
if (inputVideoStreamPos == -1) return
FileConverterEngine::MissingVideoStream;
// Get the codec context for the stream
pInputVideoCodecCtx =
pInputFormatCtx->streams[inputVideoStreamPos]->codec;
// Get the codec to decode the video
pInputVideoCodec =
avcodec_find_decoder(pInputVideoCodecCtx->codec_id);
if (pInputVideoCodec == NULL) return
FileConverterEngine::UnableToFindVideoDecoder;
// Open the codec
if (avcodec_open(pInputVideoCodecCtx, pInputVideoCodec) <
0) return FileConverterEngine::UnableToOpenVideoDecoder;
try
{
// What format is the output file?
if ((pOutputFormat = guess_format(NULL, pOutput, NULL)) == NULL)
{
if ((pOutputFormat = guess_format("mpeg", NULL,
NULL)) == NULL) return FileConverterEngine::CannotGuessOutputFormat;
}
// Allocate the output file context
if ((pOutputFormatCtx = av_alloc_format_context()) ==
NULL) return FileConverterEngine::CannotAllocateOutputFileContext;
try
{
// Associate it with the output context
pOutputFormatCtx->oformat = pOutputFormat;
// Save the filename
_snprintf_s(pOutputFormatCtx->filename,
sizeof(pOutputFormatCtx->filename), _TRUNCATE, "%s", pOutput);
// Add the video stream to the output file
if ((pOutputVideoStream = AddVideoStream(pOutputFormatCtx,
pOutputFormat->video_codec)) == NULL)
return
FileConverterEngine::CannotAddVideoStreamToOutputFile;
// Set-up the output video stream
pOutputVideoCodecCtx = pOutputVideoStream->codec;
pOutputVideoCodecCtx->width = pInputVideoCodecCtx->width;
pOutputVideoCodecCtx->height = pInputVideoCodecCtx->height;
pOutputVideoCodecCtx->pix_fmt =
pInputVideoCodecCtx->pix_fmt;
// Set the output parameters
if (av_set_parameters(pOutputFormatCtx, NULL) < 0)
return FileConverterEngine::UnableToSetOutputParameters;
// Get the output video codec
if (!(pOutputVideoCodec =
avcodec_find_encoder(pOutputVideoStream->codec->codec_id)))
return FileConverterEngine::UnableToFindVideoEncoder;
// Open the output video codec
if (avcodec_open(pOutputVideoCodecCtx,
pOutputVideoCodec) < 0) return
FileConverterEngine::UnableToOpenVideoEncoder;
try
{
// Open the output file (if needed)
if (!(pOutputFormat->flags & AVFMT_NOFILE))
{
if (url_fopen(&pOutputFormatCtx->pb,
pOutput, URL_WRONLY) < 0) return
FileConverterEngine::UnableToOpenOutputFile;
}
try
{
// Create the buffer to hold the encoded frame
int buffer_size =
avpicture_get_size(pOutputVideoCodecCtx->pix_fmt,
pOutputVideoCodecCtx->width, pOutputVideoCodecCtx->height);
pOutputBuffer = (uint8_t*)av_malloc(buffer_size);
// Write the headers to the output file
av_write_header(pOutputFormatCtx);
// Allocate the input frame
pInputFrame = avcodec_alloc_frame();
try
{
while (av_read_frame(pInputFormatCtx,
&inputPacket) >= 0)
{
if (inputPacket.stream_index ==
inputVideoStreamPos)
{
// Decode the video frame
if
(avcodec_decode_video(pInputVideoCodecCtx, pInputFrame,
&frameFinished, inputPacket.data, inputPacket.size) < 0)
return
FileConverterEngine::UnableToDecodeInputVideoPacket;
if (frameFinished)
{
// Encode the video frame (always
returns -1 the second time this line is executed)
int out_size =
avcodec_encode_video(pOutputVideoCodecCtx, pOutputBuffer, buffer_size,
pInputFrame);
}
// Free the packet
av_free_packet(&inputPacket);
}
}
}
finally
{
av_free(pInputFrame);
}
// Write the trailer
av_write_trailer(pOutputFormatCtx);
}
finally
{
if (!(pOutputFormat->flags & AVFMT_NOFILE))
{
url_fclose(pOutputFormatCtx->pb);
}
}
}
finally
{
avcodec_close(pOutputVideoCodecCtx);
}
}
finally
{
av_free(pOutputFormatCtx);
}
}
finally
{
avcodec_close(pInputVideoCodecCtx);
}
}
finally
{
av_close_input_file(pInputFormatCtx);
}
_______________________________________________
libav-user mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/libav-user