我非常感谢以下问题的一些帮助:
我有一个带摄像头的小工具,生成H264压缩视频帧,这些帧正在发送到我的应用程序.这些框架不在容器中,只是原始数据.
我想使用ffmpeg和libav函数来创建一个视频文件,以后可以使用.
如果我解码帧,然后编码它们,一切正常,我得到一个有效的视频文件.(解码/编码步骤是通常的libav命令,这里没什么花哨的,我把它们从万能的互联网上取下来,它们坚如磐石)......但是,我通过解码和编码浪费了大量时间,所以我想跳过此步骤并直接将帧放在输出流中.现在,问题来了.
这是我提出的用于生成编码的代码:
AVFrame* picture;
avpicture_fill((AVPicture*) picture, (uint8_t*)frameData,
codecContext->pix_fmt, codecContext->width,
codecContext->height);
int outSize = avcodec_encode_video(codecContext, videoOutBuf,
sizeof(videoOutBuf), picture);
if (outSize > 0)
{
AVPacket packet;
av_init_packet(&packet);
packet.pts = av_rescale_q(codecContext->coded_frame->pts,
codecContext->time_base, videoStream->time_base);
if (codecContext->coded_frame->key_frame)
{
packet.flags |= PKT_FLAG_KEY;
}
packet.stream_index = videoStream->index;
packet.data = videoOutBuf;
packet.size = outSize;
av_interleaved_write_frame(context, &packet);
put_flush_packet(context->pb);
}
Run Code Online (Sandbox Code Playgroud)
变量的位置如下:
frameData是来自摄像机的解码帧数据,它是在前一步骤中解码的,videoOutBuf是用于保存数据的普通uint8_t缓冲区
我修改了应用程序以便不解码帧,而只是简单地传递数据:
AVPacket packet;
av_init_packet(&packet);
packet.stream_index = videoStream->index;
packet.data = (uint8_t*)frameData;
packet.size = currentFrameSize;
av_interleaved_write_frame(context, &packet);
put_flush_packet(context->pb);
Run Code Online (Sandbox Code Playgroud)
哪里
frameData是原始的H264帧,currentFrameSize是原始H264帧的大小,即.我从每个框架的小工具中获得的字节数.
然后,应用程序突然无法正常工作,生成的视频无法播放.这很明显,因为我没有为数据包设置正确的PTS.我做的是以下(我很绝望,你可以从这种方法看到:)) …
我目前正在尝试阅读从服务器发送的小型视频文件
为了使用libavformat读取文件,您应该调用
av_open_input_file(&avFormatContext, "C:\\path\\to\\video.avi", 0, 0, 0);
Run Code Online (Sandbox Code Playgroud)
问题是在这种情况下,文件不在磁盘上,而是在内存中.
我现在正在做的是下载文件,使用临时名称将其写入磁盘,然后av_open_input_file使用临时文件名调用,这不是一个非常干净的解决方案.
事实上我想要的是一个功能,av_open_custom(&avFormatContext, &myReadFunction, &mySeekFunction);但我没有在文档中找到任何.我想这在技术上是可行的,因为文件的名称不能帮助库确定它使用的格式.
那么有这样的函数,还是av_open_input_file的替代品?
我正在多路复用视频和音频流.视频流来自生成的图像数据.音频流来自aac文件.有些音频文件比我设置的总视频时间长,所以当我的时间变得大于总视频时间(我用数字编码的视频帧控制的最后一个)时,我的策略是停止音频流复用.
我不会在这里放置整个设置代码,但它类似于最新的FFMPEG repo中的muxing.c示例.唯一的区别是我使用来自文件的音频流,正如我所说的,不是来自合成生成的编码帧.我很确定问题是在muxer循环期间我的错误同步.这就是我所做的:
void AudioSetup(const char* audioInFileName)
{
AVOutputFormat* outputF = mOutputFormatContext->oformat;
auto audioCodecId = outputF->audio_codec;
if (audioCodecId == AV_CODEC_ID_NONE) {
return false;
}
audio_codec = avcodec_find_encoder(audioCodecId);
avformat_open_input(&mInputAudioFormatContext,
audioInFileName, 0, 0);
avformat_find_stream_info(mInputAudioFormatContext, 0);
av_dump_format(mInputAudioFormatContext, 0, audioInFileName, 0);
for (size_t i = 0; i < mInputAudioFormatContext->nb_streams; i++) {
if (mInputAudioFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
inAudioStream = mInputAudioFormatContext->streams[i];
AVCodecParameters *in_codecpar = inAudioStream->codecpar;
mAudioOutStream.st = avformat_new_stream(mOutputFormatContext, NULL);
mAudioOutStream.st->id = mOutputFormatContext->nb_streams - 1;
AVCodecContext* c = avcodec_alloc_context3(audio_codec);
mAudioOutStream.enc = c;
c->sample_fmt = audio_codec->sample_fmts[0]; …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用FFmpeg libavformat记录来自Axis相机的RTSP流.我可以从文件中获取视频,然后将其保存到另一个文件,这没关系.但相机发送奇怪的数据,FPS为100,相机每隔4帧发送一次,因此结果FPS约为25.但是libavformat设置数据包dts/pts为90000 fps(默认值?),新文件流有100fps.结果是一小时视频,只有100帧.
这是我的代码
#include <stdio.h>
#include <stdlib.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
int main(int argc, char** argv) {
AVFormatContext* context = avformat_alloc_context();
int video_stream_index;
av_register_all();
avcodec_register_all();
avformat_network_init();
//open rtsp
if(avformat_open_input(&context, "rtsp://195.200.199.8/mpeg4/media.amp",NULL,NULL) != 0){
return EXIT_FAILURE;
}
if(avformat_find_stream_info(context,NULL) < 0){
return EXIT_FAILURE;
}
//search video stream
for(int i =0;i<context->nb_streams;i++){
if(context->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
video_stream_index = i;
}
AVPacket packet;
av_init_packet(&packet);
//open output file
AVOutputFormat* fmt = av_guess_format(NULL,"test2.avi",NULL);
AVFormatContext* oc = avformat_alloc_context();
oc->oformat = fmt;
avio_open2(&oc->pb, "test.avi", AVIO_FLAG_WRITE,NULL,NULL);
AVStream* stream=NULL;
int …Run Code Online (Sandbox Code Playgroud) I am trying to mux H.264 data into a MP4 file. There appear to be no errors in saving this H.264 Annex B data out to an MP4 file, but the file fails to playback.
I've done a binary comparison on the files and the issue seems to be somewhere in what is being written to the footer (trailer) of the MP4 file.
I suspect it has to be something with the way the stream is being created or something. …
过去一周我一直在尝试通过RTP实现H.264流,使用x264作为编码器,使用libavformat来打包和发送流.问题是,据我所知,它无法正常工作.
现在我只是编码随机数据(x264_picture_alloc)并从libx264中提取NAL帧.这很简单:
x264_picture_t pic_out;
x264_nal_t* nals;
int num_nals;
int frame_size = x264_encoder_encode(this->encoder, &nals, &num_nals, this->pic_in, &pic_out);
if (frame_size <= 0)
{
return frame_size;
}
// push NALs into the queue
for (int i = 0; i < num_nals; i++)
{
// create a NAL storage unit
NAL nal;
nal.size = nals[i].i_payload;
nal.payload = new uint8_t[nal.size];
memcpy(nal.payload, nals[i].p_payload, nal.size);
// push the storage into the NAL queue
{
// lock and push the NAL to the queue
boost::mutex::scoped_lock lock(this->nal_lock);
this->nal_queue.push(nal);
} …Run Code Online (Sandbox Code Playgroud) 是否可以将pcm音频文件存储到.mp4文件中?
我用的ffmpeg命令"的ffmpeg -i tempA.wav -acodec副本temp.mp4的",但无法将其存储在MP4容器文件.
输入#0,wav,来自'tempA.wav':
持续时间:00:01:36.51,比特率:128 kb/s
Run Code Online (Sandbox Code Playgroud)Stream #0.0: Audio: pcm_s16le, 8000 Hz, 1 channels, s16, 128 kb/s[mp4 @ 0x7d70e0] Tag [1] [0] [0] [0]/0x00000001与输出编解码器ID"65536"不兼容
输出#0,mp4,到'temp.mp4':
Run Code Online (Sandbox Code Playgroud)Stream #0.0: Audio: pcm_s16le, 8000 Hz, 1 channels, 128 kb/s流映射:
流#0.0 - >#0.0
无法为输出文件#0写入标头(编解码器参数不正确?)
凡在转换为.AVI(ffmpeg的-i tempA.wav -acodec副本temp.avi).MOV(ffmpeg的-i tempA.wav -acodec副本temp.mov)文件格式工作完全正常.
我正在使用FFmpeg录制视频,我希望它写入的帧速率至少在正确的球场.现在我采用输入声称拥有的帧速率,并使用它来设置输出视频流的帧速率(time_base).然而,这有时与我得到的实际帧速率大不相同(我看到一个流声称50 fps但以9 fps发布).
我想要做的是使用经过时间的计时器并计算我记录的帧数来计算我在完成录制时记录的实际帧速率.我似乎在我编写任何帧之前,我在AVStream中设置的帧速率在avcodec_open2中使用.如果我稍后设置它(例如在我写帧的时候),而ffplay可以播放它(抱怨时间增量位是6而不是4)其他视频播放器不能.有没有办法在写入帧后设置整个文件的帧速率?如果没有办法在我录制时告诉帧本身某种时间戳或帧速率会产生有效的录制文件?
我正在尝试使用 FFmpeg 和 C++ 创建 mp4 视频文件,但结果我收到损坏的文件(Windows 播放器显示“无法播放 ... 0xc00d36c4”)。如果我创建 .h264 文件,它可以用 'ffplay' 播放并通过 CL 成功转换为 mp4。
我的代码:
int main() {
char *filename = "tmp.mp4";
AVOutputFormat *fmt;
AVFormatContext *fctx;
AVCodecContext *cctx;
AVStream *st;
av_register_all();
avcodec_register_all();
//auto detect the output format from the name
fmt = av_guess_format(NULL, filename, NULL);
if (!fmt) {
cout << "Error av_guess_format()" << endl; system("pause"); exit(1);
}
if (avformat_alloc_output_context2(&fctx, fmt, NULL, filename) < 0) {
cout << "Error avformat_alloc_output_context2()" << endl; system("pause"); exit(1);
}
//stream creation + …Run Code Online (Sandbox Code Playgroud) 默认情况下,libavformat将错误消息写入stderr,如:
Estimating duration from bitrate, this may be inaccurate
我怎么能把它关掉?或者更好的是,把它管道到我自己的整洁记录功能?
编辑:将stderr重定向到其他地方是不可接受的,因为我需要它用于其他日志记录目的,我只是希望libavformat不写入它.
libavformat ×10
ffmpeg ×7
c++ ×5
libavcodec ×5
c ×4
h.264 ×3
audio ×2
mp4 ×2
video ×2
containers ×1
file ×1
frame-rate ×1
libav ×1
libx264 ×1
rtp ×1
rtsp-client ×1