我所有解析fmp4的尝试均失败,并出现以下错误:
avcodec_send_packet
返回-10949955291
并显示以下错误:
[h264 @ 0x105001600] No start code is found.
[h264 @ 0x105001600] Error splitting the input into NAL units.
我做了什么?
下载了可完美播放的h.264
文件,并使用以下cmd对其进行了分段
ffmpeg -i long.mp4 -an -sn -vcodec libx264 -force_key_frames "expr:gte(t,n_forced*4)" -sc_threshold 0 -r 25 -f hls -hls_time 4 -hls_list_size 99999 -start_number 1 -hls_segment_type fmp4 -hls_fmp4_init_filename init.mp4 -t 30 -threads 0 big_bunny.m3u8
,并使用以下AVIO
阅读示例
#include <fstream>
#include <iterator>
#include <algorithm>
#include <libavcodec/avcodec.h>
std::vector<unsigned char> b1;
std::vector<unsigned char> b2;
bool initialized = false;
int bytesread = 0;
static int read_packet(void* opaque, uint8_t* buf, int buf_size)
{
if (b1.size() && !initialized) {
size_t bytesToRead = std::min(buf_size, (int)b1.size());
::memcpy(buf, b1.data(), bytesToRead);
bytesread += bytesToRead;
if (bytesread >= b1.size()) {
initialized = true;
bytesread = 0;
}
return bytesToRead;
}
::memcpy(buf, b2.data() + bytesread, buf_size);
bytesread += buf_size;
return buf_size;
}
int main(int argc, char** argv)
{
AVFormatContext* fmt_ctx = NULL;
AVIOContext* avio_ctx = NULL;
uint8_t *buffer = NULL, *buffer2 = nullptr, *avio_ctx_buffer = NULL;
size_t buffer_size, buffer_size2, avio_ctx_buffer_size = 4096;
char* input_filename = NULL;
int ret = 0;
struct buffer_data bd = {0};
std::ifstream input1("/Users/x/Downloads/fmp4/init.mp4", std::ios::binary);
std::ifstream input2("/Users/x/Downloads/fmp4/big_bunny1.m4s", std::ios::binary);
b1 = std::vector<unsigned char>((std::istreambuf_iterator<char>(input1)), std::istreambuf_iterator<char>());
b2 = std::vector<unsigned char>((std::istreambuf_iterator<char>(input2)), std::istreambuf_iterator<char>());
avio_ctx_buffer = (uint8_t*)av_malloc(avio_ctx_buffer_size);
fmt_ctx = avformat_alloc_context();
avio_ctx = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size, 0, nullptr, &read_packet, NULL, NULL);
fmt_ctx->pb = avio_ctx;
AVDictionary* opts = NULL;
// av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
ret = avformat_open_input(&fmt_ctx, NULL, NULL, &opts);
ret = avformat_find_stream_info(fmt_ctx, NULL);
AVCodec* decoder = nullptr;
decoder = avcodec_find_decoder(fmt_ctx->streams[0]->codecpar->codec_id);
AVCodecContext* decoderCtx = avcodec_alloc_context3(decoder);
ret = avcodec_open2(decoderCtx, decoder, nullptr);
AVPacket pkt;
av_init_packet(&pkt);
AVFrame* frame = av_frame_alloc();
while (true) {
ret = av_read_frame(fmt_ctx, &pkt);
ret = avcodec_send_packet(decoderCtx, &pkt);
if (ret != 0)
assert(false);
for (;;) {
ret = avcodec_receive_frame(decoderCtx, frame);
if (ret < 0) {
break;
}
int g;
g = 0;
}
}
我什至不确定这是否是处理fmp4
类型的正确方法。但是为了清楚起见,我只是将初始化文件加载到第一个缓冲区中,并将实际的媒体文件加载到第二个缓冲区中,然后在缓冲区之间分别切换为buf_size
的值。
答案 0 :(得分:0)
我不认为在使用avio_alloc_context
多路分解器的情况下获取所有必要的信息-请参见Opening a media file,但这是一个大胆的猜测,因为您的输出没有显示来自mp4多路分解器的错误但仅来自H.264比特流解析器,因此我倾向于所探查的文件格式可能是原始H.264,但很难分辨。但是,如果我弄错了,您还没有提供搜索回调,并且对mp4进行解复用肯定会要求搜索跳出框框,然后搜索示例数据。因此,我首先尝试提供一个搜索回调,看看是否被调用。但是从示例中并不能确定为什么甚至需要I / O回调,因为数据驻留在文件中而不是存储位置中,所以我建议尝试使用标准的avformat_open_input方法。>