提交 ca572396 编写于 作者: V Vladislav Vinogradov

fixed some problems after r8280 (lost code)

上级 d5a0088b
......@@ -622,9 +622,6 @@ void cv::gpu::ORB_GPU::computeDescriptors(GpuMat& descriptors)
if (keyPointsCount_[level] == 0)
continue;
if (keyPointsCount_[level] == 0)
continue;
GpuMat descRange = descriptors.rowRange(offset, offset + keyPointsCount_[level]);
if (blurForDescriptor)
......
......@@ -375,7 +375,7 @@ TEST_P(FarnebackOpticalFlow, Accuracy)
EXPECT_MAT_SIMILAR(flowxy[0], d_flowx, 0.1);
EXPECT_MAT_SIMILAR(flowxy[1], d_flowy, 0.1);
};
}
INSTANTIATE_TEST_CASE_P(GPU_Video, FarnebackOpticalFlow, testing::Combine(
ALL_DEVICES,
......@@ -413,4 +413,116 @@ TEST_P(OpticalFlowNan, Regression)
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
......@@ -1565,3 +1565,528 @@ int cvWriteFrame_FFMPEG( CvVideoWriter_FFMPEG* writer,
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)
{
case 27:
return 0;
case 'A':
if (currentFrame > 0)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册