Created
September 24, 2014 05:42
-
-
Save sqbing/020a287b8c447bed9eb3 to your computer and use it in GitHub Desktop.
demuxing media file
This file contains hidden or 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/imgutils.h> | |
#include <libavutil/samplefmt.h> | |
#include <libavutil/timestamp.h> | |
#include <libavformat/avformat.h> | |
static AVFormatContext *fmt_ctx = NULL; | |
static AVCodecContext *video_dec_ctx = NULL, *audio_dec_ctx; | |
static AVStream *video_stream = NULL, *audio_stream = NULL; | |
static const char *src_filename = NULL; | |
static uint8_t *video_dst_data[4] = {NULL}; | |
static int video_dst_linesize[4]; | |
static int video_dst_bufsize; | |
static uint8_t **audio_dst_data = NULL; | |
static int audio_dst_linesize; | |
static int audio_dst_bufsize; | |
static int video_stream_idx = -1, audio_stream_idx = -1; | |
static AVPacket pkt; | |
static int video_frame_count = 0; | |
static int audio_frame_count = 0; | |
static int decode_packet(int *got_frame, int cached) | |
{ | |
int ret = 0; | |
if (pkt.stream_index == video_stream_idx) { | |
// TODO 检查是否x264 params string | |
printf("Video pkt size: %i, data: %x %x %x %x %x %x %x %x\n", | |
pkt.size, | |
pkt.data[0], pkt.data[1], pkt.data[2], pkt.data[3], | |
pkt.data[4], pkt.data[5], pkt.data[6], pkt.data[7]); | |
} | |
return ret; | |
} | |
static int open_codec_context(int *stream_idx, | |
AVFormatContext *fmt_ctx, enum AVMediaType type) | |
{ | |
int ret; | |
ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0); | |
if (ret < 0) { | |
fprintf(stderr, "Could not find %s stream in input file '%s'\n", | |
av_get_media_type_string(type), src_filename); | |
return ret; | |
} | |
*stream_idx = ret; | |
return 0; | |
} | |
static int get_format_from_sample_fmt(const char **fmt, | |
enum AVSampleFormat sample_fmt) | |
{ | |
int i; | |
struct sample_fmt_entry { | |
enum AVSampleFormat sample_fmt; const char *fmt_be, *fmt_le; | |
} sample_fmt_entries[] = { | |
{ AV_SAMPLE_FMT_U8, "u8", "u8" }, | |
{ AV_SAMPLE_FMT_S16, "s16be", "s16le" }, | |
{ AV_SAMPLE_FMT_S32, "s32be", "s32le" }, | |
{ AV_SAMPLE_FMT_FLT, "f32be", "f32le" }, | |
{ AV_SAMPLE_FMT_DBL, "f64be", "f64le" }, | |
}; | |
*fmt = NULL; | |
for (i = 0; i < FF_ARRAY_ELEMS(sample_fmt_entries); i++) { | |
struct sample_fmt_entry *entry = &sample_fmt_entries[i]; | |
if (sample_fmt == entry->sample_fmt) { | |
*fmt = AV_NE(entry->fmt_be, entry->fmt_le); | |
return 0; | |
} | |
} | |
fprintf(stderr, | |
"sample format %s is not supported as output format\n", | |
av_get_sample_fmt_name(sample_fmt)); | |
return -1; | |
} | |
int main (int argc, char **argv) | |
{ | |
int ret = 0, got_frame; | |
if(argc < 2){ | |
printf("Need filename.\n"); | |
return -1; | |
} | |
src_filename = argv[1]; | |
/* register all formats and codecs */ | |
av_register_all(); | |
/* open input file, and allocate format context */ | |
if (avformat_open_input(&fmt_ctx, src_filename, NULL, NULL) < 0) { | |
fprintf(stderr, "Could not open source file %s\n", src_filename); | |
exit(1); | |
} | |
printf("After open input file.\n"); | |
/* retrieve stream information */ | |
if (avformat_find_stream_info(fmt_ctx, NULL) < 0) { | |
fprintf(stderr, "Could not find stream information\n"); | |
exit(1); | |
} | |
printf("After find stream info.\n"); | |
if (open_codec_context(&video_stream_idx, fmt_ctx, AVMEDIA_TYPE_VIDEO) >= 0) { | |
video_stream = fmt_ctx->streams[video_stream_idx]; | |
video_dec_ctx = video_stream->codec; | |
} | |
printf("After open video codec context.\n"); | |
if (open_codec_context(&audio_stream_idx, fmt_ctx, AVMEDIA_TYPE_AUDIO) >= 0) { | |
audio_stream = fmt_ctx->streams[audio_stream_idx]; | |
audio_dec_ctx = audio_stream->codec; | |
} | |
printf("After open audio codec context.\n"); | |
/* dump input information to stderr */ | |
av_dump_format(fmt_ctx, 0, src_filename, 0); | |
printf("After dump format.\n"); | |
if (!audio_stream && !video_stream) { | |
fprintf(stderr, "Could not find audio or video stream in the input, aborting\n"); | |
ret = 1; | |
goto end; | |
} | |
/* initialize packet, set data to NULL, let the demuxer fill it */ | |
av_init_packet(&pkt); | |
pkt.data = NULL; | |
pkt.size = 0; | |
/* read frames from the file */ | |
while (av_read_frame(fmt_ctx, &pkt) >= 0) | |
decode_packet(&got_frame, 0); | |
/* flush cached frames */ | |
pkt.data = NULL; | |
pkt.size = 0; | |
do { | |
decode_packet(&got_frame, 1); | |
} while (got_frame); | |
printf("Demuxing succeeded.\n"); | |
end: | |
if (video_dec_ctx) | |
avcodec_close(video_dec_ctx); | |
if (audio_dec_ctx) | |
avcodec_close(audio_dec_ctx); | |
avformat_close_input(&fmt_ctx); | |
return ret < 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment