我尝试使用Libav解码.mkv文件中的h.264流,因此我必须使用一个函数来读取容器中stream [i]存在的地址。我想将整个流存储在某个位置的缓冲区中,以应用例如parse_nal_units函数(我无法使用av_read_frame进行读取,因为我不知道一个帧有多长)。据我所知,fread仅从文件读取,并且我没有文件,只有地址。解决此问题的最佳方法是什么?
而不是//将输入文件中的一帧读取到一个临时包中。 while(!(ret = av_read_frame(ifmt_ctx,&input_packet))&&(ret> = 0))我应该在缓冲区中读取整个流,然后通过h264解析器对其进行解析。
这里有一些代码
for (i = 0; i < ifmt_ctx->nb_streams; i++)
{
AVStream *in_stream = ifmt_ctx->streams[i], *out_stream ;
AVCodec *pCodec = NULL, *oCodec = NULL;
AVCodecParameters *inpar;
AVCodecContext *avctx= NULL, *oavctx= NULL;
AVPacket input_packet;
AVFrame *iframe = NULL, *oframe = NULL;
AVCodecParserContext *parser = NULL;
const uint8_t *poutbuf;
int poutbuf_size;
int *finished;
//------------------------------Decode----------------------------------
//Find decoder pCodec
if (!(pCodec =avcodec_find_decoder(in_stream->codecpar->codec_id))){
fprintf(stderr, "Could not find input codec\n");
//avformat_close_input(input_format_context);
return AVERROR_EXIT;
}
// Allocate a new decoding context.
avctx = avcodec_alloc_context3(pCodec);
if (!avctx) {
fprintf(stderr, "Could not allocate a decoding context\n");
avformat_close_input(ifmt_ctx);
return AVERROR(ENOMEM);
}
// Initialize the stream parameters with demuxer information.
ret = avcodec_parameters_to_context(avctx, ifmt_ctx->streams[i]->codecpar);
if (ret < 0) {
avformat_close_input(ifmt_ctx);
avcodec_free_context(&avctx);
return ret;
}
//Open the decoder
if ((ret = avcodec_open2(avctx, pCodec, NULL)) < 0) {
fprintf(stderr, "Could not open input codec (error '%s')\n",
get_error_text(ret));
avcodec_free_context(&avctx);
avformat_close_input(ifmt_ctx);
return ret;
}
//Prepare data
if (!(iframe = av_frame_alloc())) {
fprintf(stderr, "Could not allocate input frame\n");
return AVERROR(ENOMEM);
}
parser = av_parser_init(pCodec->id);
if (!parser) {
fprintf(stderr, "parser not found\n");
exit(1);
}
//----------------------Decode & Encode---------------------------
switch (pCodec->type) {
case AVMEDIA_TYPE_VIDEO:
//------------------Set encoder format and context-----------------------
// Find the encoder to be used by its ID.
if (!(oCodec = avcodec_find_encoder(AV_CODEC_ID_MPEG4))) {
fprintf(stderr, "Could not find an AV_CODEC_ID_MPEG4 encoder.\n");
goto end;
}
init_packet(&input_packet);
// Read one frame from the input file into a temporary packet.
while(!(ret = av_read_frame(ifmt_ctx, &input_packet))&&(ret>=0)){
ret = av_parser_parse2(parser, avctx, &poutbuf, &poutbuf_size, (&input_packet)->data, (&input_packet)->size,
AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
if (ret < 0) {
fprintf(stderr, "Error while parsing\n");
exit(1);
}
if ((ret = avcodec_send_packet(avctx, &input_packet)) < 0) {
fprintf(stderr, "Could not send packet for decoding (error '%s')\n",get_error_text(ret));
return ret;
}
ret = avcodec_receive_frame(avctx, iframe);
if (ret == AVERROR(EAGAIN)) {
goto read_another_frame;
/* If the end of the input file is reached, stop decoding. */
} else if (ret == AVERROR_EOF) {
break;
} else if (ret < 0) {
fprintf(stderr, "Could not decode frame (error '%s')\n",get_error_text(ret));
break;
}
// Default case: encode data
else {
}
read_another_frame:
av_packet_unref(&input_packet);
}
if (ret == AVERROR_EOF)
*finished = 1;
else {
fprintf(stderr, "Could not read frame (error '%s')\n",
get_error_text(ret));
return ret;
}
break;
谢谢