int main(int argc, char *argv[]){ int i; int kk[1]; int error_code, ret; char *src, *dst; int len = 0; int video_id; int got_picture = 1; const AVCodec *codec; FILE *f; FILE *df; AVFormatContext *fmt_ctx; // 格式化上下文 存放输入的视频解码信息 AVCodecContext *c = NULL; // 解码器上下文
// 注意这里的 ioCtxBuffer 大小对程序结果有影响 ---》4096时 对1.MP4文件解析成功 对v1h265.mp4失败(报找不到帧) 放到 2736496(实际就是v1h265.mp4的文件大小) 大小就ok
AVIOContext *avioCtx; BufferData bd; AVPacket pkt; AVStream *st = NULL; AVFrame *frame = NULL; uint8_t *buffer = (uint8_t *)malloc(BUFFERSIZE); uint8_t *buffer2 = NULL; int64_t jumpTime = 0; int fileSize = 0; int bufferSize = BUFFERSIZE; // av_log_set_level(AV_LOG_DEBUG); if (argc < 3) { printf("arg less than 2\n"); return -1; } src = argv[1]; dst = argv[2]; jumpTime = atoi(argv[3]); fmt_ctx = avformat_alloc_context(); if (fmt_ctx == NULL) { printf("alloc format context fail\n"); return -1; } // count1 = 1; f = fopen(src, "rb"); if (f == NULL) { printf("open file: %s fail\n", src); return -1; }
memset(buffer, 0, bufferSize);
while (!feof(f)) { len = fread(buffer + fileSize, 1, BUFFERSIZE, f); fileSize += len; printf("len:%d\n", len);
if (len == BUFFERSIZE && fileSize + BUFFERSIZE >= bufferSize) { printf("realloc\n"); buffer2 = (uint8_t *)malloc(bufferSize + 20* BUFFERSIZE); memset(buffer2, 0, bufferSize + 20* BUFFERSIZE); memcpy(buffer2, buffer, bufferSize); free(buffer); buffer = buffer2; bufferSize = bufferSize + 20* BUFFERSIZE; } } printf("read done! fileSize:%d bufferSize:%d\n", fileSize, bufferSize); return 0; uint8_t *ioCtxBuffer = (uint8_t *)av_malloc(fileSize); bd.file_size = fileSize; bd.size = bd.file_size; bd.ptr = buffer; bd.ori_ptr = buffer; avioCtx = avio_alloc_context(ioCtxBuffer, fileSize, 0, &bd, &read_packet, NULL, NULL); if (avioCtx == NULL) { printf("alloc avio context fail\n"); return -1; }
fmt_ctx->pb = avioCtx; fmt_ctx->flags |= AVFMT_FLAG_CUSTOM_IO; error_code = avformat_open_input(&fmt_ctx, "", NULL, NULL); printf("error_code:%d\n", error_code); if (error_code < 0) { printf("open input fail\n"); return -1; }
ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); if (ret < 0) { printf("find best stream fail"); goto end; } printf("best_stream id:%d\n", ret); video_id = ret; st = fmt_ctx->streams[video_id]; ret = avformat_find_stream_info(fmt_ctx, 0); // 获取流详细信息 if (ret < 0) { printf("Can't get stream information! just show aac , not show aac(LC)\n"); }
av_dump_format(fmt_ctx, video_id, "", 0); //第一个0是流的索引值,第二个表示输入/输出流,由于是输入文件,所以为0 printf("codec_id:%d \n", st->codecpar->codec_id); codec = avcodec_find_decoder(st->codecpar->codec_id); if (!codec) { printf("find decoder fail\n"); return -1; }
// 分配解码器上下文内存 c = avcodec_alloc_context3(NULL); if (!c) { printf("Fail to alloc context:c\n"); return -1; }
// 设置解码器参数 ret = avcodec_parameters_to_context(c, st->codecpar); if (ret < 0) { printf("cannot initialize the conversion context\n"); return -1; }
// 打开解码器 ret = avcodec_open2(c, codec, NULL); if (ret < 0) { printf("cannot open codec\n"); return -1; }
// 帧空间分配 frame = av_frame_alloc(); if (!frame) { printf("can't not alloc the frame for video \n"); return -1; }
df = fopen(dst, "wb"); if (!df) { printf("Can't open dst file!\n"); return -1; }
av_init_packet(&pkt);
jumpTime = getStartTime(st, jumpTime); error_code = seek(fmt_ctx, st, jumpTime);
printf("seek error_code:%d\n", error_code); printf("start read frame\n"); while ((av_read_frame(fmt_ctx, &pkt) >= 0)) { // error_code++; // printf("error_code:%d\n", error_code); if (pkt.stream_index == video_id) {
len = avcodec_decode_video2(c, frame, &got_picture, &pkt); if (len < 0) { printf("fail to decode video frame (return len:%d)\n", len); return len; } if (pkt.pts < jumpTime) { continue; }
if (got_picture) { // printf("got_picture:%d \n", got_picture); // printf("picture w h :%d %d %d\n", frame->width, frame->height, (frame->width) * (frame->height)); len = 0;
for (kk[0] = 0; kk[0] < frame->height; kk[0] += 1) { fwrite(frame->data[0] + kk[0] * (frame->linesize[0]), 1, frame->width, df); fflush(df); } for (kk[0] = 0; kk[0] < frame->height / 2; kk[0] += 1) { fwrite(frame->data[1] + kk[0] * (frame->linesize[1]), 1, frame->width / 2, df); fflush(df); } for (kk[0] = 0; kk[0] < frame->height / 2; kk[0] += 1) { fwrite(frame->data[2] + kk[0] * (frame->linesize[2]), 1, frame->width / 2, df); fflush(df); } } else { printf("got not picture :%d\n", got_picture); // return -1; } }
av_packet_unref(&pkt); }
jumpTime = getStartTime(st, 2); error_code = seek(fmt_ctx, st, jumpTime);
printf("seek error_code:%d\n", error_code); printf("start read frame\n"); while ((av_read_frame(fmt_ctx, &pkt) >= 0)) { // error_code++; // printf("error_code:%d\n", error_code); if (pkt.stream_index == video_id) {
len = avcodec_decode_video2(c, frame, &got_picture, &pkt); if (len < 0) { printf("fail to decode video frame (return len:%d)\n", len); return len; } if (pkt.pts < jumpTime) { continue; }
if (got_picture) { // printf("got_picture:%d \n", got_picture); // printf("picture w h :%d %d %d\n", frame->width, frame->height, (frame->width) * (frame->height)); len = 0;
for (kk[0] = 0; kk[0] < frame->height; kk[0] += 1) { fwrite(frame->data[0] + kk[0] * (frame->linesize[0]), 1, frame->width, df); fflush(df); } for (kk[0] = 0; kk[0] < frame->height / 2; kk[0] += 1) { fwrite(frame->data[1] + kk[0] * (frame->linesize[1]), 1, frame->width / 2, df); fflush(df); } for (kk[0] = 0; kk[0] < frame->height / 2; kk[0] += 1) { fwrite(frame->data[2] + kk[0] * (frame->linesize[2]), 1, frame->width / 2, df); fflush(df); } } else { printf("got not picture :%d\n", got_picture); // return -1; } }
av_packet_unref(&pkt); }
end: avformat_close_input(&fmt_ctx); // fclose(f); return 0;}
2022年07月25日 08点07分
6