FFMPEG and av_open_input_stream

Started by
2 comments, last by arthur__ 12 years, 1 month ago
Hello,

I try to read a mpeg2 video from a stream with ffmpeg library. In my first tests, I tried to read from a byte buffer, but now I read directly from a file (in my ReadPacket function) in order to be sure it's right data.
I tried many way to do that, but av_open_input_stream function return always -1.
I post my code here and hope someone could help me ! If someone have a full code to do that, i''ll be happy to see it. Thanks.

av_log_set_level(AV_LOG_VERBOSE);
avcodec_init();
av_register_all();
avcodec_register_all();

pFormatCtx = avformat_alloc_context();
if (!pFormatCtx)
{
return -1;
}

FILE* f = fopen("D:\\projets\\test_data\\video\\video_ts.mpg", "rb");

int bioBufferSize = 8000;
unsigned char *bioBuffer = (unsigned char *)av_malloc(bioBufferSize + FF_INPUT_BUFFER_PADDING_SIZE);
ByteIOContext *bioContext = new ByteIOContext();
int ret = init_put_byte(bioContext, bioBuffer, bioBufferSize, 0, (void *)f, readPackets, NULL, seekPackets);

AVFormatParameters params, *ap = &params;
memset(ap, 0, sizeof(*ap));
ap->prealloced_context = 1

//pFormatCtx->video_codec_id = findCodecOrDie("mpeg2video", AVMEDIA_TYPE_VIDEO, 0, avcodecOpts[AVMEDIA_TYPE_VIDEO]->strict_std_compliance);
//pFormatCtx->flags |= AVFMT_FLAG_NONBLOCK;
AVInputFormat *inputFormat = av_find_input_format("mpegts");
//pFormatCtx->iformat = inputFormat;

ret = av_open_input_stream(&pFormatCtx, bioContext, "stream", inputFormat, ap);

av_close_input_stream(pFormatCtx);
av_free(bioBuffer);
delete bioContext;
fclose(f);

[...]


And my readPacket func :


static int readPackets(void *opaque, uint8_t *buf, int buf_size)
{
FILE* f = (FILE *)opaque;
int read = fread(buf, 1, buf_size, f);
return read;
}
Advertisement
Why not use FFmpeg to open the video file? I hate giving out code, but this is what I use to open and play video files. It accepts anything FFmpeg can read, not just mpeg2video. It's a copy 'n' paste of a small portion of my code, and for my personal purposes I just needed the frame to be an 8-bit gray frame so I convert all frames to 8-bit gray. If there's a particular part you have a question about, feel free to ask. Otherwise, I'm going to assume the code is self-explanatory.


Video::Video(const std::string& filename) : imageConvertContext(NULL),
buffer(NULL),
grayFrame(NULL),
frame(NULL),
codecContext(NULL),
formatContext(NULL),
videoStreamIndex(-1),
endReached(true),
scaledWidth(0),
scaledHeight(0),
currentFrameNumber(-1)
{
int errorCode = 0;

if ((errorCode = avformat_open_input(&formatContext, filename.c_str(), NULL, NULL)) != 0)
{
throw std::runtime_error("Unable to open the stream");
}

if ((errorCode = avformat_find_stream_info(formatContext, NULL)) < 0)
{
throw std::runtime_error("Unable to find the stream's info");
}

for (unsigned int i = 0; i < formatContext->nb_streams; ++i)
{
if (formatContext->streams->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoStreamIndex = i;
break;
}
}

if (videoStreamIndex == -1)
{
throw std::runtime_error("Unable to find a video stream");
}

codecContext = formatContext->streams[videoStreamIndex]->codec;
codec = avcodec_find_decoder(codecContext->codec_id);
if (codec == NULL)
{
throw std::runtime_error("Unsupported codec");
}

if ((errorCode = avcodec_open2(codecContext, codec, NULL)) != 0)
{
throw std::runtime_error("Error opening the codec");
}

frameRate = formatContext->streams[videoStreamIndex]->avg_frame_rate;
if (!frameRate.num || ! frameRate.den)
{
throw std::runtime_error("This video does not have a constant frame rate");
}

//TODO: if one of these fail, we should release what has succeeded
frame = avcodec_alloc_frame();
grayFrame = avcodec_alloc_frame();
if (frame == NULL || grayFrame == NULL)
{
throw std::runtime_error("Unable to allocate frame memory");
}

int numBytes = avpicture_get_size(PIX_FMT_GRAY8, codecContext->width, codecContext->height);
buffer = (uint8_t*)av_malloc(numBytes * sizeof(uint8_t));

avpicture_fill((AVPicture*)grayFrame, buffer, PIX_FMT_GRAY8, codecContext->width, codecContext->height);

imageConvertContext = sws_getContext(codecContext->width,
codecContext->height,
codecContext->pix_fmt,
codecContext->width,
codecContext->height,
PIX_FMT_GRAY8,
SWS_FAST_BILINEAR,
NULL,
NULL,
NULL);

scaledWidth = codecContext->width;
scaledHeight = codecContext->height;

endReached = false;
}

Video::~Video()
{
sws_freeContext(imageConvertContext);
av_free_packet(&packet);
av_free(buffer);
av_free(grayFrame);
av_free(frame);
avcodec_close(codecContext);
av_close_input_file(formatContext);
}

const AVFrame* Video::getNextFrame()
{
while (av_read_frame(formatContext, &packet) == 0)
{
int frameFinished = 0;
if (packet.stream_index == videoStreamIndex)
{
avcodec_decode_video2(codecContext, frame, &frameFinished, &packet);
if (frameFinished)
{
sws_scale(imageConvertContext,
frame->data,
frame->linesize,
0,
frame->height,
grayFrame->data,
grayFrame->linesize);

++currentFrameNumber;
return grayFrame;
}
}
}

endReached = true;
return NULL;
}
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]
Thanks for your reply;
I want to read from stream (in a char *buffer), but as it not work I changed my buffer by reading directly the file, that's why I use [color=#000000][size=2]

av_open_input_stream.

I have already tried to open my file with av_open_input_file and it's work, but it's not my goal here.
Problem solved ! I compiled with ffmpeg static library and it works !

This topic is closed to new replies.

Advertisement