-
-
Save tigerwood/1ac07d7f5359a4ec65d2b3deba94006a to your computer and use it in GitHub Desktop.
save AVPacket from mem to disk and then read back
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <libavutil/timestamp.h> | |
#include <libavformat/avformat.h> | |
static FILE *open_file_write(const char *file); | |
static FILE *open_file_read(const char *file); | |
static size_t write_packt_to_file(AVPacket *packet, FILE *file); | |
static size_t read_packt_from_file(AVPacket *packet, FILE *file); | |
static void close_file(FILE *file); | |
static void log_packet(const AVFormatContext *fmt_ctx, const AVPacket *pkt, const char *tag) | |
{ | |
// AVRational *time_base = &fmt_ctx->streams[pkt->stream_index]->time_base; | |
// printf("%s: pts:%s pts_time:%s dts:%s dts_time:%s duration:%s duration_time:%s stream_index:%d\n", | |
// tag, | |
// av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, time_base), | |
// av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, time_base), | |
// av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, time_base), | |
// pkt->stream_index); | |
} | |
static void ff_log_callback(void*avcl, int level, const char*fmt, va_list vl) | |
{ | |
printf(fmt, vl); | |
} | |
int main(int argc, char **argv) | |
{ | |
AVOutputFormat *ofmt = NULL; | |
AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL; | |
AVPacket pkt; | |
AVPacket read_packet; | |
const char *in_filename, *out_filename; | |
int ret, i; | |
if (argc < 3) { | |
printf("usage: %s input output\n" | |
"API example program to remux a media file with libavformat and libavcodec.\n" | |
"The output format is guessed according to the file extension.\n" | |
"\n", argv[0]); | |
return 1; | |
} | |
in_filename = argv[1]; | |
out_filename = argv[2]; | |
av_register_all(); | |
if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) { | |
fprintf(stderr, "Could not open input file '%s'", in_filename); | |
goto end; | |
} | |
if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) { | |
fprintf(stderr, "Failed to retrieve input stream information"); | |
goto end; | |
} | |
av_log_set_level(48); | |
av_log_set_callback(ff_log_callback); | |
av_dump_format(ifmt_ctx, 0, in_filename, 0); | |
avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename); | |
if (!ofmt_ctx) { | |
fprintf(stderr, "Could not create output context\n"); | |
ret = AVERROR_UNKNOWN; | |
goto end; | |
} | |
ofmt = ofmt_ctx->oformat; | |
for (i = 0; i < ifmt_ctx->nb_streams; i++) { | |
AVStream *in_stream = ifmt_ctx->streams[i]; | |
AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec); | |
if (!out_stream) { | |
fprintf(stderr, "Failed allocating output stream\n"); | |
ret = AVERROR_UNKNOWN; | |
goto end; | |
} | |
ret = avcodec_copy_context(out_stream->codec, in_stream->codec); | |
if (ret < 0) { | |
fprintf(stderr, "Failed to copy context from input to output stream codec context\n"); | |
goto end; | |
} | |
out_stream->codec->codec_tag = 0; | |
if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) | |
out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; | |
} | |
av_dump_format(ofmt_ctx, 0, out_filename, 1); | |
if (!(ofmt->flags & AVFMT_NOFILE)) { | |
ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE); | |
if (ret < 0) { | |
fprintf(stderr, "Could not open output file '%s'", out_filename); | |
goto end; | |
} | |
} | |
ret = avformat_write_header(ofmt_ctx, NULL); | |
if (ret < 0) { | |
fprintf(stderr, "Error occurred when opening output file\n"); | |
goto end; | |
} | |
FILE *file_write = open_file_write("/Users/sunjun/Desktop/packt_file.b"); | |
FILE *file_read = open_file_read("/Users/sunjun/Desktop/packt_file.b"); | |
while (1) { | |
AVStream *in_stream, *out_stream; | |
ret = av_read_frame(ifmt_ctx, &pkt); | |
if (ret < 0) | |
break; | |
write_packt_to_file(&pkt, file_write); | |
read_packt_from_file(&read_packet, file_read); | |
in_stream = ifmt_ctx->streams[read_packet.stream_index]; | |
out_stream = ofmt_ctx->streams[read_packet.stream_index]; | |
log_packet(ifmt_ctx, &read_packet, "in"); | |
/* copy packet */ | |
read_packet.pts = av_rescale_q_rnd(read_packet.pts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); | |
read_packet.dts = av_rescale_q_rnd(read_packet.dts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); | |
read_packet.duration = (int)av_rescale_q(read_packet.duration, in_stream->time_base, out_stream->time_base); | |
read_packet.pos = -1; | |
log_packet(ofmt_ctx, &read_packet, "out"); | |
//写音频流的packet时候会出错 | |
ret = av_interleaved_write_frame(ofmt_ctx, &read_packet); | |
if (ret < 0) { | |
fprintf(stderr, "Error muxing packet\n"); | |
break; | |
} | |
av_free_packet(&read_packet); | |
av_free_packet(&pkt); | |
} | |
av_write_trailer(ofmt_ctx); | |
close_file(file_write); | |
close_file(file_read); | |
end: | |
avformat_close_input(&ifmt_ctx); | |
/* close output */ | |
if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE)) | |
avio_closep(&ofmt_ctx->pb); | |
avformat_free_context(ofmt_ctx); | |
if (ret < 0 && ret != AVERROR_EOF) { | |
fprintf(stderr, "Error occurred: %s\n", av_err2str(ret)); | |
return 1; | |
} | |
return 0; | |
} | |
static FILE *open_file_write(const char *file) | |
{ | |
FILE *packt_file = NULL; | |
packt_file = fopen(file, "wb+"); | |
return packt_file; | |
} | |
static FILE *open_file_read(const char *file) | |
{ | |
FILE *packt_file = NULL; | |
packt_file = fopen(file, "rb+"); | |
return packt_file; | |
} | |
static size_t read_packt_from_file(AVPacket *packet, FILE *file) | |
{ | |
size_t ret = 0; | |
ret = fread(packet, sizeof(AVPacket), 1, file); | |
packet->data = malloc(packet->size); | |
ret = fread(packet->data, packet->size, 1, file); | |
if (packet->buf) { | |
int buf_size = packet->buf->size; | |
packet->buf = malloc(sizeof(AVBufferRef)); | |
packet->buf->size = buf_size; | |
packet->buf->data = malloc(packet->buf->size); | |
ret = fread(packet->buf->data, packet->buf->size, 1, file); | |
} | |
return ret; | |
} | |
static size_t write_packt_to_file(AVPacket *packet, FILE *file) | |
{ | |
size_t ret = 0; | |
ret = fwrite(packet, sizeof(AVPacket), 1, file); | |
ret = fwrite(packet->data, packet->size, 1, file); | |
if (packet->buf) { | |
fwrite(packet->buf->data, packet->buf->size, 1, file); | |
} | |
fflush(file); | |
return ret; | |
} | |
static void close_file(FILE *file) | |
{ | |
fclose(file); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment