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 check_black_end(AVFilterContext *ctx) { BlackDetectContext *blackdetect = ctx->priv; AVFilterLink *inlink = ctx->inputs[0]; if ((blackdetect->black_end - blackdetect->black_start) >= blackdetect->black_min_duration) { av_log(blackdetect, AV_LOG_INFO, "black_start:%s black_end:%s black_duration:%s\n", av_ts2timestr(blackdetect->black_start, &inlink->time_base), av_ts2timestr(blackdetect->black_end, &inlink->time_base), av_ts2timestr(blackdetect->black_end - blackdetect->black_start, &inlink->time_base)); } }
static av_always_inline void update(SilenceDetectContext *s, AVFrame *insamples, int is_silence, int64_t nb_samples_notify, AVRational time_base) { #ifdef IDE_COMPILE char tmp__0[32] = {0}; char *tmp; #endif if (is_silence) { if (!s->start) { s->nb_null_samples++; if (s->nb_null_samples >= nb_samples_notify) { s->start = insamples->pts - (int64_t)(s->duration / av_q2d(time_base) + .5); #ifdef IDE_COMPILE tmp = av_ts_make_time_string(tmp__0, s->start, &time_base); av_dict_set(&insamples->metadata, "lavfi.silence_start", tmp, 0); #else av_dict_set(&insamples->metadata, "lavfi.silence_start", av_ts2timestr(s->start, &time_base), 0); #endif av_log(s, AV_LOG_INFO, "silence_start: %s\n", get_metadata_val(insamples, "lavfi.silence_start")); } } } else { if (s->start) { #ifdef IDE_COMPILE tmp = av_ts_make_time_string(tmp__0, insamples->pts, &time_base); av_dict_set(&insamples->metadata, "lavfi.silence_end", tmp, 0); tmp = av_ts_make_time_string(tmp__0, insamples->pts - s->start, &time_base); av_dict_set(&insamples->metadata, "lavfi.silence_duration", tmp, 0); #else av_dict_set(&insamples->metadata, "lavfi.silence_end", av_ts2timestr(insamples->pts, &time_base), 0); av_dict_set(&insamples->metadata, "lavfi.silence_duration", av_ts2timestr(insamples->pts - s->start, &time_base), 0); #endif av_log(s, AV_LOG_INFO, "silence_end: %s | silence_duration: %s\n", get_metadata_val(insamples, "lavfi.silence_end"), get_metadata_val(insamples, "lavfi.silence_duration")); } s->nb_null_samples = s->start = 0; } }
static void end_frame(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; BBoxContext *bbox = ctx->priv; AVFilterBufferRef *picref = inlink->cur_buf; FFBoundingBox box; int has_bbox, w, h; has_bbox = ff_calculate_bounding_box(&box, picref->data[0], picref->linesize[0], inlink->w, inlink->h, 16); w = box.x2 - box.x1 + 1; h = box.y2 - box.y1 + 1; av_log(ctx, AV_LOG_INFO, "n:%d pts:%s pts_time:%s", bbox->frame, av_ts2str(picref->pts), av_ts2timestr(picref->pts, &inlink->time_base)); if (has_bbox) { av_log(ctx, AV_LOG_INFO, "x1:%d x2:%d y1:%d y2:%d w:%d h:%d" " crop=%d:%d:%d:%d drawbox=%d:%d:%d:%d", box.x1, box.x2, box.y1, box.y2, w, h, w, h, box.x1, box.y1, /* crop params */ box.x1, box.y1, w, h); /* drawbox params */ } av_log(ctx, AV_LOG_INFO, "\n"); bbox->frame++; avfilter_end_frame(inlink->dst->outputs[0]); }
static int decode_packet(int *got_frame, int cached) { int ret = 0; int decoded = pkt.size; *got_frame = 0; if (pkt.stream_index == video_stream_idx) { /* decode video frame */ ret = avcodec_decode_video2(video_dec_ctx, frame, got_frame, &pkt); if (ret < 0) { fprintf(stderr, "Error decoding video frame (%s)\n", av_err2str(ret)); return ret; } if (*got_frame) { if (frame->width != width || frame->height != height || frame->format != pix_fmt) { /* To handle this change, one could call av_image_alloc again and * decode the following frames into another rawvideo file. */ fprintf(stderr, "Error: Width, height and pixel format have to be " "constant in a rawvideo file, but the width, height or " "pixel format of the input video changed:\n" "old: width = %d, height = %d, format = %s\n" "new: width = %d, height = %d, format = %s\n", width, height, av_get_pix_fmt_name(pix_fmt), frame->width, frame->height, av_get_pix_fmt_name(frame->format)); return -1; } printf("video_frame%s n:%d coded_n:%d pts:%s\n", cached ? "(cached)" : "", video_frame_count++, frame->coded_picture_number, av_ts2timestr(frame->pts, &video_dec_ctx->time_base)); /* copy decoded frame to destination buffer: * this is required since rawvideo expects non aligned data */ av_image_copy(video_dst_data, video_dst_linesize, (const uint8_t **)(frame->data), frame->linesize, pix_fmt, width, height); /* write to rawvideo file */ fwrite(video_dst_data[0], 1, video_dst_bufsize, video_dst_file); } } // /* If we use frame reference counting, we own the data and need // * to de-reference it when we don't use it anymore */ // // if (*got_frame && refcount) // if (*got_frame) // av_frame_unref(frame); return decoded; }
// TODO: document metadata static int filter_frame(AVFilterLink *inlink, AVFrame *picref) { AVFilterContext *ctx = inlink->dst; BlackDetectContext *blackdetect = ctx->priv; double picture_black_ratio = 0; const uint8_t *p = picref->data[0]; int x, i; for (i = 0; i < inlink->h; i++) { for (x = 0; x < inlink->w; x++) blackdetect->nb_black_pixels += p[x] <= blackdetect->pixel_black_th_i; p += picref->linesize[0]; } picture_black_ratio = (double)blackdetect->nb_black_pixels / (inlink->w * inlink->h); av_log(ctx, AV_LOG_DEBUG, "frame:%"PRId64" picture_black_ratio:%f pts:%s t:%s type:%c\n", inlink->frame_count_out, picture_black_ratio, av_ts2str(picref->pts), av_ts2timestr(picref->pts, &inlink->time_base), av_get_picture_type_char(picref->pict_type)); if (picture_black_ratio >= blackdetect->picture_black_ratio_th) { if (!blackdetect->black_started) { /* black starts here */ blackdetect->black_started = 1; blackdetect->black_start = picref->pts; av_dict_set(&picref->metadata, "lavfi.black_start", av_ts2timestr(blackdetect->black_start, &inlink->time_base), 0); } } else if (blackdetect->black_started) { /* black ends here */ blackdetect->black_started = 0; blackdetect->black_end = picref->pts; check_black_end(ctx); av_dict_set(&picref->metadata, "lavfi.black_end", av_ts2timestr(blackdetect->black_end, &inlink->time_base), 0); } blackdetect->last_picref_pts = picref->pts; blackdetect->nb_black_pixels = 0; return ff_filter_frame(inlink->dst->outputs[0], picref); }
static int filter_frame(AVFilterLink *inlink, AVFrame *buf) { AVFilterContext *ctx = inlink->dst; AShowInfoContext *s = ctx->priv; char chlayout_str[128]; uint32_t checksum = 0; int channels = av_get_channel_layout_nb_channels(buf->channel_layout); int planar = av_sample_fmt_is_planar(buf->format); int block_align = av_get_bytes_per_sample(buf->format) * (planar ? 1 : channels); int data_size = buf->nb_samples * block_align; int planes = planar ? channels : 1; int i; void *tmp_ptr = av_realloc(s->plane_checksums, channels * sizeof(*s->plane_checksums)); if (!tmp_ptr) return AVERROR(ENOMEM); s->plane_checksums = tmp_ptr; for (i = 0; i < planes; i++) { uint8_t *data = buf->extended_data[i]; s->plane_checksums[i] = av_adler32_update(0, data, data_size); checksum = i ? av_adler32_update(checksum, data, data_size) : s->plane_checksums[0]; } av_get_channel_layout_string(chlayout_str, sizeof(chlayout_str), -1, buf->channel_layout); av_log(ctx, AV_LOG_INFO, "n:%"PRId64" pts:%s pts_time:%s pos:%"PRId64" " "fmt:%s channels:%d chlayout:%s rate:%d nb_samples:%d " "checksum:%08X ", inlink->frame_count, av_ts2str(buf->pts), av_ts2timestr(buf->pts, &inlink->time_base), av_frame_get_pkt_pos(buf), av_get_sample_fmt_name(buf->format), av_frame_get_channels(buf), chlayout_str, buf->sample_rate, buf->nb_samples, checksum); av_log(ctx, AV_LOG_INFO, "plane_checksums: [ "); for (i = 0; i < planes; i++) av_log(ctx, AV_LOG_INFO, "%08X ", s->plane_checksums[i]); av_log(ctx, AV_LOG_INFO, "]\n"); return ff_filter_frame(inlink->dst->outputs[0], buf); }
static int end_frame(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; ShowInfoContext *showinfo = ctx->priv; AVFilterBufferRef *picref = inlink->cur_buf; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); uint32_t plane_checksum[4] = {0}, checksum = 0; int i, plane, vsub = desc->log2_chroma_h; for (plane = 0; picref->data[plane] && plane < 4; plane++) { int64_t linesize = av_image_get_linesize(picref->format, picref->video->w, plane); uint8_t *data = picref->data[plane]; int h = plane == 1 || plane == 2 ? inlink->h >> vsub : inlink->h; if (linesize < 0) return linesize; for (i = 0; i < h; i++) { plane_checksum[plane] = av_adler32_update(plane_checksum[plane], data, linesize); checksum = av_adler32_update(checksum, data, linesize); data += picref->linesize[plane]; } } av_log(ctx, AV_LOG_INFO, "n:%d pts:%s pts_time:%s pos:%"PRId64" " "fmt:%s sar:%d/%d s:%dx%d i:%c iskey:%d type:%c " "checksum:%08X plane_checksum:[%08X", showinfo->frame, av_ts2str(picref->pts), av_ts2timestr(picref->pts, &inlink->time_base), picref->pos, desc->name, picref->video->sample_aspect_ratio.num, picref->video->sample_aspect_ratio.den, picref->video->w, picref->video->h, !picref->video->interlaced ? 'P' : /* Progressive */ picref->video->top_field_first ? 'T' : 'B', /* Top / Bottom */ picref->video->key_frame, av_get_picture_type_char(picref->video->pict_type), checksum, plane_checksum[0]); for (plane = 1; picref->data[plane] && plane < 4; plane++) av_log(ctx, AV_LOG_INFO, " %08X", plane_checksum[plane]); av_log(ctx, AV_LOG_INFO, "]\n"); showinfo->frame++; return ff_end_frame(inlink->dst->outputs[0]); }
static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref) { AVFilterContext *ctx = inlink->dst; ShowInfoContext *showinfo = ctx->priv; uint32_t plane_checksum[8] = {0}, checksum = 0; char chlayout_str[128]; int plane; int linesize = samplesref->audio->nb_samples * av_get_bytes_per_sample(samplesref->format); if (!av_sample_fmt_is_planar(samplesref->format)) linesize *= av_get_channel_layout_nb_channels(samplesref->audio->channel_layout); for (plane = 0; samplesref->data[plane] && plane < 8; plane++) { uint8_t *data = samplesref->data[plane]; plane_checksum[plane] = av_adler32_update(plane_checksum[plane], data, linesize); checksum = av_adler32_update(checksum, data, linesize); } av_get_channel_layout_string(chlayout_str, sizeof(chlayout_str), -1, samplesref->audio->channel_layout); av_log(ctx, AV_LOG_INFO, "n:%d pts:%s pts_time:%s pos:%"PRId64" " "fmt:%s chlayout:%s nb_samples:%d rate:%d " "checksum:%08X plane_checksum[%08X", showinfo->frame, av_ts2str(samplesref->pts), av_ts2timestr(samplesref->pts, &inlink->time_base), samplesref->pos, av_get_sample_fmt_name(samplesref->format), chlayout_str, samplesref->audio->nb_samples, samplesref->audio->sample_rate, checksum, plane_checksum[0]); for (plane = 1; samplesref->data[plane] && plane < 8; plane++) av_log(ctx, AV_LOG_INFO, " %08X", plane_checksum[plane]); av_log(ctx, AV_LOG_INFO, "]\n"); showinfo->frame++; ff_filter_samples(inlink->dst->outputs[0], samplesref); }
static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); uint32_t plane_checksum[4] = {0}, checksum = 0; int i, plane, vsub = desc->log2_chroma_h; for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) { int64_t linesize = av_image_get_linesize(frame->format, frame->width, plane); uint8_t *data = frame->data[plane]; int h = plane == 1 || plane == 2 ? FF_CEIL_RSHIFT(inlink->h, vsub) : inlink->h; if (linesize < 0) return linesize; for (i = 0; i < h; i++) { plane_checksum[plane] = av_adler32_update(plane_checksum[plane], data, linesize); checksum = av_adler32_update(checksum, data, linesize); data += frame->linesize[plane]; } } av_log(ctx, AV_LOG_INFO, "n:%"PRId64" pts:%s pts_time:%s pos:%"PRId64" " "fmt:%s sar:%d/%d s:%dx%d i:%c iskey:%d type:%c " "checksum:%08X plane_checksum:[%08X", inlink->frame_count, av_ts2str(frame->pts), av_ts2timestr(frame->pts, &inlink->time_base), av_frame_get_pkt_pos(frame), desc->name, frame->sample_aspect_ratio.num, frame->sample_aspect_ratio.den, frame->width, frame->height, !frame->interlaced_frame ? 'P' : /* Progressive */ frame->top_field_first ? 'T' : 'B', /* Top / Bottom */ frame->key_frame, av_get_picture_type_char(frame->pict_type), checksum, plane_checksum[0]); for (plane = 1; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) av_log(ctx, AV_LOG_INFO, " %08X", plane_checksum[plane]); av_log(ctx, AV_LOG_INFO, "]\n"); return ff_filter_frame(inlink->dst->outputs[0], frame); }
static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; BlackDetectContext *blackdetect = ctx->priv; blackdetect->black_min_duration = blackdetect->black_min_duration_time / av_q2d(inlink->time_base); blackdetect->pixel_black_th_i = ff_fmt_is_in(inlink->format, yuvj_formats) ? // luminance_minimum_value + pixel_black_th * luminance_range_size blackdetect->pixel_black_th * 255 : 16 + blackdetect->pixel_black_th * (235 - 16); av_log(blackdetect, AV_LOG_VERBOSE, "black_min_duration:%s pixel_black_th:%f pixel_black_th_i:%d picture_black_ratio_th:%f\n", av_ts2timestr(blackdetect->black_min_duration, &inlink->time_base), blackdetect->pixel_black_th, blackdetect->pixel_black_th_i, blackdetect->picture_black_ratio_th); return 0; }
static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; BBoxContext *bbox = ctx->priv; FFBoundingBox box; int has_bbox, w, h; has_bbox = ff_calculate_bounding_box(&box, frame->data[0], frame->linesize[0], inlink->w, inlink->h, bbox->min_val); w = box.x2 - box.x1 + 1; h = box.y2 - box.y1 + 1; av_log(ctx, AV_LOG_INFO, "n:%"PRId64" pts:%s pts_time:%s", inlink->frame_count_out, av_ts2str(frame->pts), av_ts2timestr(frame->pts, &inlink->time_base)); if (has_bbox) { AVDictionary **metadata = &frame->metadata; SET_META("lavfi.bbox.x1", box.x1) SET_META("lavfi.bbox.x2", box.x2) SET_META("lavfi.bbox.y1", box.y1) SET_META("lavfi.bbox.y2", box.y2) SET_META("lavfi.bbox.w", w) SET_META("lavfi.bbox.h", h) av_log(ctx, AV_LOG_INFO, " x1:%d x2:%d y1:%d y2:%d w:%d h:%d" " crop=%d:%d:%d:%d drawbox=%d:%d:%d:%d", box.x1, box.x2, box.y1, box.y2, w, h, w, h, box.x1, box.y1, /* crop params */ box.x1, box.y1, w, h); /* drawbox params */ } av_log(ctx, AV_LOG_INFO, "\n"); return ff_filter_frame(inlink->dst->outputs[0], frame); }
static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; MetadataContext *s = ctx->priv; AVDictionary *metadata = av_frame_get_metadata(frame); AVDictionaryEntry *e; if (!metadata) return ff_filter_frame(outlink, frame); e = av_dict_get(metadata, !s->key ? "" : s->key, NULL, !s->key ? AV_DICT_IGNORE_SUFFIX: 0); switch (s->mode) { case METADATA_SELECT: if (!s->value && e && e->value) { return ff_filter_frame(outlink, frame); } else if (s->value && e && e->value && s->compare(s, e->value, s->value)) { return ff_filter_frame(outlink, frame); } break; case METADATA_ADD: if (e && e->value) { ; } else { av_dict_set(&metadata, s->key, s->value, 0); } return ff_filter_frame(outlink, frame); break; case METADATA_MODIFY: if (e && e->value) { av_dict_set(&metadata, s->key, s->value, 0); } return ff_filter_frame(outlink, frame); break; case METADATA_PRINT: if (!s->key && e) { s->print(ctx, "frame:%-4"PRId64" pts:%-7s pts_time:%-7s\n", inlink->frame_count, av_ts2str(frame->pts), av_ts2timestr(frame->pts, &inlink->time_base)); s->print(ctx, "%s=%s\n", e->key, e->value); while ((e = av_dict_get(metadata, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL) { s->print(ctx, "%s=%s\n", e->key, e->value); } } else if (e && e->value && (!s->value || (e->value && s->compare(s, e->value, s->value)))) { s->print(ctx, "frame:%-4"PRId64" pts:%-7s pts_time:%-7s\n", inlink->frame_count, av_ts2str(frame->pts), av_ts2timestr(frame->pts, &inlink->time_base)); s->print(ctx, "%s=%s\n", s->key, e->value); } return ff_filter_frame(outlink, frame); break; case METADATA_DELETE: if (e && e->value && s->value && s->compare(s, e->value, s->value)) { av_dict_set(&metadata, s->key, NULL, 0); } else if (e && e->value) { av_dict_set(&metadata, s->key, NULL, 0); } return ff_filter_frame(outlink, frame); break; default: av_assert0(0); }; av_frame_free(&frame); return 0; }
static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); uint32_t plane_checksum[4] = {0}, checksum = 0; int i, plane, vsub = desc->log2_chroma_h; for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) { int64_t linesize = av_image_get_linesize(frame->format, frame->width, plane); uint8_t *data = frame->data[plane]; int h = plane == 1 || plane == 2 ? FF_CEIL_RSHIFT(inlink->h, vsub) : inlink->h; if (linesize < 0) return linesize; for (i = 0; i < h; i++) { plane_checksum[plane] = av_adler32_update(plane_checksum[plane], data, linesize); checksum = av_adler32_update(checksum, data, linesize); data += frame->linesize[plane]; } } av_log(ctx, AV_LOG_INFO, "n:%"PRId64" pts:%s pts_time:%s pos:%"PRId64" " "fmt:%s sar:%d/%d s:%dx%d i:%c iskey:%d type:%c " "checksum:%08"PRIX32" plane_checksum:[%08"PRIX32, inlink->frame_count, av_ts2str(frame->pts), av_ts2timestr(frame->pts, &inlink->time_base), av_frame_get_pkt_pos(frame), desc->name, frame->sample_aspect_ratio.num, frame->sample_aspect_ratio.den, frame->width, frame->height, !frame->interlaced_frame ? 'P' : /* Progressive */ frame->top_field_first ? 'T' : 'B', /* Top / Bottom */ frame->key_frame, av_get_picture_type_char(frame->pict_type), checksum, plane_checksum[0]); for (plane = 1; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) av_log(ctx, AV_LOG_INFO, " %08"PRIX32, plane_checksum[plane]); av_log(ctx, AV_LOG_INFO, "]\n"); for (i = 0; i < frame->nb_side_data; i++) { AVFrameSideData *sd = frame->side_data[i]; av_log(ctx, AV_LOG_INFO, " side data - "); switch (sd->type) { case AV_FRAME_DATA_PANSCAN: av_log(ctx, AV_LOG_INFO, "pan/scan"); break; case AV_FRAME_DATA_A53_CC: av_log(ctx, AV_LOG_INFO, "A/53 closed captions (%d bytes)", sd->size); break; case AV_FRAME_DATA_STEREO3D: dump_stereo3d(ctx, sd); break; default: av_log(ctx, AV_LOG_WARNING, "unknown side data type %d (%d bytes)", sd->type, sd->size); break; } av_log(ctx, AV_LOG_INFO, "\n"); } return ff_filter_frame(inlink->dst->outputs[0], frame); }
static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); uint32_t plane_checksum[4] = {0}, checksum = 0; int64_t sum[4] = {0}, sum2[4] = {0}; int32_t pixelcount[4] = {0}; int i, plane, vsub = desc->log2_chroma_h; #ifdef IDE_COMPILE char tmp1[32] = {0}; char tmp2[32] = {0}; #endif for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) { int64_t linesize = av_image_get_linesize(frame->format, frame->width, plane); uint8_t *data = frame->data[plane]; int h = plane == 1 || plane == 2 ? FF_CEIL_RSHIFT(inlink->h, vsub) : inlink->h; if (linesize < 0) return linesize; for (i = 0; i < h; i++) { plane_checksum[plane] = av_adler32_update(plane_checksum[plane], data, linesize); checksum = av_adler32_update(checksum, data, linesize); update_sample_stats(data, linesize, sum+plane, sum2+plane); pixelcount[plane] += linesize; data += frame->linesize[plane]; } } #ifdef IDE_COMPILE av_log(ctx, AV_LOG_INFO, "n:%"PRId64" pts:%s pts_time:%s pos:%"PRId64" " "fmt:%s sar:%d/%d s:%dx%d i:%c iskey:%d type:%c " "checksum:%08"PRIX32" plane_checksum:[%08"PRIX32, inlink->frame_count, av_ts_make_string(tmp1, frame->pts), av_ts_make_time_string(tmp2, frame->pts, &inlink->time_base), av_frame_get_pkt_pos(frame), desc->name, frame->sample_aspect_ratio.num, frame->sample_aspect_ratio.den, frame->width, frame->height, !frame->interlaced_frame ? 'P' : /* Progressive */ frame->top_field_first ? 'T' : 'B', /* Top / Bottom */ frame->key_frame, av_get_picture_type_char(frame->pict_type), checksum, plane_checksum[0]); #else av_log(ctx, AV_LOG_INFO, "n:%"PRId64" pts:%s pts_time:%s pos:%"PRId64" " "fmt:%s sar:%d/%d s:%dx%d i:%c iskey:%d type:%c " "checksum:%08"PRIX32" plane_checksum:[%08"PRIX32, inlink->frame_count, av_ts2str(frame->pts), av_ts2timestr(frame->pts, &inlink->time_base), av_frame_get_pkt_pos(frame), desc->name, frame->sample_aspect_ratio.num, frame->sample_aspect_ratio.den, frame->width, frame->height, !frame->interlaced_frame ? 'P' : /* Progressive */ frame->top_field_first ? 'T' : 'B', /* Top / Bottom */ frame->key_frame, av_get_picture_type_char(frame->pict_type), checksum, plane_checksum[0]); #endif for (plane = 1; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) av_log(ctx, AV_LOG_INFO, " %08"PRIX32, plane_checksum[plane]); av_log(ctx, AV_LOG_INFO, "] mean:["); for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) av_log(ctx, AV_LOG_INFO, "%"PRId64" ", (sum[plane] + pixelcount[plane]/2) / pixelcount[plane]); av_log(ctx, AV_LOG_INFO, "\b] stdev:["); for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) av_log(ctx, AV_LOG_INFO, "%3.1f ", sqrt((sum2[plane] - sum[plane]*(double)sum[plane]/pixelcount[plane])/pixelcount[plane])); av_log(ctx, AV_LOG_INFO, "\b]\n"); for (i = 0; i < frame->nb_side_data; i++) { AVFrameSideData *sd = frame->side_data[i]; av_log(ctx, AV_LOG_INFO, " side data - "); switch (sd->type) { case AV_FRAME_DATA_PANSCAN: av_log(ctx, AV_LOG_INFO, "pan/scan"); break; case AV_FRAME_DATA_A53_CC: av_log(ctx, AV_LOG_INFO, "A/53 closed captions (%d bytes)", sd->size); break; case AV_FRAME_DATA_STEREO3D: dump_stereo3d(ctx, sd); break; case AV_FRAME_DATA_DISPLAYMATRIX: av_log(ctx, AV_LOG_INFO, "displaymatrix: rotation of %.2f degrees", av_display_rotation_get((int32_t *)sd->data)); break; case AV_FRAME_DATA_AFD: av_log(ctx, AV_LOG_INFO, "afd: value of %"PRIu8, sd->data[0]); break; default: av_log(ctx, AV_LOG_WARNING, "unknown side data type %d (%d bytes)", sd->type, sd->size); break; } av_log(ctx, AV_LOG_INFO, "\n"); } return ff_filter_frame(inlink->dst->outputs[0], frame); }
/* * Return * - 0 -- one packet was read and processed * - AVERROR(EAGAIN) -- no packets were available for selected file, * this function should be called again * - AVERROR_EOF -- this function should not be called again */ static int process_input(int file_index) { InputFile *ifile = input_files[file_index]; AVFormatContext *is; InputStream *ist; AVPacket pkt; int ret, i, j; is = ifile->ctx; // ****<< Capture a frame: audio/video/subtitle ret = get_input_packet(ifile, &pkt); // ****<< Call stack: av_read_frame() --> read_frame_internal() --> ff_read_packet() --> s->iformat->read_packet(s, pkt); --> dshow_read_frame(); if (ret == AVERROR(EAGAIN)) { ifile->eagain = 1; return ret; } if (ret < 0) { if (ret != AVERROR_EOF) { print_error(is->filename, ret); if (exit_on_error) exit_program(1); } ifile->eof_reached = 1; for (i = 0; i < ifile->nb_streams; i++) { ist = input_streams[ifile->ist_index + i]; if (ist->decoding_needed) output_packet(ist, NULL); /* mark all outputs that don't go through lavfi as finished */ for (j = 0; j < nb_output_streams; j++) { OutputStream *ost = output_streams[j]; if (ost->source_index == ifile->ist_index + i && (ost->stream_copy || ost->enc->type == AVMEDIA_TYPE_SUBTITLE)) close_output_stream(ost); } } return AVERROR(EAGAIN); } reset_eagain(); if (do_pkt_dump) { av_pkt_dump_log2(NULL, AV_LOG_DEBUG, &pkt, do_hex_dump, is->streams[pkt.stream_index]); } /* the following test is needed in case new streams appear dynamically in stream : we ignore them */ if (pkt.stream_index >= ifile->nb_streams) { report_new_stream(file_index, &pkt); goto discard_packet; } ist = input_streams[ifile->ist_index + pkt.stream_index]; ist->data_size += pkt.size; ist->nb_packets++; if (ist->discard) goto discard_packet; if (debug_ts) { av_log(NULL, AV_LOG_INFO, "demuxer -> ist_index:%d type:%s " "next_dts:%s next_dts_time:%s next_pts:%s next_pts_time:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s off:%s off_time:%s\n", ifile->ist_index + pkt.stream_index, av_get_media_type_string(ist->dec_ctx->codec_type), av_ts2str(ist->next_dts), av_ts2timestr(ist->next_dts, &AV_TIME_BASE_Q), av_ts2str(ist->next_pts), av_ts2timestr(ist->next_pts, &AV_TIME_BASE_Q), av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ist->st->time_base), av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ist->st->time_base), av_ts2str(input_files[ist->file_index]->ts_offset), av_ts2timestr(input_files[ist->file_index]->ts_offset, &AV_TIME_BASE_Q)); } if(!ist->wrap_correction_done && is->start_time != AV_NOPTS_VALUE && ist->st->pts_wrap_bits < 64) { int64_t stime, stime2; // Correcting starttime based on the enabled streams // FIXME this ideally should be done before the first use of starttime but we do not know which are the enabled streams at that point. // so we instead do it here as part of discontinuity handling if ( ist->next_dts == AV_NOPTS_VALUE && ifile->ts_offset == -is->start_time && (is->iformat->flags & AVFMT_TS_DISCONT)) { int64_t new_start_time = INT64_MAX; for (i=0; i<is->nb_streams; i++) { AVStream *st = is->streams[i]; if(st->discard == AVDISCARD_ALL || st->start_time == AV_NOPTS_VALUE) continue; new_start_time = FFMIN(new_start_time, av_rescale_q(st->start_time, st->time_base, AV_TIME_BASE_Q)); } if (new_start_time > is->start_time) { av_log(is, AV_LOG_VERBOSE, "Correcting start time by %"PRId64"\n", new_start_time - is->start_time); ifile->ts_offset = -new_start_time; } } stime = av_rescale_q(is->start_time, AV_TIME_BASE_Q, ist->st->time_base); stime2= stime + (1ULL<<ist->st->pts_wrap_bits); ist->wrap_correction_done = 1; if(stime2 > stime && pkt.dts != AV_NOPTS_VALUE && pkt.dts > stime + (1LL<<(ist->st->pts_wrap_bits-1))) { pkt.dts -= 1ULL<<ist->st->pts_wrap_bits; ist->wrap_correction_done = 0; } if(stime2 > stime && pkt.pts != AV_NOPTS_VALUE && pkt.pts > stime + (1LL<<(ist->st->pts_wrap_bits-1))) { pkt.pts -= 1ULL<<ist->st->pts_wrap_bits; ist->wrap_correction_done = 0; } } /* add the stream-global side data to the first packet */ if (ist->nb_packets == 1) if (ist->st->nb_side_data) av_packet_split_side_data(&pkt); for (i = 0; i < ist->st->nb_side_data; i++) { AVPacketSideData *src_sd = &ist->st->side_data[i]; uint8_t *dst_data; if (av_packet_get_side_data(&pkt, src_sd->type, NULL)) continue; dst_data = av_packet_new_side_data(&pkt, src_sd->type, src_sd->size); if (!dst_data) exit_program(1); memcpy(dst_data, src_sd->data, src_sd->size); } // ****<< pkt.pts: 采集时间戳(以毫秒为单位; 一般为系统时间) // ****<< ts_offset: 起始时间戳(以毫秒为单位; 一般为第一帧采集时间戳的相反数) // ****<< 最终.pts: 相对时间戳(以毫秒为单位; 从第一帧到现在的相对时间) if (pkt.dts != AV_NOPTS_VALUE) pkt.dts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, ist->st->time_base); if (pkt.pts != AV_NOPTS_VALUE) pkt.pts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, ist->st->time_base); if (pkt.pts != AV_NOPTS_VALUE) pkt.pts *= ist->ts_scale; if (pkt.dts != AV_NOPTS_VALUE) pkt.dts *= ist->ts_scale; if (pkt.dts != AV_NOPTS_VALUE && ist->next_dts == AV_NOPTS_VALUE && !copy_ts && (is->iformat->flags & AVFMT_TS_DISCONT) && ifile->last_ts != AV_NOPTS_VALUE) { int64_t pkt_dts = av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q); int64_t delta = pkt_dts - ifile->last_ts; if(delta < -1LL*dts_delta_threshold*AV_TIME_BASE || (delta > 1LL*dts_delta_threshold*AV_TIME_BASE && ist->dec_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE)) { ifile->ts_offset -= delta; av_log(NULL, AV_LOG_DEBUG, "Inter stream timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", delta, ifile->ts_offset); pkt.dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); if (pkt.pts != AV_NOPTS_VALUE) pkt.pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); } } if (pkt.dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE && !copy_ts) { int64_t pkt_dts = av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q); int64_t delta = pkt_dts - ist->next_dts; if (is->iformat->flags & AVFMT_TS_DISCONT) { if (delta < -1LL*dts_delta_threshold*AV_TIME_BASE || (delta > 1LL*dts_delta_threshold*AV_TIME_BASE && ist->dec_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) || pkt_dts + AV_TIME_BASE/10 < FFMAX(ist->pts, ist->dts)) { ifile->ts_offset -= delta; av_log(NULL, AV_LOG_DEBUG, "timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", delta, ifile->ts_offset); pkt.dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); if (pkt.pts != AV_NOPTS_VALUE) pkt.pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); } } else { if ( delta < -1LL*dts_error_threshold*AV_TIME_BASE || (delta > 1LL*dts_error_threshold*AV_TIME_BASE && ist->dec_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE)) { av_log(NULL, AV_LOG_WARNING, "DTS %"PRId64", next:%"PRId64" st:%d invalid dropping\n", pkt.dts, ist->next_dts, pkt.stream_index); pkt.dts = AV_NOPTS_VALUE; } if (pkt.pts != AV_NOPTS_VALUE) { int64_t pkt_pts = av_rescale_q(pkt.pts, ist->st->time_base, AV_TIME_BASE_Q); delta = pkt_pts - ist->next_dts; if ( delta < -1LL*dts_error_threshold*AV_TIME_BASE || (delta > 1LL*dts_error_threshold*AV_TIME_BASE && ist->dec_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE)) { av_log(NULL, AV_LOG_WARNING, "PTS %"PRId64", next:%"PRId64" invalid dropping st:%d\n", pkt.pts, ist->next_dts, pkt.stream_index); pkt.pts = AV_NOPTS_VALUE; } } } } if (pkt.dts != AV_NOPTS_VALUE) ifile->last_ts = av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q); if (debug_ts) { av_log(NULL, AV_LOG_INFO, "demuxer+ffmpeg -> ist_index:%d type:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s off:%s off_time:%s\n", ifile->ist_index + pkt.stream_index, av_get_media_type_string(ist->dec_ctx->codec_type), av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ist->st->time_base), av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ist->st->time_base), av_ts2str(input_files[ist->file_index]->ts_offset), av_ts2timestr(input_files[ist->file_index]->ts_offset, &AV_TIME_BASE_Q)); } sub2video_heartbeat(ist, pkt.pts); ret = output_packet(ist, &pkt); // ****<< see output_packet.c if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d: %s\n", ist->file_index, ist->st->index, av_err2str(ret)); if (exit_on_error) exit_program(1); } discard_packet: av_free_packet(&pkt); return 0; }
static int decode_packet(int *got_frame, int cached) { int ret = 0; if (pkt.stream_index == video_stream_idx) { /* decode video frame */ ret = avcodec_decode_video2(video_dec_ctx, frame, got_frame, &pkt); if (ret < 0) { fprintf(stderr, "Error decoding video frame\n"); return ret; } if (*got_frame) { printf("video_frame%s n:%d coded_n:%d pts:%s\n", cached ? "(cached)" : "", video_frame_count++, frame->coded_picture_number, av_ts2timestr(frame->pts, &video_dec_ctx->time_base)); /* copy decoded frame to destination buffer: * this is required since rawvideo expects non aligned data */ av_image_copy(video_dst_data, video_dst_linesize, (const uint8_t **)(frame->data), frame->linesize, video_dec_ctx->pix_fmt, video_dec_ctx->width, video_dec_ctx->height); /* write to rawvideo file */ fwrite(video_dst_data[0], 1, video_dst_bufsize, video_dst_file); } } else if (pkt.stream_index == audio_stream_idx) { /* decode audio frame */ ret = avcodec_decode_audio4(audio_dec_ctx, frame, got_frame, &pkt); if (ret < 0) { fprintf(stderr, "Error decoding audio frame\n"); return ret; } if (*got_frame) { printf("audio_frame%s n:%d nb_samples:%d pts:%s\n", cached ? "(cached)" : "", audio_frame_count++, frame->nb_samples, av_ts2timestr(frame->pts, &audio_dec_ctx->time_base)); ret = av_samples_alloc(audio_dst_data, &audio_dst_linesize, frame->channels, frame->nb_samples, frame->format, 1); if (ret < 0) { fprintf(stderr, "Could not allocate audio buffer\n"); return AVERROR(ENOMEM); } /* TODO: extend return code of the av_samples_* functions so that this call is not needed */ audio_dst_bufsize = av_samples_get_buffer_size(NULL, frame->channels, frame->nb_samples, frame->format, 1); /* copy audio data to destination buffer: * this is required since rawaudio expects non aligned data */ av_samples_copy(audio_dst_data, frame->data, 0, 0, frame->nb_samples, frame->channels, frame->format); /* write to rawaudio file */ fwrite(audio_dst_data[0], 1, audio_dst_bufsize, audio_dst_file); av_freep(&audio_dst_data[0]); } } return ret; }
/** * Decode a frame to a packet, run the result through SwrContext, if desired, encode it via an appropriate * encoder, and write the results to the Java-side native buffer. * * @param aio FFAudio context * @param cached true or false * @return number of bytes placed into java buffer or a negative value, if something went wrong */ static int decode_packet(FFAudioIO *aio, int cached) { int res = 0; uint8_t **resample_buf = NULL; jobject byte_buffer = NULL; uint8_t *javaBuffer = NULL; uint32_t out_buf_size = 0; int out_buf_samples = 0; int64_t out_channel_count; int64_t out_sample_rate; int flush = aio->got_frame; enum AVSampleFormat out; int bytesConsumed = 0; init_ids(aio->env, aio->java_instance); av_opt_get_int(aio->swr_context, "out_channel_count", 0, &out_channel_count); av_opt_get_int(aio->swr_context, "out_sample_rate", 0, &out_sample_rate); av_opt_get_sample_fmt(aio->swr_context, "out_sample_fmt", 0, &out); resample_buf = av_mallocz(sizeof(uint8_t *) * 1); // one plane! // make sure we really have an audio packet if (aio->decode_packet.stream_index == aio->stream_index) { // decode frame // got_frame indicates whether we got a frame bytesConsumed = avcodec_decode_audio4(aio->decode_context, aio->decode_frame, &aio->got_frame, &aio->decode_packet); if (bytesConsumed < 0) { throwUnsupportedAudioFileExceptionIfError(aio->env, bytesConsumed, "Failed to decode audio frame."); return bytesConsumed; } if (aio->got_frame) { aio->decoded_samples += aio->decode_frame->nb_samples; out_buf_samples = aio->decode_frame->nb_samples; #ifdef DEBUG fprintf(stderr, "samples%s n:%" PRIu64 " nb_samples:%d pts:%s\n", cached ? "(cached)" : "", aio->decoded_samples, aio->decode_frame->nb_samples, av_ts2timestr(aio->decode_frame->pts, &aio->decode_context->time_base)); #endif // adjust out sample number for a different sample rate // this is an estimate!! out_buf_samples = av_rescale_rnd( swr_get_delay(aio->swr_context, aio->stream->codecpar->sample_rate) + aio->decode_frame->nb_samples, out_sample_rate, aio->stream->codecpar->sample_rate, AV_ROUND_UP ); // allocate new aio->audio_data buffers res = av_samples_alloc(aio->audio_data, NULL, av_frame_get_channels(aio->decode_frame), aio->decode_frame->nb_samples, aio->decode_frame->format, 1); if (res < 0) { throwIOExceptionIfError(aio->env, res, "Could not allocate audio buffer."); return AVERROR(ENOMEM); } // copy audio data to aio->audio_data av_samples_copy(aio->audio_data, aio->decode_frame->data, 0, 0, aio->decode_frame->nb_samples, av_frame_get_channels(aio->decode_frame), aio->decode_frame->format); res = resample(aio, resample_buf, out_buf_samples, (const uint8_t **)aio->audio_data, aio->decode_frame->nb_samples); if (res < 0) goto bail; else out_buf_samples = res; } else if (flush && swr_get_delay(aio->swr_context, aio->stream->codecpar->sample_rate)) { res = resample(aio, resample_buf, swr_get_delay(aio->swr_context, aio->stream->codecpar->sample_rate), NULL, 0); if (res < 0) goto bail; else out_buf_samples = res; } else { #ifdef DEBUG fprintf(stderr, "Got no frame.\n"); #endif } if (out_buf_samples > 0) { res = av_samples_get_buffer_size(NULL, (int)out_channel_count, out_buf_samples, out, 1); if (res < 0) goto bail; else out_buf_size = res; // ensure native buffer capacity if (aio->java_buffer_capacity < out_buf_size) { aio->java_buffer_capacity = (*aio->env)->CallIntMethod(aio->env, aio->java_instance, setNativeBufferCapacity_MID, (jint)out_buf_size); } // get java-managed byte buffer reference byte_buffer = (*aio->env)->GetObjectField(aio->env, aio->java_instance, nativeBuffer_FID); if (!byte_buffer) { res = -1; throwIOExceptionIfError(aio->env, 1, "Failed to get native buffer."); goto bail; } // we have some samples, let's copy them to the java buffer, using the desired encoding javaBuffer = (uint8_t *)(*aio->env)->GetDirectBufferAddress(aio->env, byte_buffer); if (!javaBuffer) { throwIOExceptionIfError(aio->env, 1, "Failed to get address for native buffer."); goto bail; } if (aio->encode_context) { aio->encode_frame->nb_samples = out_buf_samples; res = encode_buffer(aio, resample_buf[0], out_buf_size, javaBuffer); if (res < 0) { out_buf_size = 0; goto bail; } out_buf_size = res; } else { memcpy(javaBuffer, resample_buf[0], out_buf_size); } // we already wrote to the buffer, now we still need to // set new bytebuffer limit and position to 0. (*aio->env)->CallObjectMethod(aio->env, byte_buffer, rewind_MID); (*aio->env)->CallObjectMethod(aio->env, byte_buffer, limit_MID, out_buf_size); } } aio->resampled_samples += out_buf_size; bail: if (resample_buf) { if (resample_buf[0]) av_freep(&resample_buf[0]); av_free(resample_buf); } if (aio->audio_data[0]) av_freep(&aio->audio_data[0]); return res; }
int main(int argc, char **argv) { int opt, ret, stream, flags; const char *filename; AVFormatContext *avf = NULL; int64_t min_ts, max_ts, ts; AVPacket packet; while ((opt = getopt(argc, argv, "h")) != -1) { switch (opt) { case 'h': usage(0); default: usage(1); } } argc -= optind; argv += optind; if (!argc) usage(1); filename = *argv; argv++; argc--; av_register_all(); if ((ret = avformat_open_input(&avf, filename, NULL, NULL)) < 0) { fprintf(stderr, "%s: %s\n", filename, av_err2str(ret)); return 1; } if ((ret = avformat_find_stream_info(avf, NULL)) < 0) { fprintf(stderr, "%s: could not find codec parameters: %s\n", filename, av_err2str(ret)); return 1; } for (; argc; argc--, argv++) { if (!strcmp(*argv, "read")) { ret = av_read_frame(avf, &packet); if (ret < 0) { printf("read: %d (%s)\n", ret, av_err2str(ret)); } else { AVRational *tb = &avf->streams[packet.stream_index]->time_base; printf("read: %d size=%d stream=%d dts=%s (%s) pts=%s (%s)\n", ret, packet.size, packet.stream_index, av_ts2str(packet.dts), av_ts2timestr(packet.dts, tb), av_ts2str(packet.pts), av_ts2timestr(packet.pts, tb)); av_packet_unref(&packet); } } else if (sscanf(*argv, "seek:%i:%"SCNi64":%"SCNi64":%"SCNi64":%i", &stream, &min_ts, &ts, &max_ts, &flags) == 5) { ret = avformat_seek_file(avf, stream, min_ts, ts, max_ts, flags); printf("seek: %d (%s)\n", ret, av_err2str(ret)); } else { fprintf(stderr, "'%s': unknown command\n", *argv); return 1; } } avformat_close_input(&avf); return 0; }
static int decode_packet(AVCodecContext *dec_ctx, FILE *dst_file, AVFrame *frame, int *got_frame, int *frame_count, AVPacket *pkt) { int ret = -1; *got_frame = 0; AVSubtitle sub; unsigned i, j, k, l; if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) { ret = 0; /* decode video frame */ ret = avcodec_decode_video2(dec_ctx, frame, got_frame, pkt); if (ret < 0) { fprintf(stderr, "Error decoding video frame (%s)\n", av_err2str(ret)); return ret; } if (*got_frame) { if (frame->width != width || frame->height != height || frame->format != pix_fmt) { fprintf(stderr, "Error: input video width/height/format changed:\n" "old: width = %d, height = %d, format = %s\n" "new: width = %d, height = %d, format = %s\n", width, height, av_get_pix_fmt_name(pix_fmt), dec_ctx->width, dec_ctx->height, av_get_pix_fmt_name(dec_ctx->pix_fmt)); return -1; } printf("video_frame n:%d coded_n:%d pts:%s\n", *frame_count, frame->coded_picture_number, av_ts2timestr(frame->pts, &dec_ctx->time_base)); /* copy decoded frame to destination buffer: * this is required since rawvideo expects non aligned data */ av_image_copy(video_dst_data, video_dst_linesize, (const uint8_t **)(frame->data), frame->linesize, pix_fmt, width, height); *frame_count += 1; /* write to rawvideo file */ fwrite(video_dst_data[0], 1, video_dst_bufsize, dst_file); } } else if (dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) { ret = 0; /* decode audio frame */ ret = avcodec_decode_audio4(dec_ctx, frame, got_frame, pkt); if (ret < 0) { fprintf(stderr, "Error decoding audio frame (%s)\n", av_err2str(ret)); return ret; } /* Some audio decoders decode only part of the packet, and have to be * called again with the remainder of the packet data. * Sample: fate-suite/lossless-audio/luckynight-partial.shn * Also, some decoders might over-read the packet. */ ret = FFMIN(ret, pkt->size); if (*got_frame) { size_t unpadded_linesize = frame->nb_samples * av_get_bytes_per_sample(frame->format); printf("audio_frame n:%d nb_samples:%d pts:%s\n", *frame_count, frame->nb_samples, av_ts2timestr(frame->pts, &dec_ctx->time_base)); *frame_count += 1; /* Write the raw audio data samples of the first plane. This works * fine for packed formats (e.g. AV_SAMPLE_FMT_S16). However, * most audio decoders output planar audio, which uses a separate * plane of audio samples for each channel (e.g. AV_SAMPLE_FMT_S16P). * In other words, this code will write only the first audio channel * in these cases. * You should use libswresample or libavfilter to convert the frame * to packed data. */ fwrite(frame->extended_data[0], 1, unpadded_linesize, dst_file); } } else if (dec_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE) { ret = 0; /* decode video frame */ ret = avcodec_decode_subtitle2(dec_ctx, &sub, got_frame, pkt); if (ret < 0) { fprintf(stderr, "Error decoding subtitle (%s)\n", av_err2str(ret)); return ret; } if (*got_frame) { printf("subtitle n:%d format:%u pts:%s start_time:%u end_time:%u num_recs:%u\n", *frame_count, sub.format, av_ts2timestr(sub.pts, &dec_ctx->time_base), sub.start_display_time, sub.end_display_time, sub.num_rects); *frame_count += 1; /* write to text file */ for (i = 0; i < sub.num_rects; i += 1) { fprintf(dst_file, "x:%d y:%d w:%d h:%d nb_colors:%d flags:%x linesizes:%d,%d,%d,%d,%d,%d,%d,%d\n" "text:%s\nass:%s\n", sub.rects[i]->x, sub.rects[i]->y, sub.rects[i]->w, sub.rects[i]->h, sub.rects[i]->nb_colors, sub.rects[i]->flags, sub.rects[i]->pict.linesize[0], sub.rects[i]->pict.linesize[1], sub.rects[i]->pict.linesize[2], sub.rects[i]->pict.linesize[3], sub.rects[i]->pict.linesize[4], sub.rects[i]->pict.linesize[5], sub.rects[i]->pict.linesize[6], sub.rects[i]->pict.linesize[7], sub.rects[i]->text, sub.rects[i]->ass); for (j = 0; j < AV_NUM_DATA_POINTERS; j += 1) { if (sub.rects[i]->pict.linesize[j]) { fprintf(dst_file, "data:%d\n", j); for (k = 0; k < sub.rects[i]->h; k += 1) { for (l = 0; l < sub.rects[i]->w; l += 1) { fprintf(dst_file, "%x", sub.rects[i]->pict.data[j][l + k * sub.rects[i]->pict.linesize[j]]); } fprintf(dst_file, "\n"); } } } } avsubtitle_free(&sub); } } /* de-reference the frame, which is not used anymore */ if (*got_frame) av_frame_unref(frame); return ret; }
static int filter_frame(AVFilterLink *inlink, AVFrame *buf) { AVFilterContext *ctx = inlink->dst; AShowInfoContext *s = ctx->priv; char chlayout_str[128]; uint32_t checksum = 0; int channels = inlink->channels; int planar = av_sample_fmt_is_planar(buf->format); int block_align = av_get_bytes_per_sample(buf->format) * (planar ? 1 : channels); int data_size = buf->nb_samples * block_align; int planes = planar ? channels : 1; int i; void *tmp_ptr = av_realloc_array(s->plane_checksums, channels, sizeof(*s->plane_checksums)); if (!tmp_ptr) return AVERROR(ENOMEM); s->plane_checksums = tmp_ptr; for (i = 0; i < planes; i++) { uint8_t *data = buf->extended_data[i]; s->plane_checksums[i] = av_adler32_update(0, data, data_size); checksum = i ? av_adler32_update(checksum, data, data_size) : s->plane_checksums[0]; } av_get_channel_layout_string(chlayout_str, sizeof(chlayout_str), -1, buf->channel_layout); av_log(ctx, AV_LOG_INFO, "n:%"PRId64" pts:%s pts_time:%s pos:%"PRId64" " "fmt:%s channels:%d chlayout:%s rate:%d nb_samples:%d " "checksum:%08"PRIX32" ", inlink->frame_count_out, av_ts2str(buf->pts), av_ts2timestr(buf->pts, &inlink->time_base), av_frame_get_pkt_pos(buf), av_get_sample_fmt_name(buf->format), av_frame_get_channels(buf), chlayout_str, buf->sample_rate, buf->nb_samples, checksum); av_log(ctx, AV_LOG_INFO, "plane_checksums: [ "); for (i = 0; i < planes; i++) av_log(ctx, AV_LOG_INFO, "%08"PRIX32" ", s->plane_checksums[i]); av_log(ctx, AV_LOG_INFO, "]\n"); for (i = 0; i < buf->nb_side_data; i++) { AVFrameSideData *sd = buf->side_data[i]; av_log(ctx, AV_LOG_INFO, " side data - "); switch (sd->type) { case AV_FRAME_DATA_MATRIXENCODING: dump_matrixenc (ctx, sd); break; case AV_FRAME_DATA_DOWNMIX_INFO: dump_downmix (ctx, sd); break; case AV_FRAME_DATA_REPLAYGAIN: dump_replaygain(ctx, sd); break; case AV_FRAME_DATA_AUDIO_SERVICE_TYPE: dump_audio_service_type(ctx, sd); break; default: dump_unknown (ctx, sd); break; } av_log(ctx, AV_LOG_INFO, "\n"); } return ff_filter_frame(inlink->dst->outputs[0], buf); }
static int decode_packet(int *got_frame, int cached) { int ret = 0; int decoded = pkt.size; *got_frame = 0; //avpicture_fill(h264_frame, (uint8_t*)yuv_buff, PIX_FMT_YUV420P, frame->width*SCALE_MULTIPLE, frame->height*SCALE_MULTIPLE); if (pkt.stream_index == video_stream_idx) { /* decode video frame */ ret = avcodec_decode_video2(video_dec_ctx, frame, got_frame, &pkt); if (ret < 0) { fprintf(stderr, "Error decoding video frame (%s)\n", av_err2str(ret)); return ret; } if (*got_frame) { if (frame->width != width || frame->height != height || frame->format != pix_fmt) { /* To handle this change, one could call av_image_alloc again and * decode the following frames into another rawvideo file. */ fprintf(stderr, "Error: Width, height and pixel format have to be " "constant in a rawvideo file, but the width, height or " "pixel format of the input video changed:\n" "old: width = %d, height = %d, format = %s\n" "new: width = %d, height = %d, format = %s\n", width, height, av_get_pix_fmt_name(pix_fmt), frame->width, frame->height, av_get_pix_fmt_name(frame->format)); return -1; } printf("video_frame%s n:%d coded_n:%d pts:%s\n", cached ? "(cached)" : "", video_frame_count++, frame->coded_picture_number, av_ts2timestr(frame->pts, &video_dec_ctx->time_base)); /*scale yuv*/ /* copy decoded frame to destination buffer: * this is required since rawvideo expects non aligned data */ av_image_copy(video_dst_data, video_dst_linesize, (const uint8_t **)(frame->data), frame->linesize, pix_fmt, width, height); /* convert to destination format */ sws_scale(sws_ctx, (const uint8_t * const*)video_dst_data, video_dst_linesize, 0, height, scale_video_dst_data , scale_video_dst_linesize); /*encode yuv to h264*/ encode2file(); /* write to rawvideo file */ //fwrite(video_dst_data[0], 1, video_dst_bufsize, video_dst_file); fwrite(scale_video_dst_data[0], 1, scale_video_dst_bufsize, video_dst_file); } } else if (pkt.stream_index == audio_stream_idx) { /* decode audio frame */ ret = avcodec_decode_audio4(audio_dec_ctx, frame, got_frame, &pkt); if (ret < 0) { fprintf(stderr, "Error decoding audio frame (%s)\n", av_err2str(ret)); return ret; } /* Some audio decoders decode only part of the packet, and have to be * called again with the remainder of the packet data. * Sample: fate-suite/lossless-audio/luckynight-partial.shn * Also, some decoders might over-read the packet. */ decoded = FFMIN(ret, pkt.size); if (*got_frame) { size_t unpadded_linesize = frame->nb_samples * av_get_bytes_per_sample(frame->format); printf("audio_frame%s n:%d nb_samples:%d pts:%s\n", cached ? "(cached)" : "", audio_frame_count++, frame->nb_samples, av_ts2timestr(frame->pts, &audio_dec_ctx->time_base)); /* Write the raw audio data samples of the first plane. This works * fine for packed formats (e.g. AV_SAMPLE_FMT_S16). However, * most audio decoders output planar audio, which uses a separate * plane of audio samples for each channel (e.g. AV_SAMPLE_FMT_S16P). * In other words, this code will write only the first audio channel * in these cases. * You should use libswresample or libavfilter to convert the frame * to packed data. */ fwrite(frame->extended_data[0], 1, unpadded_linesize, audio_dst_file); } } /* If we use frame reference counting, we own the data and need * to de-reference it when we don't use it anymore */ if (*got_frame && refcount) av_frame_unref(frame); return decoded; }