问题描述
我想将h264流中的缩略图保存为ffmpeg avpackets作为jpeg。
我首先使用h264 AVPacket(iframe),然后使用avcodec_send_packet / avcodec_receive_frame将其解码为AVFrame。现在尝试从AVFrame转到使用avcodec_send_frame / avcodec_receive_packet转换为AVPacket
我可以将视频转换为png而不是jpg,尽管我确实得到了一个视频,看起来它像是输出三个并排压缩的单独帧。想知道是否是一帧是R,下一个G,最后是B。我不确定,显然我在那儿做错了。我认为这可能是png编码器,但我不需要它,因此让jpg首先工作。但是jpg输出的是无法打开的文件。
有什么建议吗?
这是我的代码:
int output_thumbnails(AVPacket* video_packet)
{
char png_file_name[max_chars_per_filename];
char thumbnail_id_char[10];
_itoa_s(thumbnail_id,thumbnail_id_char,10);
strcpy_s(png_file_name,max_chars_per_filename,time_stamped_filepath);
strcat_s(png_file_name,time_stamped_filename);
strcat_s(png_file_name,thumbnail_id_char);
strcat_s(png_file_name,".jpg");
thumbnail_id++;
int error_code = send_AVPacket_to_videocard(video_packet,av_codec_context_RTSP);
//if (error_code == AVERROR_EOF)
//{
// // error_code = videocard_to_PNG(png_file_name,av_codec_context_RTSP,av_codec_RTSP);
//}
if (error_code == AVERROR(EAGAIN)) //send packets to videocard until function returns EAGAIN
{
error_code = videocard_to_PNG(png_file_name,av_codec_context_RTSP);
//EAGAIN means that the video card buffer is ready to have the png pulled off of it
if (error_code == AVERROR_EOF)
{
// error_code = videocard_to_PNG(png_file_name,av_codec_RTSP);
}
else if (error_code == AVERROR(EAGAIN))
{
}
else
{
deal_with_av_errors(error_code,__LINE__,__FILE__);
}
}
else
{
deal_with_av_errors(error_code,__FILE__);
}
return 0;
}
VideoThumbnailGenerator.h: #include“ VideoThumbnailGenerator.h”
bool decoder_context_created = false;
bool encoder_context_created = false;
AVCodecContext* h264_decoder_codec_ctx;
AVCodecContext* thumbnail_encoder_codec_ctx;
int send_AVPacket_to_videocard(AVPacket* packet,AVCodecContext* codec_ctx)
{
if(!decoder_context_created)
{
AVCodec* h264_codec = avcodec_find_decoder(codec_ctx->codec_id);
h264_decoder_codec_ctx = avcodec_alloc_context3(h264_codec);
h264_decoder_codec_ctx->width = codec_ctx->width;
h264_decoder_codec_ctx->height = codec_ctx->height;
h264_decoder_codec_ctx->pix_fmt = AV_PIX_FMT_RGB24;
h264_decoder_codec_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
h264_decoder_codec_ctx->skip_frame = AVDISCARD_NONINTRA;//AVDISCARD_NONREF;//AVDISCARD_NONINTRA;
h264_decoder_codec_ctx->time_base.num = 1;
h264_decoder_codec_ctx->time_base.den = 30;
h264_decoder_codec_ctx->extradata = codec_ctx->extradata;
h264_decoder_codec_ctx->extradata_size = codec_ctx->extradata_size;
int error_code = avcodec_open2(h264_decoder_codec_ctx,h264_codec,NULL);
if (!h264_codec) {
return -1;
}
if (error_code < 0)
{
return error_code;
}
decoder_context_created = true;
}
//use hardware decoding to decode video frame
int error_code = avcodec_send_packet(h264_decoder_codec_ctx,packet);
if(error_code == AVERROR(EAGAIN))
{
return AVERROR(EAGAIN);
}
if(error_code<0)
{
printf("Error: Could not send packet to video card");
return error_code;
}
return 0;
}
int videocard_to_PNG(char *png_file_path,AVCodecContext* codec_ctx)
{
if (!encoder_context_created)
{
//AVCodec* thumbnail_codec = avcodec_find_encoder(AV_CODEC_ID_PNG);
AVCodec* thumbnail_codec = avcodec_find_encoder(AV_CODEC_ID_JPEG2000);
thumbnail_encoder_codec_ctx = avcodec_alloc_context3(thumbnail_codec);
thumbnail_encoder_codec_ctx->width = 128;
thumbnail_encoder_codec_ctx->height = (int)(((float)codec_ctx->height/(float)codec_ctx->width) * 128);
thumbnail_encoder_codec_ctx->pix_fmt = AV_PIX_FMT_RGB24; //AV_PIX_FMT_YUVJ420P
thumbnail_encoder_codec_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
thumbnail_encoder_codec_ctx->time_base.num = 1;
thumbnail_encoder_codec_ctx->time_base.den = 30;
bool thread_check = thumbnail_encoder_codec_ctx->thread_type & FF_THREAD_FRAME;
bool frame_threads_check = thumbnail_encoder_codec_ctx->codec->capabilities & AV_CODEC_CAP_FRAME_THREADS;
int error_code = avcodec_open2(thumbnail_encoder_codec_ctx,thumbnail_codec,NULL);
if (!thumbnail_codec) {
return -1;
}
if (error_code < 0)
{
return error_code;
}
encoder_context_created = true;
}
AVFrame* thumbnail_frame = av_frame_alloc();
AVPacket* thumbnail_packet = av_packet_alloc();
//av_init_packet(png_packet);
int error_code = avcodec_receive_frame(h264_decoder_codec_ctx,thumbnail_frame);
//check for errors everytime
//note EAGAIN errors won't get here since they won't get past while
if (error_code < 0 && error_code != AVERROR(EAGAIN))
{
printf("Error: Could not get frame from video card");
return error_code;
}
//empty buffer if there are any more frames to pull (there shouldn't be)
//while(error_code != AVERROR(EAGAIN))
//{
// //check for errors everytime
// //note EAGAIN errors won't get here since they won't get past while
// if (error_code < 0)
// {
// printf("Error: Could not get frame from video card");
// return error_code;
// }
//
// error_code = avcodec_receive_frame(h264_decoder_codec_ctx,png_frame);
//}
//now we convert back to AVPacket,this time one holding PNG info,so we can store to file
error_code = avcodec_send_frame(thumbnail_encoder_codec_ctx,thumbnail_frame);
if (error_code >= 0) {
error_code = avcodec_receive_packet(thumbnail_encoder_codec_ctx,thumbnail_packet);
FILE* out_PNG;
errno_t err = fopen_s(&out_PNG,png_file_path,"wb");
if (err == 0) {
fwrite(thumbnail_packet->data,thumbnail_packet->size,1,out_PNG);
}
fclose(out_PNG);
}
return error_code;
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)