fixed some problems after r8280 (lost code)
This commit is contained in:
@@ -622,9 +622,6 @@ void cv::gpu::ORB_GPU::computeDescriptors(GpuMat& descriptors)
|
|||||||
if (keyPointsCount_[level] == 0)
|
if (keyPointsCount_[level] == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (keyPointsCount_[level] == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
GpuMat descRange = descriptors.rowRange(offset, offset + keyPointsCount_[level]);
|
GpuMat descRange = descriptors.rowRange(offset, offset + keyPointsCount_[level]);
|
||||||
|
|
||||||
if (blurForDescriptor)
|
if (blurForDescriptor)
|
||||||
|
@@ -375,7 +375,7 @@ TEST_P(FarnebackOpticalFlow, Accuracy)
|
|||||||
|
|
||||||
EXPECT_MAT_SIMILAR(flowxy[0], d_flowx, 0.1);
|
EXPECT_MAT_SIMILAR(flowxy[0], d_flowx, 0.1);
|
||||||
EXPECT_MAT_SIMILAR(flowxy[1], d_flowy, 0.1);
|
EXPECT_MAT_SIMILAR(flowxy[1], d_flowy, 0.1);
|
||||||
};
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_CASE_P(GPU_Video, FarnebackOpticalFlow, testing::Combine(
|
INSTANTIATE_TEST_CASE_P(GPU_Video, FarnebackOpticalFlow, testing::Combine(
|
||||||
ALL_DEVICES,
|
ALL_DEVICES,
|
||||||
@@ -413,4 +413,116 @@ TEST_P(OpticalFlowNan, Regression)
|
|||||||
|
|
||||||
INSTANTIATE_TEST_CASE_P(GPU_Video, OpticalFlowNan, ALL_DEVICES);
|
INSTANTIATE_TEST_CASE_P(GPU_Video, OpticalFlowNan, ALL_DEVICES);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// VideoWriter
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
PARAM_TEST_CASE(VideoWriter, cv::gpu::DeviceInfo, std::string)
|
||||||
|
{
|
||||||
|
cv::gpu::DeviceInfo devInfo;
|
||||||
|
std::string inputFile;
|
||||||
|
|
||||||
|
std::string outputFile;
|
||||||
|
|
||||||
|
virtual void SetUp()
|
||||||
|
{
|
||||||
|
devInfo = GET_PARAM(0);
|
||||||
|
inputFile = GET_PARAM(1);
|
||||||
|
|
||||||
|
cv::gpu::setDevice(devInfo.deviceID());
|
||||||
|
|
||||||
|
inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "video/" + inputFile;
|
||||||
|
outputFile = inputFile.substr(0, inputFile.find('.')) + "_test.avi";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_P(VideoWriter, Regression)
|
||||||
|
{
|
||||||
|
const double FPS = 25.0;
|
||||||
|
|
||||||
|
cv::VideoCapture reader(inputFile);
|
||||||
|
ASSERT_TRUE( reader.isOpened() );
|
||||||
|
|
||||||
|
cv::gpu::VideoWriter_GPU d_writer;
|
||||||
|
|
||||||
|
cv::Mat frame;
|
||||||
|
std::vector<cv::Mat> frames;
|
||||||
|
cv::gpu::GpuMat d_frame;
|
||||||
|
|
||||||
|
for (int i = 1; i < 10; ++i)
|
||||||
|
{
|
||||||
|
reader >> frame;
|
||||||
|
|
||||||
|
if (frame.empty())
|
||||||
|
break;
|
||||||
|
|
||||||
|
frames.push_back(frame.clone());
|
||||||
|
d_frame.upload(frame);
|
||||||
|
|
||||||
|
if (!d_writer.isOpened())
|
||||||
|
d_writer.open(outputFile, frame.size(), FPS);
|
||||||
|
|
||||||
|
d_writer.write(d_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.release();
|
||||||
|
d_writer.close();
|
||||||
|
|
||||||
|
reader.open(outputFile);
|
||||||
|
ASSERT_TRUE( reader.isOpened() );
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; ++i)
|
||||||
|
{
|
||||||
|
reader >> frame;
|
||||||
|
ASSERT_FALSE( frame.empty() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_CASE_P(GPU_Video, VideoWriter, testing::Combine(
|
||||||
|
ALL_DEVICES,
|
||||||
|
testing::Values(std::string("VID00003-20100701-2204.mpg"), std::string("big_buck_bunny.mpg"))));
|
||||||
|
|
||||||
|
#endif // WIN32
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// VideoReader
|
||||||
|
|
||||||
|
PARAM_TEST_CASE(VideoReader, cv::gpu::DeviceInfo, std::string)
|
||||||
|
{
|
||||||
|
cv::gpu::DeviceInfo devInfo;
|
||||||
|
std::string inputFile;
|
||||||
|
|
||||||
|
virtual void SetUp()
|
||||||
|
{
|
||||||
|
devInfo = GET_PARAM(0);
|
||||||
|
inputFile = GET_PARAM(1);
|
||||||
|
|
||||||
|
cv::gpu::setDevice(devInfo.deviceID());
|
||||||
|
|
||||||
|
inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "video/" + inputFile;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_P(VideoReader, Regression)
|
||||||
|
{
|
||||||
|
cv::gpu::VideoReader_GPU reader(inputFile);
|
||||||
|
ASSERT_TRUE( reader.isOpened() );
|
||||||
|
|
||||||
|
cv::gpu::GpuMat frame;
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; ++i)
|
||||||
|
{
|
||||||
|
ASSERT_TRUE( reader.read(frame) );
|
||||||
|
ASSERT_FALSE( frame.empty() );
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.close();
|
||||||
|
ASSERT_FALSE( reader.isOpened() );
|
||||||
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_CASE_P(GPU_Video, VideoReader, testing::Combine(
|
||||||
|
ALL_DEVICES,
|
||||||
|
testing::Values(std::string("VID00003-20100701-2204.mpg"))));
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@@ -1565,3 +1565,528 @@ int cvWriteFrame_FFMPEG( CvVideoWriter_FFMPEG* writer,
|
|||||||
return writer->writeFrame(data, step, width, height, cn, origin);
|
return writer->writeFrame(data, step, width, height, cn, origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For CUDA encoder
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct OutputMediaStream_FFMPEG
|
||||||
|
{
|
||||||
|
bool open(const char* fileName, int width, int height, double fps);
|
||||||
|
void close();
|
||||||
|
|
||||||
|
void write(unsigned char* data, int size, int keyFrame);
|
||||||
|
|
||||||
|
// add a video output stream to the container
|
||||||
|
static AVStream* addVideoStream(AVFormatContext *oc, CodecID codec_id, int w, int h, int bitrate, double fps, PixelFormat pixel_format);
|
||||||
|
|
||||||
|
AVOutputFormat* fmt_;
|
||||||
|
AVFormatContext* oc_;
|
||||||
|
AVStream* video_st_;
|
||||||
|
};
|
||||||
|
|
||||||
|
void OutputMediaStream_FFMPEG::close()
|
||||||
|
{
|
||||||
|
// no more frame to compress. The codec has a latency of a few
|
||||||
|
// frames if using B frames, so we get the last frames by
|
||||||
|
// passing the same picture again
|
||||||
|
|
||||||
|
// TODO -- do we need to account for latency here?
|
||||||
|
|
||||||
|
if (oc_)
|
||||||
|
{
|
||||||
|
// write the trailer, if any
|
||||||
|
av_write_trailer(oc_);
|
||||||
|
|
||||||
|
// free the streams
|
||||||
|
for (unsigned int i = 0; i < oc_->nb_streams; ++i)
|
||||||
|
{
|
||||||
|
av_freep(&oc_->streams[i]->codec);
|
||||||
|
av_freep(&oc_->streams[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(fmt_->flags & AVFMT_NOFILE) && oc_->pb)
|
||||||
|
{
|
||||||
|
// close the output file
|
||||||
|
|
||||||
|
#if LIBAVCODEC_VERSION_INT < ((52<<16)+(123<<8)+0)
|
||||||
|
#if LIBAVCODEC_VERSION_INT >= ((51<<16)+(49<<8)+0)
|
||||||
|
url_fclose(oc_->pb);
|
||||||
|
#else
|
||||||
|
url_fclose(&oc_->pb);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
avio_close(oc_->pb);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// free the stream
|
||||||
|
av_free(oc_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AVStream* OutputMediaStream_FFMPEG::addVideoStream(AVFormatContext *oc, CodecID codec_id, int w, int h, int bitrate, double fps, PixelFormat pixel_format)
|
||||||
|
{
|
||||||
|
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 10, 0)
|
||||||
|
AVStream* st = avformat_new_stream(oc, 0);
|
||||||
|
#else
|
||||||
|
AVStream* st = av_new_stream(oc, 0);
|
||||||
|
#endif
|
||||||
|
if (!st)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#if LIBAVFORMAT_BUILD > 4628
|
||||||
|
AVCodecContext* c = st->codec;
|
||||||
|
#else
|
||||||
|
AVCodecContext* c = &(st->codec);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
c->codec_id = codec_id;
|
||||||
|
c->codec_type = AVMEDIA_TYPE_VIDEO;
|
||||||
|
|
||||||
|
// put sample parameters
|
||||||
|
unsigned long long lbit_rate = static_cast<unsigned long long>(bitrate);
|
||||||
|
lbit_rate += (bitrate / 4);
|
||||||
|
lbit_rate = std::min(lbit_rate, static_cast<unsigned long long>(std::numeric_limits<int>::max()));
|
||||||
|
c->bit_rate = bitrate;
|
||||||
|
|
||||||
|
// took advice from
|
||||||
|
// http://ffmpeg-users.933282.n4.nabble.com/warning-clipping-1-dct-coefficients-to-127-127-td934297.html
|
||||||
|
c->qmin = 3;
|
||||||
|
|
||||||
|
// resolution must be a multiple of two
|
||||||
|
c->width = w;
|
||||||
|
c->height = h;
|
||||||
|
|
||||||
|
AVCodec* codec = avcodec_find_encoder(c->codec_id);
|
||||||
|
|
||||||
|
// time base: this is the fundamental unit of time (in seconds) in terms
|
||||||
|
// of which frame timestamps are represented. for fixed-fps content,
|
||||||
|
// timebase should be 1/framerate and timestamp increments should be
|
||||||
|
// identically 1
|
||||||
|
|
||||||
|
int frame_rate = static_cast<int>(fps+0.5);
|
||||||
|
int frame_rate_base = 1;
|
||||||
|
while (fabs(static_cast<double>(frame_rate)/frame_rate_base) - fps > 0.001)
|
||||||
|
{
|
||||||
|
frame_rate_base *= 10;
|
||||||
|
frame_rate = static_cast<int>(fps*frame_rate_base + 0.5);
|
||||||
|
}
|
||||||
|
c->time_base.den = frame_rate;
|
||||||
|
c->time_base.num = frame_rate_base;
|
||||||
|
|
||||||
|
#if LIBAVFORMAT_BUILD > 4752
|
||||||
|
// adjust time base for supported framerates
|
||||||
|
if (codec && codec->supported_framerates)
|
||||||
|
{
|
||||||
|
AVRational req = {frame_rate, frame_rate_base};
|
||||||
|
const AVRational* best = NULL;
|
||||||
|
AVRational best_error = {INT_MAX, 1};
|
||||||
|
|
||||||
|
for (const AVRational* p = codec->supported_framerates; p->den!=0; ++p)
|
||||||
|
{
|
||||||
|
AVRational error = av_sub_q(req, *p);
|
||||||
|
|
||||||
|
if (error.num < 0)
|
||||||
|
error.num *= -1;
|
||||||
|
|
||||||
|
if (av_cmp_q(error, best_error) < 0)
|
||||||
|
{
|
||||||
|
best_error= error;
|
||||||
|
best= p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c->time_base.den= best->num;
|
||||||
|
c->time_base.num= best->den;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
c->gop_size = 12; // emit one intra frame every twelve frames at most
|
||||||
|
c->pix_fmt = pixel_format;
|
||||||
|
|
||||||
|
if (c->codec_id == CODEC_ID_MPEG2VIDEO)
|
||||||
|
c->max_b_frames = 2;
|
||||||
|
|
||||||
|
if (c->codec_id == CODEC_ID_MPEG1VIDEO || c->codec_id == CODEC_ID_MSMPEG4V3)
|
||||||
|
{
|
||||||
|
// needed to avoid using macroblocks in which some coeffs overflow
|
||||||
|
// this doesnt happen with normal video, it just happens here as the
|
||||||
|
// motion of the chroma plane doesnt match the luma plane
|
||||||
|
|
||||||
|
// avoid FFMPEG warning 'clipping 1 dct coefficients...'
|
||||||
|
|
||||||
|
c->mb_decision = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LIBAVCODEC_VERSION_INT > 0x000409
|
||||||
|
// some formats want stream headers to be seperate
|
||||||
|
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
|
||||||
|
{
|
||||||
|
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OutputMediaStream_FFMPEG::open(const char* fileName, int width, int height, double fps)
|
||||||
|
{
|
||||||
|
fmt_ = 0;
|
||||||
|
oc_ = 0;
|
||||||
|
video_st_ = 0;
|
||||||
|
|
||||||
|
// tell FFMPEG to register codecs
|
||||||
|
av_register_all();
|
||||||
|
|
||||||
|
av_log_set_level(AV_LOG_ERROR);
|
||||||
|
|
||||||
|
// auto detect the output format from the name and fourcc code
|
||||||
|
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
|
||||||
|
fmt_ = av_guess_format(NULL, fileName, NULL);
|
||||||
|
#else
|
||||||
|
fmt_ = guess_format(NULL, fileName, NULL);
|
||||||
|
#endif
|
||||||
|
if (!fmt_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CodecID codec_id = CODEC_ID_H264;
|
||||||
|
|
||||||
|
// alloc memory for context
|
||||||
|
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
|
||||||
|
oc_ = avformat_alloc_context();
|
||||||
|
#else
|
||||||
|
oc_ = av_alloc_format_context();
|
||||||
|
#endif
|
||||||
|
if (!oc_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// set some options
|
||||||
|
oc_->oformat = fmt_;
|
||||||
|
snprintf(oc_->filename, sizeof(oc_->filename), "%s", fileName);
|
||||||
|
|
||||||
|
oc_->max_delay = (int)(0.7 * AV_TIME_BASE); // This reduces buffer underrun warnings with MPEG
|
||||||
|
|
||||||
|
// set a few optimal pixel formats for lossless codecs of interest..
|
||||||
|
PixelFormat codec_pix_fmt = PIX_FMT_YUV420P;
|
||||||
|
int bitrate_scale = 64;
|
||||||
|
|
||||||
|
// TODO -- safe to ignore output audio stream?
|
||||||
|
video_st_ = addVideoStream(oc_, codec_id, width, height, width * height * bitrate_scale, fps, codec_pix_fmt);
|
||||||
|
if (!video_st_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// set the output parameters (must be done even if no parameters)
|
||||||
|
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
|
||||||
|
if (av_set_parameters(oc_, NULL) < 0)
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// now that all the parameters are set, we can open the audio and
|
||||||
|
// video codecs and allocate the necessary encode buffers
|
||||||
|
|
||||||
|
#if LIBAVFORMAT_BUILD > 4628
|
||||||
|
AVCodecContext* c = (video_st_->codec);
|
||||||
|
#else
|
||||||
|
AVCodecContext* c = &(video_st_->codec);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
c->codec_tag = MKTAG('H', '2', '6', '4');
|
||||||
|
c->bit_rate_tolerance = c->bit_rate;
|
||||||
|
|
||||||
|
// open the output file, if needed
|
||||||
|
if (!(fmt_->flags & AVFMT_NOFILE))
|
||||||
|
{
|
||||||
|
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
|
||||||
|
int err = url_fopen(&oc_->pb, fileName, URL_WRONLY);
|
||||||
|
#else
|
||||||
|
int err = avio_open(&oc_->pb, fileName, AVIO_FLAG_WRITE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (err != 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write the stream header, if any
|
||||||
|
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
|
||||||
|
av_write_header(oc_);
|
||||||
|
#else
|
||||||
|
avformat_write_header(oc_, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OutputMediaStream_FFMPEG::write(unsigned char* data, int size, int keyFrame)
|
||||||
|
{
|
||||||
|
// if zero size, it means the image was buffered
|
||||||
|
if (size > 0)
|
||||||
|
{
|
||||||
|
AVPacket pkt;
|
||||||
|
av_init_packet(&pkt);
|
||||||
|
|
||||||
|
if (keyFrame)
|
||||||
|
pkt.flags |= PKT_FLAG_KEY;
|
||||||
|
|
||||||
|
pkt.stream_index = video_st_->index;
|
||||||
|
pkt.data = data;
|
||||||
|
pkt.size = size;
|
||||||
|
|
||||||
|
// write the compressed frame in the media file
|
||||||
|
av_write_frame(oc_, &pkt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct OutputMediaStream_FFMPEG* create_OutputMediaStream_FFMPEG(const char* fileName, int width, int height, double fps)
|
||||||
|
{
|
||||||
|
OutputMediaStream_FFMPEG* stream = (OutputMediaStream_FFMPEG*) malloc(sizeof(OutputMediaStream_FFMPEG));
|
||||||
|
|
||||||
|
if (stream->open(fileName, width, height, fps))
|
||||||
|
return stream;
|
||||||
|
|
||||||
|
stream->close();
|
||||||
|
free(stream);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void release_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream)
|
||||||
|
{
|
||||||
|
stream->close();
|
||||||
|
free(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream, unsigned char* data, int size, int keyFrame)
|
||||||
|
{
|
||||||
|
stream->write(data, size, keyFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For CUDA decoder
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
VideoCodec_MPEG1 = 0,
|
||||||
|
VideoCodec_MPEG2,
|
||||||
|
VideoCodec_MPEG4,
|
||||||
|
VideoCodec_VC1,
|
||||||
|
VideoCodec_H264,
|
||||||
|
VideoCodec_JPEG,
|
||||||
|
VideoCodec_H264_SVC,
|
||||||
|
VideoCodec_H264_MVC,
|
||||||
|
|
||||||
|
// Uncompressed YUV
|
||||||
|
VideoCodec_YUV420 = (('I'<<24)|('Y'<<16)|('U'<<8)|('V')), // Y,U,V (4:2:0)
|
||||||
|
VideoCodec_YV12 = (('Y'<<24)|('V'<<16)|('1'<<8)|('2')), // Y,V,U (4:2:0)
|
||||||
|
VideoCodec_NV12 = (('N'<<24)|('V'<<16)|('1'<<8)|('2')), // Y,UV (4:2:0)
|
||||||
|
VideoCodec_YUYV = (('Y'<<24)|('U'<<16)|('Y'<<8)|('V')), // YUYV/YUY2 (4:2:2)
|
||||||
|
VideoCodec_UYVY = (('U'<<24)|('Y'<<16)|('V'<<8)|('Y')), // UYVY (4:2:2)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
VideoChromaFormat_Monochrome = 0,
|
||||||
|
VideoChromaFormat_YUV420,
|
||||||
|
VideoChromaFormat_YUV422,
|
||||||
|
VideoChromaFormat_YUV444,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InputMediaStream_FFMPEG
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool open(const char* fileName, int* codec, int* chroma_format, int* width, int* height);
|
||||||
|
void close();
|
||||||
|
|
||||||
|
bool read(unsigned char** data, int* size, int* endOfFile);
|
||||||
|
|
||||||
|
private:
|
||||||
|
InputMediaStream_FFMPEG(const InputMediaStream_FFMPEG&);
|
||||||
|
InputMediaStream_FFMPEG& operator =(const InputMediaStream_FFMPEG&);
|
||||||
|
|
||||||
|
AVFormatContext* ctx_;
|
||||||
|
int video_stream_id_;
|
||||||
|
AVPacket pkt_;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool InputMediaStream_FFMPEG::open(const char* fileName, int* codec, int* chroma_format, int* width, int* height)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
ctx_ = 0;
|
||||||
|
video_stream_id_ = -1;
|
||||||
|
memset(&pkt_, 0, sizeof(AVPacket));
|
||||||
|
|
||||||
|
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 13, 0)
|
||||||
|
avformat_network_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// register all codecs, demux and protocols
|
||||||
|
av_register_all();
|
||||||
|
|
||||||
|
av_log_set_level(AV_LOG_ERROR);
|
||||||
|
|
||||||
|
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 6, 0)
|
||||||
|
err = avformat_open_input(&ctx_, fileName, 0, 0);
|
||||||
|
#else
|
||||||
|
err = av_open_input_file(&ctx_, fileName, 0, 0, 0);
|
||||||
|
#endif
|
||||||
|
if (err < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 3, 0)
|
||||||
|
err = avformat_find_stream_info(ctx_, 0);
|
||||||
|
#else
|
||||||
|
err = av_find_stream_info(ctx_);
|
||||||
|
#endif
|
||||||
|
if (err < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < ctx_->nb_streams; ++i)
|
||||||
|
{
|
||||||
|
#if LIBAVFORMAT_BUILD > 4628
|
||||||
|
AVCodecContext *enc = ctx_->streams[i]->codec;
|
||||||
|
#else
|
||||||
|
AVCodecContext *enc = &ctx_->streams[i]->codec;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (enc->codec_type == AVMEDIA_TYPE_VIDEO)
|
||||||
|
{
|
||||||
|
video_stream_id_ = static_cast<int>(i);
|
||||||
|
|
||||||
|
switch (enc->codec_id)
|
||||||
|
{
|
||||||
|
case CODEC_ID_MPEG1VIDEO:
|
||||||
|
*codec = ::VideoCodec_MPEG1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CODEC_ID_MPEG2VIDEO:
|
||||||
|
*codec = ::VideoCodec_MPEG2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CODEC_ID_MPEG4:
|
||||||
|
*codec = ::VideoCodec_MPEG4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CODEC_ID_VC1:
|
||||||
|
*codec = ::VideoCodec_VC1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CODEC_ID_H264:
|
||||||
|
*codec = ::VideoCodec_H264;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (enc->pix_fmt)
|
||||||
|
{
|
||||||
|
case PIX_FMT_YUV420P:
|
||||||
|
*chroma_format = ::VideoChromaFormat_YUV420;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PIX_FMT_YUV422P:
|
||||||
|
*chroma_format = ::VideoChromaFormat_YUV422;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PIX_FMT_YUV444P:
|
||||||
|
*chroma_format = ::VideoChromaFormat_YUV444;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*width = enc->coded_width;
|
||||||
|
*height = enc->coded_height;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (video_stream_id_ < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
av_init_packet(&pkt_);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputMediaStream_FFMPEG::close()
|
||||||
|
{
|
||||||
|
if (ctx_)
|
||||||
|
{
|
||||||
|
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 24, 2)
|
||||||
|
avformat_close_input(&ctx_);
|
||||||
|
#else
|
||||||
|
av_close_input_file(ctx_);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// free last packet if exist
|
||||||
|
if (pkt_.data)
|
||||||
|
av_free_packet(&pkt_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InputMediaStream_FFMPEG::read(unsigned char** data, int* size, int* endOfFile)
|
||||||
|
{
|
||||||
|
// free last packet if exist
|
||||||
|
if (pkt_.data)
|
||||||
|
av_free_packet(&pkt_);
|
||||||
|
|
||||||
|
// get the next frame
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int ret = av_read_frame(ctx_, &pkt_);
|
||||||
|
|
||||||
|
if (ret == AVERROR(EAGAIN))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
if (ret == AVERROR_EOF)
|
||||||
|
*endOfFile = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pkt_.stream_index != video_stream_id_)
|
||||||
|
{
|
||||||
|
av_free_packet(&pkt_);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*data = pkt_.data;
|
||||||
|
*size = pkt_.size;
|
||||||
|
*endOfFile = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputMediaStream_FFMPEG* create_InputMediaStream_FFMPEG(const char* fileName, int* codec, int* chroma_format, int* width, int* height)
|
||||||
|
{
|
||||||
|
InputMediaStream_FFMPEG* stream = (InputMediaStream_FFMPEG*) malloc(sizeof(InputMediaStream_FFMPEG));
|
||||||
|
|
||||||
|
if (stream && stream->open(fileName, codec, chroma_format, width, height))
|
||||||
|
return stream;
|
||||||
|
|
||||||
|
stream->close();
|
||||||
|
free(stream);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void release_InputMediaStream_FFMPEG(InputMediaStream_FFMPEG* stream)
|
||||||
|
{
|
||||||
|
stream->close();
|
||||||
|
free(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_InputMediaStream_FFMPEG(InputMediaStream_FFMPEG* stream, unsigned char** data, int* size, int* endOfFile)
|
||||||
|
{
|
||||||
|
return stream->read(data, size, endOfFile);
|
||||||
|
}
|
||||||
|
@@ -215,6 +215,7 @@ int main(int argc, const char* argv[])
|
|||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
case 27:
|
case 27:
|
||||||
|
return 0;
|
||||||
|
|
||||||
case 'A':
|
case 'A':
|
||||||
if (currentFrame > 0)
|
if (currentFrame > 0)
|
||||||
|
Reference in New Issue
Block a user