static int seek_test(const char *input_filename, const char *start, const char *end) { AVCodec *codec = NULL; AVCodecContext *ctx= NULL; AVCodecParameters *origin_par = NULL; AVFrame *fr = NULL; AVFormatContext *fmt_ctx = NULL; int video_stream; int result; int i, j; long int start_ts, end_ts; size_of_array = 0; number_of_elements = 0; crc_array = pts_array = NULL; result = avformat_open_input(&fmt_ctx, input_filename, NULL, NULL); if (result < 0) { av_log(NULL, AV_LOG_ERROR, "Can't open file\n"); return result; } result = avformat_find_stream_info(fmt_ctx, NULL); if (result < 0) { av_log(NULL, AV_LOG_ERROR, "Can't get stream info\n"); return result; } start_ts = read_seek_range(start); end_ts = read_seek_range(end); if ((start_ts < 0) || (end_ts < 0)) return -1; //TODO: add ability to work with audio format video_stream = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); if (video_stream < 0) { av_log(NULL, AV_LOG_ERROR, "Can't find video stream in input file\n"); return -1; } origin_par = fmt_ctx->streams[video_stream]->codecpar; codec = avcodec_find_decoder(origin_par->codec_id); if (!codec) { av_log(NULL, AV_LOG_ERROR, "Can't find decoder\n"); return -1; } ctx = avcodec_alloc_context3(codec); if (!ctx) { av_log(NULL, AV_LOG_ERROR, "Can't allocate decoder context\n"); return AVERROR(ENOMEM); } result = avcodec_parameters_to_context(ctx, origin_par); if (result) { av_log(NULL, AV_LOG_ERROR, "Can't copy decoder context\n"); return result; } result = avcodec_open2(ctx, codec, NULL); if (result < 0) { av_log(ctx, AV_LOG_ERROR, "Can't open decoder\n"); return result; } fr = av_frame_alloc(); if (!fr) { av_log(NULL, AV_LOG_ERROR, "Can't allocate frame\n"); return AVERROR(ENOMEM); } result = compute_crc_of_packets(fmt_ctx, video_stream, ctx, fr, i, j, 1); if (result != 0) return -1; for (i = start_ts; i < end_ts; i += 100) { for (j = i + 100; j < end_ts; j += 100) result = compute_crc_of_packets(fmt_ctx, video_stream, ctx, fr, i, j, 0); if (result != 0) return -1; } av_freep(&crc_array); av_freep(&pts_array); av_frame_free(&fr); avcodec_close(ctx); avformat_close_input(&fmt_ctx); avcodec_free_context(&ctx); return 0; }
int stream_component_open(VideoState *is, int stream_index) { AVFormatContext *pFormatCtx = is->pFormatCtx; AVCodecContext *codecCtx = NULL; AVCodec *codec = NULL; AVDictionary *optionsDict = NULL; if(stream_index < 0 || stream_index >= pFormatCtx->nb_streams) { return -1; } // Get a pointer to the codec context for the video stream codecCtx = pFormatCtx->streams[stream_index]->codec; if(codecCtx->codec_type == AVMEDIA_TYPE_AUDIO) { is->audio_callback = audio_callback; // Set audio settings from codec info AudioPlayer *player = malloc(sizeof(AudioPlayer)); is->audio_player = player; createEngine(&is->audio_player); createBufferQueueAudioPlayer(&is->audio_player, is, codecCtx->channels, codecCtx->sample_rate); //is->audio_hw_buf_size = 4096; } else if (codecCtx->codec_type == AVMEDIA_TYPE_VIDEO) { // Set video settings from codec info VideoPlayer *player = malloc(sizeof(VideoPlayer)); is->video_player = player; createVideoEngine(&is->video_player); } codec = avcodec_find_decoder(codecCtx->codec_id); if(!codec || (avcodec_open2(codecCtx, codec, &optionsDict) < 0)) { fprintf(stderr, "Unsupported codec!\n"); return -1; } switch(codecCtx->codec_type) { case AVMEDIA_TYPE_AUDIO: is->audioStream = stream_index; is->audio_st = pFormatCtx->streams[stream_index]; is->audio_buf_size = 0; is->audio_buf_index = 0; /* averaging filter for audio sync */ is->audio_diff_avg_coef = exp(log(0.01 / AUDIO_DIFF_AVG_NB)); is->audio_diff_avg_count = 0; /* Correct audio only if larger error than this */ is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / codecCtx->sample_rate; is->sws_ctx_audio = swr_alloc(); if (!is->sws_ctx_audio) { fprintf(stderr, "Could not allocate resampler context\n"); return -1; } memset(&is->audio_pkt, 0, sizeof(is->audio_pkt)); packet_queue_init(&is->audioq); break; case AVMEDIA_TYPE_VIDEO: is->videoStream = stream_index; is->video_st = pFormatCtx->streams[stream_index]; is->frame_timer = (double)av_gettime() / 1000000.0; is->frame_last_delay = 40e-3; is->video_current_pts_time = av_gettime(); packet_queue_init(&is->videoq); is->video_tid = malloc(sizeof(*(is->video_tid))); // uncomment for video pthread_create(is->video_tid, NULL, (void *) &video_thread, is); is->sws_ctx = sws_getContext ( is->video_st->codec->width, is->video_st->codec->height, is->video_st->codec->pix_fmt, is->video_st->codec->width, is->video_st->codec->height, AV_PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL ); /*is->sws_ctx = sws_getContext ( is->video_st->codec->width, is->video_st->codec->height, is->video_st->codec->pix_fmt, //pCodecCtx->width, //pCodecCtx->height, is->video_st->codec->width, is->video_st->codec->height, TARGET_IMAGE_FORMAT, SWS_BILINEAR, NULL, NULL, NULL );*/ codecCtx->get_buffer2 = our_get_buffer; break; default: break; } return 0; }
static int startffmpeg(struct anim *anim) { int i, videoStream; AVCodec *pCodec; AVFormatContext *pFormatCtx = NULL; AVCodecContext *pCodecCtx; AVRational frame_rate; int frs_num; double frs_den; int streamcount; #ifdef FFMPEG_SWSCALE_COLOR_SPACE_SUPPORT /* The following for color space determination */ int srcRange, dstRange, brightness, contrast, saturation; int *table; const int *inv_table; #endif if (anim == NULL) return(-1); streamcount = anim->streamindex; if (avformat_open_input(&pFormatCtx, anim->name, NULL, NULL) != 0) { return -1; } if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { avformat_close_input(&pFormatCtx); return -1; } av_dump_format(pFormatCtx, 0, anim->name, 0); /* Find the video stream */ videoStream = -1; for (i = 0; i < pFormatCtx->nb_streams; i++) if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { if (streamcount > 0) { streamcount--; continue; } videoStream = i; break; } if (videoStream == -1) { avformat_close_input(&pFormatCtx); return -1; } pCodecCtx = pFormatCtx->streams[videoStream]->codec; /* Find the decoder for the video stream */ pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if (pCodec == NULL) { avformat_close_input(&pFormatCtx); return -1; } pCodecCtx->workaround_bugs = 1; if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { avformat_close_input(&pFormatCtx); return -1; } if (pCodecCtx->pix_fmt == AV_PIX_FMT_NONE) { avcodec_close(anim->pCodecCtx); avformat_close_input(&pFormatCtx); return -1; } frame_rate = av_get_r_frame_rate_compat(pFormatCtx, pFormatCtx->streams[videoStream]); if (pFormatCtx->streams[videoStream]->nb_frames != 0) { anim->duration = pFormatCtx->streams[videoStream]->nb_frames; } else { anim->duration = (int)(pFormatCtx->duration * av_q2d(frame_rate) / AV_TIME_BASE + 0.5f); } frs_num = frame_rate.num; frs_den = frame_rate.den; frs_den *= AV_TIME_BASE; while (frs_num % 10 == 0 && frs_den >= 2.0 && frs_num > 10) { frs_num /= 10; frs_den /= 10; } anim->frs_sec = frs_num; anim->frs_sec_base = frs_den; anim->params = 0; anim->x = pCodecCtx->width; anim->y = av_get_cropped_height_from_codec(pCodecCtx); anim->pFormatCtx = pFormatCtx; anim->pCodecCtx = pCodecCtx; anim->pCodec = pCodec; anim->videoStream = videoStream; anim->interlacing = 0; anim->orientation = 0; anim->framesize = anim->x * anim->y * 4; anim->curposition = -1; anim->last_frame = 0; anim->last_pts = -1; anim->next_pts = -1; anim->next_packet.stream_index = -1; anim->pFrame = av_frame_alloc(); anim->pFrameComplete = false; anim->pFrameDeinterlaced = av_frame_alloc(); anim->pFrameRGB = av_frame_alloc(); if (need_aligned_ffmpeg_buffer(anim)) { anim->pFrameRGB->format = AV_PIX_FMT_RGBA; anim->pFrameRGB->width = anim->x; anim->pFrameRGB->height = anim->y; if (av_frame_get_buffer(anim->pFrameRGB, 32) < 0) { fprintf(stderr, "Could not allocate frame data.\n"); avcodec_close(anim->pCodecCtx); avformat_close_input(&anim->pFormatCtx); av_frame_free(&anim->pFrameRGB); av_frame_free(&anim->pFrameDeinterlaced); av_frame_free(&anim->pFrame); anim->pCodecCtx = NULL; return -1; } } if (avpicture_get_size(AV_PIX_FMT_RGBA, anim->x, anim->y) != anim->x * anim->y * 4) { fprintf(stderr, "ffmpeg has changed alloc scheme ... ARGHHH!\n"); avcodec_close(anim->pCodecCtx); avformat_close_input(&anim->pFormatCtx); av_frame_free(&anim->pFrameRGB); av_frame_free(&anim->pFrameDeinterlaced); av_frame_free(&anim->pFrame); anim->pCodecCtx = NULL; return -1; } if (anim->ib_flags & IB_animdeinterlace) { avpicture_fill((AVPicture *) anim->pFrameDeinterlaced, MEM_callocN(avpicture_get_size( anim->pCodecCtx->pix_fmt, anim->pCodecCtx->width, anim->pCodecCtx->height), "ffmpeg deinterlace"), anim->pCodecCtx->pix_fmt, anim->pCodecCtx->width, anim->pCodecCtx->height); } if (pCodecCtx->has_b_frames) { anim->preseek = 25; /* FIXME: detect gopsize ... */ } else { anim->preseek = 0; } anim->img_convert_ctx = sws_getContext( anim->x, anim->y, anim->pCodecCtx->pix_fmt, anim->x, anim->y, AV_PIX_FMT_RGBA, SWS_FAST_BILINEAR | SWS_PRINT_INFO | SWS_FULL_CHR_H_INT, NULL, NULL, NULL); if (!anim->img_convert_ctx) { fprintf(stderr, "Can't transform color space??? Bailing out...\n"); avcodec_close(anim->pCodecCtx); avformat_close_input(&anim->pFormatCtx); av_frame_free(&anim->pFrameRGB); av_frame_free(&anim->pFrameDeinterlaced); av_frame_free(&anim->pFrame); anim->pCodecCtx = NULL; return -1; } #ifdef FFMPEG_SWSCALE_COLOR_SPACE_SUPPORT /* Try do detect if input has 0-255 YCbCR range (JFIF Jpeg MotionJpeg) */ if (!sws_getColorspaceDetails(anim->img_convert_ctx, (int **)&inv_table, &srcRange, &table, &dstRange, &brightness, &contrast, &saturation)) { srcRange = srcRange || anim->pCodecCtx->color_range == AVCOL_RANGE_JPEG; inv_table = sws_getCoefficients(anim->pCodecCtx->colorspace); if (sws_setColorspaceDetails(anim->img_convert_ctx, (int *)inv_table, srcRange, table, dstRange, brightness, contrast, saturation)) { fprintf(stderr, "Warning: Could not set libswscale colorspace details.\n"); } } else { fprintf(stderr, "Warning: Could not set libswscale colorspace details.\n"); } #endif return (0); }
bool CDVDOverlayCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) { AVCodec* pCodec = avcodec_find_decoder(hints.codec); if (!pCodec) { CLog::Log(LOGDEBUG,"%s - Unable to find codec %d", __FUNCTION__, hints.codec); return false; } m_pCodecContext = avcodec_alloc_context3(pCodec); m_pCodecContext->debug_mv = 0; m_pCodecContext->debug = 0; m_pCodecContext->workaround_bugs = FF_BUG_AUTODETECT; m_pCodecContext->codec_tag = hints.codec_tag; m_pCodecContext->time_base.num = 1; m_pCodecContext->time_base.den = DVD_TIME_BASE; m_pCodecContext->pkt_timebase.num = 1; m_pCodecContext->pkt_timebase.den = DVD_TIME_BASE; if( hints.extradata && hints.extrasize > 0 ) { m_pCodecContext->extradata_size = hints.extrasize; m_pCodecContext->extradata = (uint8_t*)av_mallocz(hints.extrasize + FF_INPUT_BUFFER_PADDING_SIZE); memcpy(m_pCodecContext->extradata, hints.extradata, hints.extrasize); // start parsing of extra data - create a copy to be safe and make it zero-terminating to avoid access violations! unsigned int parse_extrasize = hints.extrasize; char* parse_extra = new char[parse_extrasize + 1]; memcpy(parse_extra, hints.extradata, parse_extrasize); parse_extra[parse_extrasize] = '\0'; // assume that the extra data is formatted as a concatenation of lines ('\n' terminated) char *ptr = parse_extra; do // read line by line { if (!strncmp(ptr, "size:", 5)) { int width = 0, height = 0; sscanf(ptr, "size: %dx%d", &width, &height); if (width > 0 && height > 0) { m_pCodecContext->width = width; m_pCodecContext->height = height; CLog::Log(LOGDEBUG,"%s - parsed extradata: size: %d x %d", __FUNCTION__, width, height); } } /* // leaving commented code: these items don't work yet... but they may be meaningful if (!strncmp(ptr, "palette:", 8)) if (sscanf(ptr, "palette: %x, %x, %x, %x, %x, %x, %x, %x," " %x, %x, %x, %x, %x, %x, %x, %x", ... if (!strncasecmp(ptr, "forced subs: on", 15)) forced_subs_only = 1; */ // if tried all possibilities, then read newline char and move to next line ptr = strchr(ptr, '\n'); if (ptr != NULL) ptr++; } while (ptr != NULL && ptr <= parse_extra + parse_extrasize); delete[] parse_extra; } if (avcodec_open2(m_pCodecContext, pCodec, NULL) < 0) { CLog::Log(LOGDEBUG,"CDVDVideoCodecFFmpeg::Open() Unable to open codec"); return false; } return true; }
std::string get_codec_name(AVCodecContext *pCodecCtx) { AVCodecID id = pCodecCtx->codec_id; // Grab the codec const AVCodec *p = avcodec_find_decoder(id); const AVCodecDescriptor *desc = avcodec_descriptor_get(id); const char *profile = avcodec_profile_name(id, pCodecCtx->profile); std::ostringstream codec_name; const char *nice_name = nullptr; for (int i = 0; i < countof(nice_codec_names); ++i) { if (nice_codec_names[i].id == id) { nice_name = nice_codec_names[i].name; break; } } if (id == AV_CODEC_ID_DTS && pCodecCtx->codec_tag == 0xA2) { profile = "DTS Express"; } if (id == AV_CODEC_ID_H264 && profile) { codec_name << nice_name << " " << tolower(profile); if (pCodecCtx->level && pCodecCtx->level != FF_LEVEL_UNKNOWN && pCodecCtx->level < 1000) { char l_buf[5]; sprintf_s(l_buf, "%.1f", pCodecCtx->level / 10.0); codec_name << " L" << l_buf; } } else if (id == AV_CODEC_ID_VC1 && profile) { codec_name << nice_name << " " << tolower(profile); if (pCodecCtx->level != FF_LEVEL_UNKNOWN) { codec_name << " L" << pCodecCtx->level; } } else if (id == AV_CODEC_ID_DTS && profile) { codec_name << tolower(profile); } else if (id == AV_CODEC_ID_JPEG2000 && profile) { codec_name << tolower(profile); } else if (nice_name) { codec_name << nice_name; if (profile) codec_name << " " << tolower(profile); } else if (desc && desc->name) { codec_name << desc->name; if (profile) codec_name << " " << tolower(profile); } else if (p && p->name) { codec_name << p->name; if (profile) codec_name << " " << tolower(profile); } else { /* output avi tags */ char buf[32]; av_get_codec_tag_string(buf, sizeof(buf), pCodecCtx->codec_tag); codec_name << buf; sprintf_s(buf, "0x%04X", pCodecCtx->codec_tag); codec_name << " / " << buf; } return codec_name.str(); }
void Utility::VideoLoader::loadP() { isRunning_=true; target_->setIsComplete(false); // Contains information about the stream AVFormatContext *formatContext = NULL; // Contains information about the codex AVCodecContext *codecContext = NULL; // The coder with wich to decode the video AVCodec *codec = NULL; // Open video file // avformat_open_input(context, path, format, options) // format = NULL means autodetect if(!path_.isEmpty() && avformat_open_input(&formatContext, path_.toUtf8(), NULL, NULL)!=0) { target_->setIsComplete(true); return; } // Retrieve stream information if(avformat_find_stream_info(formatContext, NULL)<0) { target_->setIsComplete(true); return; } // Print stream information // av_dump_format(formatContext, 0, path_.toUtf8(), 0); // Find the best video stream in context int videoStreamIndex = av_find_best_stream(formatContext, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); if(videoStreamIndex == -1) { target_->setIsComplete(true); return; } // Get a pointer to the codec context for the video stream codecContext = formatContext->streams[videoStreamIndex]->codec; // Find the decoder for the video stream codec = avcodec_find_decoder(codecContext->codec_id); if(codec == NULL) { target_->setIsComplete(true); return; } // Open codec if(avcodec_open2(codecContext, codec, &dict_) < 0) { target_->setIsComplete(true); return; } struct SwsContext *sws_ctx = NULL; averageBitrate_=codecContext->bit_rate; codec_=QString(av_codec_get_codec_descriptor(codecContext)->name); if(codec_=="") codec_="N/A"; sws_ctx = sws_getContext ( codecContext->width, codecContext->height, codecContext->pix_fmt, codecContext->width, codecContext->height, AV_PIX_FMT_RGB24, 0, 0, 0, 0 ); AVPacket packet; AVFrame *frame = NULL; frame = av_frame_alloc(); AVFrame* rgbframe=NULL; uint8_t* buffer = NULL; int numbytes=avpicture_get_size(AV_PIX_FMT_RGB24, codecContext->width,codecContext->height); target_->setFps(codecContext->framerate.num); av_init_packet(&packet); packet.data = NULL; packet.size = 0; int gotPicture = 0; while(av_read_frame(formatContext, &packet) >= 0&&isRunning_) { avcodec_decode_video2(codecContext, frame, &gotPicture, &packet); if(gotPicture != 0) { rgbframe=av_frame_alloc(); buffer=(uint8_t *)av_malloc(numbytes*sizeof(uint8_t)); avpicture_fill((AVPicture *)rgbframe, buffer, AV_PIX_FMT_RGB24,codecContext->width, codecContext->height); rgbframe->width=codecContext->width; rgbframe->height=codecContext->height; rgbframe->format=AV_PIX_FMT_RGB24; rgbframe->pkt_size=frame->pkt_size; sws_scale ( sws_ctx, frame->data, frame->linesize, 0, codecContext->height, rgbframe->data, rgbframe->linesize ); target_->appendFrame(rgbframe); } } packet.data=NULL; packet.size=0; while(isRunning_) { avcodec_decode_video2(codecContext, frame, &gotPicture, &packet); if(gotPicture == 0) break; rgbframe=av_frame_alloc(); buffer=(uint8_t *)av_malloc(numbytes*sizeof(uint8_t)); avpicture_fill((AVPicture *)rgbframe, buffer, AV_PIX_FMT_RGB24,codecContext->width, codecContext->height); rgbframe->width=codecContext->width; rgbframe->height=codecContext->height; rgbframe->format=AV_PIX_FMT_RGB24; rgbframe->pkt_size=frame->pkt_size; sws_scale ( sws_ctx, frame->data, frame->linesize, 0, codecContext->height, rgbframe->data, rgbframe->linesize ); target_->appendFrame(rgbframe); } av_frame_unref(frame); av_frame_free(&frame); avcodec_close(codecContext); avformat_close_input(&formatContext); isRunning_=false; if(dict_) { free(dict_); } target_->setIsComplete(true); }
/* * Audio decoding. */ static void audio_decode_example(const char *outfilename, const char *filename) { AVCodec *codec; AVCodecContext *c= NULL; int len; FILE *f, *outfile; uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; AVPacket avpkt; AVFrame *decoded_frame = NULL; av_init_packet(&avpkt); printf("Audio decoding\n"); /* find the mpeg audio decoder */ codec = avcodec_find_decoder(CODEC_ID_MP2); if (!codec) { fprintf(stderr, "codec not found\n"); exit(1); } c = avcodec_alloc_context3(codec); /* open it */ if (avcodec_open2(c, codec, NULL) < 0) { fprintf(stderr, "could not open codec\n"); exit(1); } f = fopen(filename, "rb"); if (!f) { fprintf(stderr, "could not open %s\n", filename); exit(1); } outfile = fopen(outfilename, "wb"); if (!outfile) { av_free(c); exit(1); } /* decode until eof */ avpkt.data = inbuf; avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f); while (avpkt.size > 0) { int got_frame = 0; if (!decoded_frame) { if (!(decoded_frame = avcodec_alloc_frame())) { fprintf(stderr, "out of memory\n"); exit(1); } } else avcodec_get_frame_defaults(decoded_frame); len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt); if (len < 0) { fprintf(stderr, "Error while decoding\n"); exit(1); } if (got_frame) { /* if a frame has been decoded, output it */ int data_size = av_samples_get_buffer_size(NULL, c->channels, decoded_frame->nb_samples, c->sample_fmt, 1); fwrite(decoded_frame->data[0], 1, data_size, outfile); } avpkt.size -= len; avpkt.data += len; if (avpkt.size < AUDIO_REFILL_THRESH) { /* Refill the input buffer, to avoid trying to decode * incomplete frames. Instead of this, one could also use * a parser, or use a proper container format through * libavformat. */ memmove(inbuf, avpkt.data, avpkt.size); avpkt.data = inbuf; len = fread(avpkt.data + avpkt.size, 1, AUDIO_INBUF_SIZE - avpkt.size, f); if (len > 0) avpkt.size += len; } } fclose(outfile); fclose(f); avcodec_close(c); av_free(c); av_free(decoded_frame); }
int stream_component_open(VideoState *is, int stream_index) { AVFormatContext *pFormatCtx = is->pFormatCtx; AVCodecContext *codecCtx = NULL; AVCodec *codec = NULL; AVDictionary *optionsDict = NULL; SDL_AudioSpec wanted_spec, spec; if (stream_index < 0 || stream_index >= pFormatCtx->nb_streams) { return -1; } // Get a pointer to the codec context for the video stream codecCtx = pFormatCtx->streams[stream_index]->codec; if (codecCtx->codec_type == AVMEDIA_TYPE_AUDIO) { // Set audio settings from codec info wanted_spec.freq = codecCtx->sample_rate; wanted_spec.format = AUDIO_S16SYS; wanted_spec.channels = codecCtx->channels; wanted_spec.silence = 0; wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE; wanted_spec.callback = audio_callback; wanted_spec.userdata = is; if (SDL_OpenAudio(&wanted_spec, &spec) < 0) { fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError()); return -1; } is->audio_hw_buf_size = spec.size; } codec = avcodec_find_decoder(codecCtx->codec_id); if (!codec || (avcodec_open2(codecCtx, codec, &optionsDict) < 0)) { fprintf(stderr, "Unsupported codec!\n"); return -1; } switch (codecCtx->codec_type) { case AVMEDIA_TYPE_AUDIO: is->audioStream = stream_index; is->audio_st = pFormatCtx->streams[stream_index]; is->audio_buf_size = 0; is->audio_buf_index = 0; /* averaging filter for audio sync */ is->audio_diff_avg_coef = exp(log(0.01 / AUDIO_DIFF_AVG_NB)); is->audio_diff_avg_count = 0; /* Correct audio only if larger error than this */ is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / codecCtx->sample_rate; memset(&is->audio_pkt, 0, sizeof(is->audio_pkt)); packet_queue_init(&is->audioq); SDL_PauseAudio(0); break; case AVMEDIA_TYPE_VIDEO: is->videoStream = stream_index; is->video_st = pFormatCtx->streams[stream_index]; is->frame_timer = (double) av_gettime() / 1000000.0; is->frame_last_delay = 40e-3; is->video_current_pts_time = av_gettime(); packet_queue_init(&is->videoq); is->video_tid = SDL_CreateThread(video_thread, is); is->sws_ctx = sws_getContext ( is->video_st->codec->width, is->video_st->codec->height, is->video_st->codec->pix_fmt, is->video_st->codec->width, is->video_st->codec->height, PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL ); codecCtx->get_buffer2 = our_get_buffer; codecCtx->release_buffer = our_release_buffer; break; default: break; } return 0; }
int RemoteCameraRtsp::PrimeCapture() { Debug( 2, "Waiting for sources" ); for ( int i = 0; i < 100 && !rtspThread->hasSources(); i++ ) { usleep( 100000 ); } if ( !rtspThread->hasSources() ) Fatal( "No RTSP sources" ); Debug( 2, "Got sources" ); mFormatContext = rtspThread->getFormatContext(); // Find first video stream present mVideoStreamId = -1; for ( unsigned int i = 0; i < mFormatContext->nb_streams; i++ ) #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,2,1) if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO ) #else if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO ) #endif { mVideoStreamId = i; break; } if ( mVideoStreamId == -1 ) Fatal( "Unable to locate video stream" ); // Get a pointer to the codec context for the video stream mCodecContext = mFormatContext->streams[mVideoStreamId]->codec; // Find the decoder for the video stream mCodec = avcodec_find_decoder( mCodecContext->codec_id ); if ( mCodec == NULL ) Panic( "Unable to locate codec %d decoder", mCodecContext->codec_id ); // Open codec #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 7, 0) if ( avcodec_open( mCodecContext, mCodec ) < 0 ) #else if ( avcodec_open2( mCodecContext, mCodec, 0 ) < 0 ) #endif Panic( "Can't open codec" ); // Allocate space for the native video frame mRawFrame = avcodec_alloc_frame(); // Allocate space for the converted video frame mFrame = avcodec_alloc_frame(); if(mRawFrame == NULL || mFrame == NULL) Fatal( "Unable to allocate frame(s)"); int pSize = avpicture_get_size( imagePixFormat, width, height ); if( (unsigned int)pSize != imagesize) { Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize); } /* #if HAVE_LIBSWSCALE if(!sws_isSupportedInput(mCodecContext->pix_fmt)) { Fatal("swscale does not support the codec format: %c%c%c%c",(mCodecContext->pix_fmt)&0xff,((mCodecContext->pix_fmt>>8)&0xff),((mCodecContext->pix_fmt>>16)&0xff),((mCodecContext->pix_fmt>>24)&0xff)); } if(!sws_isSupportedOutput(imagePixFormat)) { Fatal("swscale does not support the target format: %c%c%c%c",(imagePixFormat)&0xff,((imagePixFormat>>8)&0xff),((imagePixFormat>>16)&0xff),((imagePixFormat>>24)&0xff)); } #else // HAVE_LIBSWSCALE Fatal( "You must compile ffmpeg with the --enable-swscale option to use RTSP cameras" ); #endif // HAVE_LIBSWSCALE */ return( 0 ); }
Libav::Libav(std::string filename, int st, int streamNumber) throw (AVException*) { pictureBuffer = NULL; pFrame = NULL; this->setIn(-1); this->setOut(-1); // default sane values this->setFrameRateNum(1); this->setFrameRateDen(1); this->setSampleAspectNum(1); this->setSampleAspectDen(1); pFormatCtx = NULL; frameCounter = 0; avStream = -1; streamType = st; lavFileName =std::string(filename); av_register_all(); if (this->openInputFile(filename) < 0) { throw new AVException("Failed to open file: " + filename, IO_ERROR); // std::cerr<<"initWithFile: avformat_open_input failed to open: "<<filename << "\n"; // how do I deal with constructor errors. } if(this->findStreamInfo()<0) { throw new AVException("Failed to find stream info", FILE_ERROR); //std::cerr<<"initWithFile: avformat_find_stream_info failed\n"; // another constructor error. } // // this->initMeta(fmt_ctx); this->initMeta(pFormatCtx); if ((avStream = this->findStream(streamNumber,streamType)) == -1) { std::stringstream exception; exception << "couldn't find requested AV stream: " << streamNumber; throw new AVException(exception.str(), FILE_ERROR); //std::cerr<<"initWithFile: couldn't find requested AV stream\n"; // constructor error blah blah } // std::cerr << "Chosen stream: " << avStream << "\n"; pCodecCtx = pFormatCtx->streams[avStream]->codec; pCodec = avcodec_find_decoder(pCodecCtx->codec_id); // this is a hack to work around the unsupported S16P if (pCodecCtx->sample_fmt == AV_SAMPLE_FMT_S16P) pCodecCtx->request_sample_fmt = AV_SAMPLE_FMT_S16; // open codec context if (this->openAVCodec() < 0) { throw new AVException("Could not find or open codec", FILE_ERROR); //std::cerr<<"initWithFile: could not find or open codec\n"; // Could not open codec } // std::cerr << filename << " pframe addr: " << pFrame << "\n"; pFrame=avcodec_alloc_frame(); // std::cerr << filename << " pframe addr: " << pFrame << "\n"; //std::cerr<<"framerate: " << pFormatCtx->streams[avStream]->r_frame_rate.num <<":" <<pFormatCtx->streams[avStream]->r_frame_rate.den << "\n"; //std::cerr<<"dar: " << pCodecCtx->sample_aspect_ratio.num <<":" <<pCodecCtx->sample_aspect_ratio.den << "\n"; this->setFrameRate(pFormatCtx->streams[avStream]->r_frame_rate); this->setSampleAspect(pCodecCtx->sample_aspect_ratio); // std::cerr<<"chroma: " << pCodecCtx->pix_fmt << "\n"; this->setChromaSampling(pCodecCtx->pix_fmt); this->setHeight(pCodecCtx->height); this->setWidth(pCodecCtx->width); this->setSampleFormat(pCodecCtx->sample_fmt); this->setSampleChannels(pCodecCtx->channels); }
static void audio_process_audio(audio_decoder_t *ad, media_buf_t *mb) { const audio_class_t *ac = ad->ad_ac; AVFrame *frame = ad->ad_frame; media_pipe_t *mp = ad->ad_mp; media_queue_t *mq = &mp->mp_audio; int r; int got_frame; AVPacket avpkt; int offset = 0; if(mb->mb_skip || mb->mb_stream != mq->mq_stream) return; while(offset < mb->mb_size) { if(mb->mb_cw == NULL) { frame->sample_rate = mb->mb_rate; frame->format = AV_SAMPLE_FMT_S16; switch(mb->mb_channels) { case 1: frame->channel_layout = AV_CH_LAYOUT_MONO; frame->nb_samples = mb->mb_size / 2; break; case 2: frame->channel_layout = AV_CH_LAYOUT_STEREO; frame->nb_samples = mb->mb_size / 4; break; default: abort(); } frame->data[0] = mb->mb_data; frame->linesize[0] = 0; r = mb->mb_size; got_frame = 1; } else { media_codec_t *mc = mb->mb_cw; AVCodecContext *ctx = mc->ctx; if(mc->codec_id != ad->ad_in_codec_id) { AVCodec *codec = avcodec_find_decoder(mc->codec_id); TRACE(TRACE_DEBUG, "audio", "Codec changed to %s", codec ? codec->name : "???"); ad->ad_in_codec_id = mc->codec_id; audio_cleanup_spdif_muxer(ad); if(ac->ac_check_passthru != NULL && codec != NULL && ac->ac_check_passthru(ad, mc->codec_id)) { audio_setup_spdif_muxer(ad, codec, mq); } } av_init_packet(&avpkt); avpkt.data = mb->mb_data + offset; avpkt.size = mb->mb_size - offset; if(ad->ad_spdif_muxer != NULL) { av_write_frame(ad->ad_spdif_muxer, &avpkt); avio_flush(ad->ad_spdif_muxer->pb); ad->ad_pts = mb->mb_pts; ad->ad_epoch = mb->mb_epoch; return; } if(ctx == NULL) { AVCodec *codec = avcodec_find_decoder(mc->codec_id); assert(codec != NULL); // Checked in libav.c ctx = mc->ctx = avcodec_alloc_context3(codec); if(ad->ad_stereo_downmix) ctx->request_channels = 2; if(avcodec_open2(mc->ctx, codec, NULL) < 0) { av_freep(&mc->ctx); return; } } r = avcodec_decode_audio4(ctx, frame, &got_frame, &avpkt); if(r < 0) return; if(frame->sample_rate == 0) { frame->sample_rate = ctx->sample_rate; if(frame->sample_rate == 0 && mb->mb_cw->fmt_ctx) frame->sample_rate = mb->mb_cw->fmt_ctx->sample_rate; if(frame->sample_rate == 0) return; } if(frame->channel_layout == 0) { switch(ctx->channels) { case 1: frame->channel_layout = AV_CH_LAYOUT_MONO; break; case 2: frame->channel_layout = AV_CH_LAYOUT_STEREO; break; default: return; } } if(mp->mp_stats) mp_set_mq_meta(mq, ctx->codec, ctx); } if(offset == 0 && mb->mb_pts != AV_NOPTS_VALUE) { int od = 0, id = 0; if(ad->ad_avr != NULL) { od = avresample_available(ad->ad_avr) * 1000000LL / ad->ad_out_sample_rate; id = avresample_get_delay(ad->ad_avr) * 1000000LL / frame->sample_rate; } ad->ad_pts = mb->mb_pts - od - id; ad->ad_epoch = mb->mb_epoch; // printf("od=%-20d id=%-20d PTS=%-20ld oPTS=%-20ld\n", // od, id, mb->mb_pts, pts); if(mb->mb_drive_clock) mp_set_current_time(mp, mb->mb_pts - ad->ad_delay, mb->mb_epoch, mb->mb_delta); } offset += r; if(got_frame) { if(frame->sample_rate != ad->ad_in_sample_rate || frame->format != ad->ad_in_sample_format || frame->channel_layout != ad->ad_in_channel_layout) { ad->ad_in_sample_rate = frame->sample_rate; ad->ad_in_sample_format = frame->format; ad->ad_in_channel_layout = frame->channel_layout; ac->ac_reconfig(ad); if(ad->ad_avr == NULL) ad->ad_avr = avresample_alloc_context(); else avresample_close(ad->ad_avr); av_opt_set_int(ad->ad_avr, "in_sample_fmt", ad->ad_in_sample_format, 0); av_opt_set_int(ad->ad_avr, "in_sample_rate", ad->ad_in_sample_rate, 0); av_opt_set_int(ad->ad_avr, "in_channel_layout", ad->ad_in_channel_layout, 0); av_opt_set_int(ad->ad_avr, "out_sample_fmt", ad->ad_out_sample_format, 0); av_opt_set_int(ad->ad_avr, "out_sample_rate", ad->ad_out_sample_rate, 0); av_opt_set_int(ad->ad_avr, "out_channel_layout", ad->ad_out_channel_layout, 0); char buf1[128]; char buf2[128]; av_get_channel_layout_string(buf1, sizeof(buf1), -1, ad->ad_in_channel_layout); av_get_channel_layout_string(buf2, sizeof(buf2), -1, ad->ad_out_channel_layout); TRACE(TRACE_DEBUG, "Audio", "Converting from [%s %dHz %s] to [%s %dHz %s]", buf1, ad->ad_in_sample_rate, av_get_sample_fmt_name(ad->ad_in_sample_format), buf2, ad->ad_out_sample_rate, av_get_sample_fmt_name(ad->ad_out_sample_format)); if(avresample_open(ad->ad_avr)) { TRACE(TRACE_ERROR, "AudioQueue", "Unable to open resampler"); avresample_free(&ad->ad_avr); } if(ac->ac_set_volume != NULL) { prop_set(mp->mp_prop_ctrl, "canAdjustVolume", PROP_SET_INT, 1); ac->ac_set_volume(ad, ad->ad_vol_scale); } } if(ad->ad_avr != NULL) avresample_convert(ad->ad_avr, NULL, 0, 0, frame->data, frame->linesize[0], frame->nb_samples); } } }
status_t AVCodecDecoder::Setup(media_format* ioEncodedFormat, const void* infoBuffer, size_t infoSize) { if (ioEncodedFormat->type != B_MEDIA_ENCODED_AUDIO && ioEncodedFormat->type != B_MEDIA_ENCODED_VIDEO) return B_ERROR; fIsAudio = (ioEncodedFormat->type == B_MEDIA_ENCODED_AUDIO); TRACE("[%c] AVCodecDecoder::Setup()\n", fIsAudio?('a'):('v')); #ifdef TRACE_AV_CODEC char buffer[1024]; string_for_format(*ioEncodedFormat, buffer, sizeof(buffer)); TRACE("[%c] input_format = %s\n", fIsAudio?('a'):('v'), buffer); TRACE("[%c] infoSize = %ld\n", fIsAudio?('a'):('v'), infoSize); TRACE("[%c] user_data_type = %08lx\n", fIsAudio?('a'):('v'), ioEncodedFormat->user_data_type); TRACE("[%c] meta_data_size = %ld\n", fIsAudio?('a'):('v'), ioEncodedFormat->MetaDataSize()); #endif media_format_description description; if (BMediaFormats().GetCodeFor(*ioEncodedFormat, B_MISC_FORMAT_FAMILY, &description) == B_OK) { if (description.u.misc.file_format != 'ffmp') return B_NOT_SUPPORTED; fCodec = avcodec_find_decoder(static_cast<CodecID>( description.u.misc.codec)); if (fCodec == NULL) { TRACE(" unable to find the correct FFmpeg " "decoder (id = %lu)\n", description.u.misc.codec); return B_ERROR; } TRACE(" found decoder %s\n", fCodec->name); const void* extraData = infoBuffer; fExtraDataSize = infoSize; if (description.family == B_WAV_FORMAT_FAMILY && infoSize >= sizeof(wave_format_ex)) { TRACE(" trying to use wave_format_ex\n"); // Special case extra data in B_WAV_FORMAT_FAMILY const wave_format_ex* waveFormatData = (const wave_format_ex*)infoBuffer; size_t waveFormatSize = infoSize; if (waveFormatData != NULL && waveFormatSize > 0) { fBlockAlign = waveFormatData->block_align; TRACE(" found block align: %d\n", fBlockAlign); fExtraDataSize = waveFormatData->extra_size; // skip the wave_format_ex from the extra data. extraData = waveFormatData + 1; } } else { if (fIsAudio) { fBlockAlign = ioEncodedFormat->u.encoded_audio.output .buffer_size; TRACE(" using buffer_size as block align: %d\n", fBlockAlign); } } if (extraData != NULL && fExtraDataSize > 0) { TRACE("AVCodecDecoder: extra data size %ld\n", infoSize); delete[] fExtraData; fExtraData = new(std::nothrow) char[fExtraDataSize]; if (fExtraData != NULL) memcpy(fExtraData, infoBuffer, fExtraDataSize); else fExtraDataSize = 0; } fInputFormat = *ioEncodedFormat; return B_OK; } else { TRACE("AVCodecDecoder: BMediaFormats().GetCodeFor() failed.\n"); } printf("AVCodecDecoder::Setup failed!\n"); return B_ERROR; }
ARCODECS_Manager_FFMPEGDecoder_t *ARCODECS_Manager_NewFFMPEGDecoder (eARCODECS_ERROR *error) { /* -- Create a new FFMPEG decoder -- */ ARCODECS_Manager_FFMPEGDecoder_t *ffmpegDecoder = NULL; eARCODECS_ERROR localError = ARCODECS_OK; ffmpegDecoder = calloc (1, sizeof(ARCODECS_Manager_FFMPEGDecoder_t)); if (ffmpegDecoder == NULL) { localError = ARCODECS_ERROR_ALLOC; } /* No else: the FFMPEG Decoder is successfully allocated and initialized to "0" */ if (localError == ARCODECS_OK) { /* register all the codecs */ avcodec_register_all(); //av_log_set_level(AV_LOG_WARNING); av_log_set_level(AV_LOG_QUIET); /* get the H264 decoder */ ffmpegDecoder->codec = avcodec_find_decoder (AV_CODEC_ID_H264); if(ffmpegDecoder->codec == NULL) { localError = ARCODECS_ERROR_MANAGER_UNSUPPORTED_CODEC; } /* No else: the codec is successfully found */ } /* No else: skipped by an error */ if(localError == ARCODECS_OK) { ffmpegDecoder->codecCtx = avcodec_alloc_context3(ffmpegDecoder->codec); if(ffmpegDecoder->codecCtx == NULL) { localError = ARCODECS_ERROR_ALLOC; } /* No else : the ffmpeg context is successfully allocated */ } /* No else: skipped by an error */ if(localError == ARCODECS_OK) { /* initialize the codec context */ ffmpegDecoder->codecCtx->pix_fmt = PIX_FMT_YUV420P; //ffmpegDecoder->codecCtx->pix_fmt = PIX_FMT_BGR24; ffmpegDecoder->codecCtx->skip_frame = AVDISCARD_DEFAULT; ffmpegDecoder->codecCtx->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK; ffmpegDecoder->codecCtx->skip_loop_filter = AVDISCARD_DEFAULT; ffmpegDecoder->codecCtx->workaround_bugs = FF_BUG_AUTODETECT; ffmpegDecoder->codecCtx->codec_type = AVMEDIA_TYPE_VIDEO; ffmpegDecoder->codecCtx->codec_id = AV_CODEC_ID_H264; ffmpegDecoder->codecCtx->skip_idct = AVDISCARD_DEFAULT; if (avcodec_open2(ffmpegDecoder->codecCtx, ffmpegDecoder->codec, NULL) < 0) { localError = ARCODECS_ERROR_MANAGER_CODEC_OPENING; } /* No else: the codec is not open ; localError is set to ARCODECS_ERROR_MANAGER_CODEC_OPENING ; stops the processing */ } /* No else: skipped by an error */ if(localError == ARCODECS_OK) { ffmpegDecoder->decodedFrame = avcodec_alloc_frame(); if (ffmpegDecoder->decodedFrame == NULL) { localError = ARCODECS_ERROR_ALLOC; } /* No else: the decodedFrame is not allocate ; localError is set to ARCODECS_ERROR_ALLOC ; stops the processing */ } /* No else: skipped by an error */ if(localError == ARCODECS_OK) { av_init_packet(&ffmpegDecoder->avpkt); } /* No else: skipped by an error */ /* return error*/ if(error != NULL) { *error = localError; } /* No else: the error is not returned */ return ffmpegDecoder; }
int dc_audio_decoder_open(AudioInputFile *audio_input_file, AudioDataConf *audio_data_conf, int mode, int no_loop) { u32 i; AVCodecContext *codec_ctx; AVCodec *codec; AVInputFormat *in_fmt = NULL; if (audio_data_conf->format && strcmp(audio_data_conf->format,"") != 0) { in_fmt = av_find_input_format(audio_data_conf->format); if (in_fmt == NULL) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Cannot find the format %s.\n", audio_data_conf->format)); return -1; } } /* * Open audio (may already be opened when shared with the video input). */ if (!audio_input_file->av_fmt_ctx) { if (avformat_open_input(&audio_input_file->av_fmt_ctx, audio_data_conf->filename, in_fmt, NULL) != 0) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Cannot open file: %s\n", audio_data_conf->filename)); return -1; } /* * Retrieve stream information */ if (avformat_find_stream_info(audio_input_file->av_fmt_ctx, NULL) < 0) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Cannot find stream information\n")); return -1; } av_dump_format(audio_input_file->av_fmt_ctx, 0, audio_data_conf->filename, 0); } /* * Find the first audio stream */ audio_input_file->astream_idx = -1; for (i=0; i<audio_input_file->av_fmt_ctx->nb_streams; i++) { if (audio_input_file->av_fmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { audio_input_file->astream_idx = i; break; } } if (audio_input_file->astream_idx == -1) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Cannot find a audio stream\n")); return -1; } /* * Get a pointer to the codec context for the audio stream */ codec_ctx = audio_input_file->av_fmt_ctx->streams[audio_input_file->astream_idx]->codec; /* * Find the decoder for the audio stream */ codec = avcodec_find_decoder(codec_ctx->codec_id); if (codec == NULL) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Input audio codec is not supported.\n")); avformat_close_input(&audio_input_file->av_fmt_ctx); return -1; } /* * Open codec */ if (avcodec_open2(codec_ctx, codec, NULL) < 0) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Cannot open input audio codec.\n")); avformat_close_input(&audio_input_file->av_fmt_ctx); return -1; } #ifdef DC_AUDIO_RESAMPLER audio_input_file->aresampler = NULL; #endif audio_input_file->fifo = av_fifo_alloc(2 * MAX_AUDIO_PACKET_SIZE); audio_data_conf->channels = codec_ctx->channels; audio_data_conf->samplerate = codec_ctx->sample_rate; audio_input_file->mode = mode; audio_input_file->no_loop = no_loop; return 0; }
int decode_audio_file(ChromaprintContext *chromaprint_ctx, int16_t *buffer1, int16_t *buffer2, const char *file_name, int max_length, int *duration) { int i, ok = 0, remaining, length, consumed, buffer_size, codec_ctx_opened = 0; AVFormatContext *format_ctx = NULL; AVCodecContext *codec_ctx = NULL; AVCodec *codec = NULL; AVStream *stream = NULL; AVPacket packet, packet_temp; #ifdef HAVE_AV_AUDIO_CONVERT AVAudioConvert *convert_ctx = NULL; #endif int16_t *buffer; #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 2, 0) if (av_open_input_file(&format_ctx, file_name, NULL, 0, NULL) != 0) { #else if (avformat_open_input(&format_ctx, file_name, NULL, NULL) != 0) { #endif fprintf(stderr, "ERROR: couldn't open the file\n"); goto done; } if (av_find_stream_info(format_ctx) < 0) { fprintf(stderr, "ERROR: couldn't find stream information in the file\n"); goto done; } for (i = 0; i < format_ctx->nb_streams; i++) { codec_ctx = format_ctx->streams[i]->codec; if (codec_ctx && codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) { stream = format_ctx->streams[i]; break; } } if (!stream) { fprintf(stderr, "ERROR: couldn't find any audio stream in the file\n"); goto done; } codec = avcodec_find_decoder(codec_ctx->codec_id); if (!codec) { fprintf(stderr, "ERROR: unknown codec\n"); goto done; } if (avcodec_open(codec_ctx, codec) < 0) { fprintf(stderr, "ERROR: couldn't open the codec\n"); goto done; } codec_ctx_opened = 1; if (codec_ctx->channels <= 0) { fprintf(stderr, "ERROR: no channels found in the audio stream\n"); goto done; } if (codec_ctx->sample_fmt != AV_SAMPLE_FMT_S16) { #ifdef HAVE_AV_AUDIO_CONVERT convert_ctx = av_audio_convert_alloc(AV_SAMPLE_FMT_S16, codec_ctx->channels, codec_ctx->sample_fmt, codec_ctx->channels, NULL, 0); if (!convert_ctx) { fprintf(stderr, "ERROR: couldn't create sample format converter\n"); goto done; } #else fprintf(stderr, "ERROR: unsupported sample format\n"); goto done; #endif } *duration = stream->time_base.num * stream->duration / stream->time_base.den; if (max_length == 0) { max_length = duration; } av_init_packet(&packet); av_init_packet(&packet_temp); remaining = max_length * codec_ctx->channels * codec_ctx->sample_rate; chromaprint_start(chromaprint_ctx, codec_ctx->sample_rate, codec_ctx->channels); while (1) { if (av_read_frame(format_ctx, &packet) < 0) { break; } packet_temp.data = packet.data; packet_temp.size = packet.size; while (packet_temp.size > 0) { buffer_size = BUFFER_SIZE; #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52, 23, 0) consumed = avcodec_decode_audio2(codec_ctx, buffer1, &buffer_size, packet_temp.data, packet_temp.size); #else consumed = avcodec_decode_audio3(codec_ctx, buffer1, &buffer_size, &packet_temp); #endif if (consumed < 0) { break; } packet_temp.data += consumed; packet_temp.size -= consumed; if (buffer_size <= 0) { if (buffer_size < 0) { fprintf(stderr, "WARNING: size returned from avcodec_decode_audioX is too small\n"); } continue; } if (buffer_size > BUFFER_SIZE) { fprintf(stderr, "WARNING: size returned from avcodec_decode_audioX is too large\n"); continue; } #ifdef HAVE_AV_AUDIO_CONVERT if (convert_ctx) { const void *ibuf[6] = { buffer1 }; void *obuf[6] = { buffer2 }; #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 8, 0) int istride[6] = { av_get_bits_per_sample_format(codec_ctx->sample_fmt) / 8 }; #else int istride[6] = { av_get_bytes_per_sample(codec_ctx->sample_fmt) }; #endif int ostride[6] = { 2 }; int len = buffer_size / istride[0]; if (av_audio_convert(convert_ctx, obuf, ostride, ibuf, istride, len) < 0) { break; } buffer = buffer2; buffer_size = len * ostride[0]; } else { buffer = buffer1; } #else buffer = buffer1; #endif length = MIN(remaining, buffer_size / 2); if (!chromaprint_feed(chromaprint_ctx, buffer, length)) { fprintf(stderr, "ERROR: fingerprint calculation failed\n"); goto done; } if (max_length) { remaining -= length; if (remaining <= 0) { goto finish; } } } if (packet.data) { av_free_packet(&packet); } } finish: if (!chromaprint_finish(chromaprint_ctx)) { fprintf(stderr, "ERROR: fingerprint calculation failed\n"); goto done; } ok = 1; done: if (codec_ctx_opened) { avcodec_close(codec_ctx); } if (format_ctx) { av_close_input_file(format_ctx); } #ifdef HAVE_AV_AUDIO_CONVERT if (convert_ctx) { av_audio_convert_free(convert_ctx); } #endif return ok; } int fpcalc_main(int argc, char **argv) { int i, j, max_length = 120, num_file_names = 0, raw = 0, raw_fingerprint_size, duration; int16_t *buffer1, *buffer2; int32_t *raw_fingerprint; char *file_name, *fingerprint, **file_names; ChromaprintContext *chromaprint_ctx; int algo = CHROMAPRINT_ALGORITHM_DEFAULT; file_names = malloc(argc * sizeof(char *)); for (i = 1; i < argc; i++) { char *arg = argv[i]; if (!strcmp(arg, "-length") && i + 1 < argc) { max_length = atoi(argv[++i]); } else if (!strcmp(arg, "-version") || !strcmp(arg, "-v")) { printf("fpcalc version %s\n", chromaprint_get_version()); return 0; } else if (!strcmp(arg, "-raw")) { raw = 1; } else if (!strcmp(arg, "-algo") && i + 1 < argc) { const char *v = argv[++i]; if (!strcmp(v, "test1")) { algo = CHROMAPRINT_ALGORITHM_TEST1; } else if (!strcmp(v, "test2")) { algo = CHROMAPRINT_ALGORITHM_TEST2; } else if (!strcmp(v, "test3")) { algo = CHROMAPRINT_ALGORITHM_TEST3; } else if (!strcmp(v, "test4")) { algo = CHROMAPRINT_ALGORITHM_TEST4; } else { fprintf(stderr, "WARNING: unknown algorithm, using the default\n"); } } else if (!strcmp(arg, "-set") && i + 1 < argc) { char *name = argv[++i]; char *value = strchr(name, '='); if (!value && i + 1 < argc) { ++i; } } else { file_names[num_file_names++] = argv[i]; } } if (!num_file_names) { printf("usage: %s [OPTIONS] FILE...\n\n", argv[0]); printf("Options:\n"); printf(" -version print version information\n"); printf(" -length SECS length of the audio data used for fingerprint calculation (default 120)\n"); printf(" -raw output the raw uncompressed fingerprint\n"); printf(" -algo NAME version of the fingerprint algorithm\n"); return 2; } av_register_all(); av_log_set_level(AV_LOG_ERROR); buffer1 = av_malloc(BUFFER_SIZE + 16); buffer2 = av_malloc(BUFFER_SIZE + 16); chromaprint_ctx = chromaprint_new(algo); for (i = 1; i < argc; i++) { char *arg = argv[i]; if (!strcmp(arg, "-set") && i + 1 < argc) { char *name = argv[++i]; char *value = strchr(name, '='); if (value) { *value++ = '\0'; chromaprint_set_option(chromaprint_ctx, name, atoi(value)); } else if (i + 1 < argc) { value = argv[++i]; chromaprint_set_option(chromaprint_ctx, name, atoi(value)); } } } for (i = 0; i < num_file_names; i++) { file_name = file_names[i]; if (!decode_audio_file(chromaprint_ctx, buffer1, buffer2, file_name, max_length, &duration)) { fprintf(stderr, "ERROR: unable to calculate fingerprint for file %s, skipping\n", file_name); continue; } if (i > 0) { printf("\n"); } printf("FILE=%s\n", file_name); printf("DURATION=%d\n", duration); if (raw) { if (!chromaprint_get_raw_fingerprint(chromaprint_ctx, (void **)&raw_fingerprint, &raw_fingerprint_size)) { fprintf(stderr, "ERROR: unable to calculate fingerprint for file %s, skipping\n", file_name); continue; } printf("FINGERPRINT="); for (j = 0; j < raw_fingerprint_size; j++) { printf("%d%s", raw_fingerprint[j], j + 1 < raw_fingerprint_size ? "," : ""); } printf("\n"); chromaprint_dealloc(raw_fingerprint); } else { if (!chromaprint_get_fingerprint(chromaprint_ctx, &fingerprint)) { fprintf(stderr, "ERROR: unable to calculate fingerprint for file %s, skipping\n", file_name); continue; } printf("FINGERPRINT=%s\n", fingerprint); chromaprint_dealloc(fingerprint); } } chromaprint_free(chromaprint_ctx); av_free(buffer1); av_free(buffer2); free(file_names); return 0; }
AudioDecoder(s32 type, u32 addr, u32 size, vm::ptr<CellAdecCbMsg> func, u32 arg) : ppu_thread("HLE Audio Decoder") , type(type) , memAddr(addr) , memSize(size) , memBias(0) , cbFunc(func) , cbArg(arg) , is_closed(false) , is_finished(false) , just_started(false) , just_finished(false) , codec(nullptr) , input_format(nullptr) , ctx(nullptr) , fmt(nullptr) { av_register_all(); avcodec_register_all(); switch (type) { case CELL_ADEC_TYPE_ATRACX: case CELL_ADEC_TYPE_ATRACX_2CH: case CELL_ADEC_TYPE_ATRACX_6CH: case CELL_ADEC_TYPE_ATRACX_8CH: { codec = avcodec_find_decoder(AV_CODEC_ID_ATRAC3P); input_format = av_find_input_format("oma"); break; } case CELL_ADEC_TYPE_MP3: { codec = avcodec_find_decoder(AV_CODEC_ID_MP3); input_format = av_find_input_format("mp3"); break; } default: { fmt::throw_exception("Unknown type (0x%x)" HERE, type); } } if (!codec) { fmt::throw_exception("avcodec_find_decoder() failed" HERE); } if (!input_format) { fmt::throw_exception("av_find_input_format() failed" HERE); } fmt = avformat_alloc_context(); if (!fmt) { fmt::throw_exception("avformat_alloc_context() failed" HERE); } io_buf = (u8*)av_malloc(4096); fmt->pb = avio_alloc_context(io_buf, 256, 0, this, adecRead, NULL, NULL); if (!fmt->pb) { fmt::throw_exception("avio_alloc_context() failed" HERE); } }
bool CFfmpegDec::SetMetaData(FILE *_in, CAudioMetaData* m, bool save_cover) { if (!meta_data_valid) { if (!Init(_in, (const CFile::FileType) m->type)) return false; mutex.lock(); int ret = avformat_find_stream_info(avc, NULL); if (ret < 0) { mutex.unlock(); DeInit(); printf("avformat_find_stream_info error %d\n", ret); return false; } mutex.unlock(); if (!is_stream) { GetMeta(avc->metadata); for(unsigned int i = 0; i < avc->nb_streams; i++) { if (avc->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) GetMeta(avc->streams[i]->metadata); } } //fseek((FILE *) in, 0, SEEK_SET); #ifdef FFDEC_DEBUG av_dump_format(avc, 0, "", 0); #endif codec = NULL; best_stream = av_find_best_stream(avc, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0); if (best_stream < 0) { DeInit(); return false; } if (!codec) codec = avcodec_find_decoder(avc->streams[best_stream]->codec->codec_id); samplerate = avc->streams[best_stream]->codec->sample_rate; mChannels = av_get_channel_layout_nb_channels(avc->streams[best_stream]->codec->channel_layout); std::stringstream ss; if (codec && codec->long_name != NULL) type_info = codec->long_name; else if(codec && codec->name != NULL) type_info = codec->name; else type_info = "unknown"; ss << " / " << mChannels << " channel" << ( mChannels > 1 ? "s" : ""); type_info += ss.str(); bitrate = 0; total_time = 0; if (avc->duration != int64_t(AV_NOPTS_VALUE)) total_time = avc->duration / int64_t(AV_TIME_BASE); printf("CFfmpegDec: format %s (%s) duration %ld\n", avc->iformat->name, type_info.c_str(), total_time); for(unsigned int i = 0; i < avc->nb_streams; i++) { if (avc->streams[i]->codec->bit_rate > 0) bitrate += avc->streams[i]->codec->bit_rate; if (save_cover && (avc->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC)) { mkdir(COVERDIR, 0755); std::string cover(COVERDIR); cover += "/" + to_string(cover_count++) + ".jpg"; FILE *f = fopen(cover.c_str(), "wb"); if (f) { AVPacket *pkt = &avc->streams[i]->attached_pic; fwrite(pkt->data, pkt->size, 1, f); fclose(f); m->cover = cover; m->cover_temporary = true; } } } if(!total_time && m->filesize && bitrate) total_time = 8 * m->filesize / bitrate; meta_data_valid = true; m->changed = true; } if (!is_stream) { m->title = title; m->artist = artist; m->date = date; m->album = album; m->genre = genre; m->total_time = total_time; } m->type_info = type_info; // make sure bitrate is set to prevent refresh metadata from gui, its a flag m->bitrate = bitrate ? bitrate : 1; m->samplerate = samplerate; return true; }
/** * Cycle through available formats using the specified pin, * try to set parameters specified through AVOptions and if successful * return 1 in *pformat_set. * If pformat_set is NULL, list all pin capabilities. */ static void dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, IPin *pin, int *pformat_set) { struct dshow_ctx *ctx = avctx->priv_data; IAMStreamConfig *config = NULL; AM_MEDIA_TYPE *type = NULL; int format_set = 0; void *caps = NULL; int i, n, size; if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **) &config) != S_OK) return; if (IAMStreamConfig_GetNumberOfCapabilities(config, &n, &size) != S_OK) goto end; caps = av_malloc(size); if (!caps) goto end; for (i = 0; i < n && !format_set; i++) { IAMStreamConfig_GetStreamCaps(config, i, &type, (void *) caps); #if DSHOWDEBUG ff_print_AM_MEDIA_TYPE(type); #endif if (devtype == VideoDevice) { VIDEO_STREAM_CONFIG_CAPS *vcaps = caps; BITMAPINFOHEADER *bih; int64_t *fr; #if DSHOWDEBUG ff_print_VIDEO_STREAM_CONFIG_CAPS(vcaps); #endif if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo)) { VIDEOINFOHEADER *v = (void *) type->pbFormat; fr = &v->AvgTimePerFrame; bih = &v->bmiHeader; } else if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo2)) { VIDEOINFOHEADER2 *v = (void *) type->pbFormat; fr = &v->AvgTimePerFrame; bih = &v->bmiHeader; } else { goto next; } if (!pformat_set) { enum AVPixelFormat pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount); if (pix_fmt == AV_PIX_FMT_NONE) { enum AVCodecID codec_id = dshow_codecid(bih->biCompression); AVCodec *codec = avcodec_find_decoder(codec_id); if (codec_id == AV_CODEC_ID_NONE || !codec) { av_log(avctx, AV_LOG_INFO, " unknown compression type 0x%X", (int) bih->biCompression); } else { av_log(avctx, AV_LOG_INFO, " vcodec=%s", codec->name); } } else { av_log(avctx, AV_LOG_INFO, " pixel_format=%s", av_get_pix_fmt_name(pix_fmt)); } av_log(avctx, AV_LOG_INFO, " min s=%ldx%ld fps=%g max s=%ldx%ld fps=%g\n", vcaps->MinOutputSize.cx, vcaps->MinOutputSize.cy, 1e7 / vcaps->MaxFrameInterval, vcaps->MaxOutputSize.cx, vcaps->MaxOutputSize.cy, 1e7 / vcaps->MinFrameInterval); continue; } if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) { if (ctx->video_codec_id != dshow_codecid(bih->biCompression)) goto next; } if (ctx->pixel_format != AV_PIX_FMT_NONE && ctx->pixel_format != dshow_pixfmt(bih->biCompression, bih->biBitCount)) { goto next; } if (ctx->framerate) { int64_t framerate = ((int64_t) ctx->requested_framerate.den*10000000) / ctx->requested_framerate.num; if (framerate > vcaps->MaxFrameInterval || framerate < vcaps->MinFrameInterval) goto next; *fr = framerate; } if (ctx->requested_width && ctx->requested_height) { if (ctx->requested_width > vcaps->MaxOutputSize.cx || ctx->requested_width < vcaps->MinOutputSize.cx || ctx->requested_height > vcaps->MaxOutputSize.cy || ctx->requested_height < vcaps->MinOutputSize.cy) goto next; bih->biWidth = ctx->requested_width; bih->biHeight = ctx->requested_height; } } else { AUDIO_STREAM_CONFIG_CAPS *acaps = caps; WAVEFORMATEX *fx; #if DSHOWDEBUG ff_print_AUDIO_STREAM_CONFIG_CAPS(acaps); #endif if (IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx)) { fx = (void *) type->pbFormat; } else { goto next; } if (!pformat_set) { av_log(avctx, AV_LOG_INFO, " min ch=%lu bits=%lu rate=%6lu max ch=%lu bits=%lu rate=%6lu\n", acaps->MinimumChannels, acaps->MinimumBitsPerSample, acaps->MinimumSampleFrequency, acaps->MaximumChannels, acaps->MaximumBitsPerSample, acaps->MaximumSampleFrequency); continue; } if (ctx->sample_rate) { if (ctx->sample_rate > acaps->MaximumSampleFrequency || ctx->sample_rate < acaps->MinimumSampleFrequency) goto next; fx->nSamplesPerSec = ctx->sample_rate; } if (ctx->sample_size) { if (ctx->sample_size > acaps->MaximumBitsPerSample || ctx->sample_size < acaps->MinimumBitsPerSample) goto next; fx->wBitsPerSample = ctx->sample_size; } if (ctx->channels) { if (ctx->channels > acaps->MaximumChannels || ctx->channels < acaps->MinimumChannels) goto next; fx->nChannels = ctx->channels; } } if (IAMStreamConfig_SetFormat(config, type) != S_OK) goto next; format_set = 1; next: if (type->pbFormat) CoTaskMemFree(type->pbFormat); CoTaskMemFree(type); } end: IAMStreamConfig_Release(config); if (caps) av_free(caps); if (pformat_set) *pformat_set = format_set; }
u32 adecOpen(AudioDecoder* data) { AudioDecoder& adec = *data; adec.adecCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU); u32 adec_id = cellAdec.GetNewId(data); adec.id = adec_id; adec.adecCb->SetName("Audio Decoder[" + std::to_string(adec_id) + "] Callback"); thread t("Audio Decoder[" + std::to_string(adec_id) + "] Thread", [&]() { ConLog.Write("Audio Decoder enter()"); AdecTask& task = adec.task; while (true) { if (Emu.IsStopped()) { break; } if (adec.job.IsEmpty() && adec.is_running) { Sleep(1); continue; } /*if (adec.frames.GetCount() >= 50) { Sleep(1); continue; }*/ if (!adec.job.Pop(task)) { break; } switch (task.type) { case adecStartSeq: { // TODO: reset data ConLog.Warning("adecStartSeq:"); adec.reader.addr = 0; adec.reader.size = 0; adec.reader.init = false; if (adec.reader.rem) free(adec.reader.rem); adec.reader.rem = nullptr; adec.reader.rem_size = 0; adec.is_running = true; adec.just_started = true; } break; case adecEndSeq: { // TODO: finalize ConLog.Warning("adecEndSeq:"); /*Callback cb; cb.SetAddr(adec.cbFunc); cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg); cb.Branch(true); // ???*/ adec.adecCb->ExecAsCallback(adec.cbFunc, true, adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg); avcodec_close(adec.ctx); avformat_close_input(&adec.fmt); adec.is_running = false; } break; case adecDecodeAu: { int err = 0; adec.reader.addr = task.au.addr; adec.reader.size = task.au.size; //ConLog.Write("Audio AU: size = 0x%x, pts = 0x%llx", task.au.size, task.au.pts); if (adec.just_started) { adec.first_pts = task.au.pts; adec.last_pts = task.au.pts - 0x10000; // hack } struct AVPacketHolder : AVPacket { AVPacketHolder(u32 size) { av_init_packet(this); if (size) { data = (u8*)av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); this->size = size + FF_INPUT_BUFFER_PADDING_SIZE; } else { data = NULL; size = 0; } } ~AVPacketHolder() { av_free(data); //av_free_packet(this); } } au(0); /*{ wxFile dump; dump.Open(wxString::Format("audio pts-0x%llx.dump", task.au.pts), wxFile::write); u8* buf = (u8*)malloc(task.au.size); if (Memory.CopyToReal(buf, task.au.addr, task.au.size)) dump.Write(buf, task.au.size); free(buf); dump.Close(); }*/ if (adec.just_started) // deferred initialization { err = avformat_open_input(&adec.fmt, NULL, av_find_input_format("oma"), NULL); if (err) { ConLog.Error("adecDecodeAu: avformat_open_input() failed"); Emu.Pause(); break; } AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_ATRAC3P); // ??? if (!codec) { ConLog.Error("adecDecodeAu: avcodec_find_decoder() failed"); Emu.Pause(); break; } /*err = avformat_find_stream_info(adec.fmt, NULL); if (err) { ConLog.Error("adecDecodeAu: avformat_find_stream_info() failed"); Emu.Pause(); break; } if (!adec.fmt->nb_streams) { ConLog.Error("adecDecodeAu: no stream found"); Emu.Pause(); break; }*/ if (!avformat_new_stream(adec.fmt, codec)) { ConLog.Error("adecDecodeAu: avformat_new_stream() failed"); Emu.Pause(); break; } adec.ctx = adec.fmt->streams[0]->codec; // TODO: check data AVDictionary* opts = nullptr; av_dict_set(&opts, "refcounted_frames", "1", 0); { SMutexGeneralLocker lock(g_mutex_avcodec_open2); // not multithread-safe err = avcodec_open2(adec.ctx, codec, &opts); } if (err) { ConLog.Error("adecDecodeAu: avcodec_open2() failed"); Emu.Pause(); break; } adec.just_started = false; } bool last_frame = false; while (true) { if (Emu.IsStopped()) { ConLog.Warning("adecDecodeAu aborted"); return; } /*if (!adec.ctx) // fake { AdecFrame frame; frame.pts = task.au.pts; frame.auAddr = task.au.addr; frame.auSize = task.au.size; frame.userdata = task.au.userdata; frame.size = 4096; frame.data = nullptr; adec.frames.Push(frame); adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); break; }*/ last_frame = av_read_frame(adec.fmt, &au) < 0; if (last_frame) { //break; av_free(au.data); au.data = NULL; au.size = 0; } struct AdecFrameHolder : AdecFrame { AdecFrameHolder() { data = av_frame_alloc(); } ~AdecFrameHolder() { if (data) { av_frame_unref(data); av_frame_free(&data); } } } frame; if (!frame.data) { ConLog.Error("adecDecodeAu: av_frame_alloc() failed"); Emu.Pause(); break; } int got_frame = 0; int decode = avcodec_decode_audio4(adec.ctx, frame.data, &got_frame, &au); if (decode <= 0) { if (!last_frame && decode < 0) { ConLog.Error("adecDecodeAu: AU decoding error(0x%x)", decode); } if (!got_frame && adec.reader.size == 0) break; } if (got_frame) { u64 ts = av_frame_get_best_effort_timestamp(frame.data); if (ts != AV_NOPTS_VALUE) { frame.pts = ts/* - adec.first_pts*/; adec.last_pts = frame.pts; } else { adec.last_pts += ((u64)frame.data->nb_samples) * 90000 / 48000; frame.pts = adec.last_pts; } //frame.pts = adec.last_pts; //adec.last_pts += ((u64)frame.data->nb_samples) * 90000 / 48000; // ??? frame.auAddr = task.au.addr; frame.auSize = task.au.size; frame.userdata = task.au.userdata; frame.size = frame.data->nb_samples * frame.data->channels * sizeof(float); if (frame.data->format != AV_SAMPLE_FMT_FLTP) { ConLog.Error("adecDecodeaAu: unsupported frame format(%d)", frame.data->format); Emu.Pause(); break; } if (frame.data->channels != 2) { ConLog.Error("adecDecodeAu: unsupported channel count (%d)", frame.data->channels); Emu.Pause(); break; } //ConLog.Write("got audio frame (pts=0x%llx, nb_samples=%d, ch=%d, sample_rate=%d, nbps=%d)", //frame.pts, frame.data->nb_samples, frame.data->channels, frame.data->sample_rate, //av_get_bytes_per_sample((AVSampleFormat)frame.data->format)); adec.frames.Push(frame); frame.data = nullptr; // to prevent destruction /*Callback cb; cb.SetAddr(adec.cbFunc); cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); cb.Branch(false);*/ adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); } } /*Callback cb; cb.SetAddr(adec.cbFunc); cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, adec.cbArg); cb.Branch(false);*/ adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, adec.cbArg); } break; case adecClose: { adec.is_finished = true; ConLog.Write("Audio Decoder exit"); return; } default: ConLog.Error("Audio Decoder error: unknown task(%d)", task.type); } } adec.is_finished = true; ConLog.Warning("Audio Decoder aborted"); }); t.detach(); return adec_id; }
bool CDVDDemuxClient::ParsePacket(DemuxPacket* pkt) { bool change = false; CDemuxStream* st = GetStream(pkt->iStreamId); if (st == nullptr) return change; if (st->ExtraSize) return change; CDemuxStreamClientInternal* stream = dynamic_cast<CDemuxStreamClientInternal*>(st); if (stream == nullptr || stream->m_parser == nullptr) return change; if (stream->m_context == nullptr) { AVCodec *codec = avcodec_find_decoder(st->codec); if (codec == nullptr) { CLog::Log(LOGERROR, "%s - can't find decoder", __FUNCTION__); stream->DisposeParser(); return change; } stream->m_context = avcodec_alloc_context3(codec); if (stream->m_context == nullptr) { CLog::Log(LOGERROR, "%s - can't allocate context", __FUNCTION__); stream->DisposeParser(); return change; } stream->m_context->time_base.num = 1; stream->m_context->time_base.den = DVD_TIME_BASE; } if (stream->m_parser_split && stream->m_parser->parser->split) { int len = stream->m_parser->parser->split(stream->m_context, pkt->pData, pkt->iSize); if (len > 0 && len < FF_MAX_EXTRADATA_SIZE) { if (st->ExtraData) delete[] (uint8_t*)st->ExtraData; st->changes++; st->disabled = false; st->ExtraSize = len; st->ExtraData = new uint8_t[len+AV_INPUT_BUFFER_PADDING_SIZE]; memcpy(st->ExtraData, pkt->pData, len); memset((uint8_t*)st->ExtraData + len, 0 , AV_INPUT_BUFFER_PADDING_SIZE); stream->m_parser_split = false; change = true; CLog::Log(LOGDEBUG, "CDVDDemuxClient::ParsePacket - split extradata"); } } uint8_t *outbuf = nullptr; int outbuf_size = 0; int len = av_parser_parse2(stream->m_parser, stream->m_context, &outbuf, &outbuf_size, pkt->pData, pkt->iSize, (int64_t)(pkt->pts * DVD_TIME_BASE), (int64_t)(pkt->dts * DVD_TIME_BASE), 0); // our parse is setup to parse complete frames, so we don't care about outbufs if (len >= 0) { if (stream->m_context->profile != st->profile && stream->m_context->profile != FF_PROFILE_UNKNOWN) { CLog::Log(LOGDEBUG, "CDVDDemuxClient::ParsePacket - {%d} profile changed from %d to %d", st->uniqueId, st->profile, stream->m_context->profile); st->profile = stream->m_context->profile; st->changes++; st->disabled = false; } if (stream->m_context->level != st->level && stream->m_context->level != FF_LEVEL_UNKNOWN) { CLog::Log(LOGDEBUG, "CDVDDemuxClient::ParsePacket - {%d} level changed from %d to %d", st->uniqueId, st->level, stream->m_context->level); st->level = stream->m_context->level; st->changes++; st->disabled = false; } switch (st->type) { case STREAM_AUDIO: { CDemuxStreamClientInternalTpl<CDemuxStreamAudio>* sta = static_cast<CDemuxStreamClientInternalTpl<CDemuxStreamAudio>*>(st); if (stream->m_context->channels != sta->iChannels && stream->m_context->channels != 0) { CLog::Log(LOGDEBUG, "CDVDDemuxClient::ParsePacket - {%d} channels changed from %d to %d", st->uniqueId, sta->iChannels, stream->m_context->channels); sta->iChannels = stream->m_context->channels; sta->changes++; sta->disabled = false; } if (stream->m_context->sample_rate != sta->iSampleRate && stream->m_context->sample_rate != 0) { CLog::Log(LOGDEBUG, "CDVDDemuxClient::ParsePacket - {%d} samplerate changed from %d to %d", st->uniqueId, sta->iSampleRate, stream->m_context->sample_rate); sta->iSampleRate = stream->m_context->sample_rate; sta->changes++; sta->disabled = false; } break; } case STREAM_VIDEO: { CDemuxStreamClientInternalTpl<CDemuxStreamVideo>* stv = static_cast<CDemuxStreamClientInternalTpl<CDemuxStreamVideo>*>(st); if (stream->m_context->width != stv->iWidth && stream->m_context->width != 0) { CLog::Log(LOGDEBUG, "CDVDDemuxClient::ParsePacket - {%d} width changed from %d to %d", st->uniqueId, stv->iWidth, stream->m_context->width); stv->iWidth = stream->m_context->width; stv->changes++; stv->disabled = false; } if (stream->m_context->height != stv->iHeight && stream->m_context->height != 0) { CLog::Log(LOGDEBUG, "CDVDDemuxClient::ParsePacket - {%d} height changed from %d to %d", st->uniqueId, stv->iHeight, stream->m_context->height); stv->iHeight = stream->m_context->height; stv->changes++; stv->disabled = false; } break; } default: break; } } else CLog::Log(LOGDEBUG, "%s - parser returned error %d", __FUNCTION__, len); return change; }
static void video_decode_example(const char *outfilename, const char *filename) { AVCodec *codec; AVCodecContext *c= NULL; int frame, got_picture, len; FILE *f; AVFrame *picture; uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; char buf[1024]; AVPacket avpkt; av_init_packet(&avpkt); /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */ memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE); printf("Video decoding\n"); /* find the mpeg1 video decoder */ codec = avcodec_find_decoder(CODEC_ID_MPEG1VIDEO); if (!codec) { fprintf(stderr, "codec not found\n"); exit(1); } c = avcodec_alloc_context3(codec); picture= avcodec_alloc_frame(); if(codec->capabilities&CODEC_CAP_TRUNCATED) c->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */ /* For some codecs, such as msmpeg4 and mpeg4, width and height MUST be initialized there because this information is not available in the bitstream. */ /* open it */ if (avcodec_open2(c, codec, NULL) < 0) { fprintf(stderr, "could not open codec\n"); exit(1); } /* the codec gives us the frame size, in samples */ f = fopen(filename, "rb"); if (!f) { fprintf(stderr, "could not open %s\n", filename); exit(1); } frame = 0; for(;;) { avpkt.size = fread(inbuf, 1, INBUF_SIZE, f); if (avpkt.size == 0) break; /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio) and this is the only method to use them because you cannot know the compressed data size before analysing it. BUT some other codecs (msmpeg4, mpeg4) are inherently frame based, so you must call them with all the data for one frame exactly. You must also initialize 'width' and 'height' before initializing them. */ /* NOTE2: some codecs allow the raw parameters (frame size, sample rate) to be changed at any frame. We handle this, so you should also take care of it */ /* here, we use a stream based decoder (mpeg1video), so we feed decoder and see if it could decode a frame */ avpkt.data = inbuf; while (avpkt.size > 0) { len = avcodec_decode_video2(c, picture, &got_picture, &avpkt); if (len < 0) { fprintf(stderr, "Error while decoding frame %d\n", frame); exit(1); } if (got_picture) { printf("saving frame %3d\n", frame); fflush(stdout); /* the picture is allocated by the decoder. no need to free it */ snprintf(buf, sizeof(buf), outfilename, frame); pgm_save(picture->data[0], picture->linesize[0], c->width, c->height, buf); frame++; } avpkt.size -= len; avpkt.data += len; } } /* some codecs, such as MPEG, transmit the I and P frame with a latency of one frame. You must do the following to have a chance to get the last frame of the video */ avpkt.data = NULL; avpkt.size = 0; len = avcodec_decode_video2(c, picture, &got_picture, &avpkt); if (got_picture) { printf("saving last frame %3d\n", frame); fflush(stdout); /* the picture is allocated by the decoder. no need to free it */ snprintf(buf, sizeof(buf), outfilename, frame); pgm_save(picture->data[0], picture->linesize[0], c->width, c->height, buf); frame++; } fclose(f); avcodec_close(c); av_free(c); av_free(picture); printf("\n"); }
int FFmpeg_Input::Open( const char *filepath ) { int error; /** Open the input file to read from it. */ if ( (error = avformat_open_input( &input_format_context, filepath, NULL, NULL)) < 0 ) { Error("Could not open input file '%s' (error '%s')\n", filepath, av_make_error_string(error).c_str() ); input_format_context = NULL; return error; } /** Get information on the input file (number of streams etc.). */ if ( (error = avformat_find_stream_info(input_format_context, NULL)) < 0 ) { Error( "Could not open find stream info (error '%s')\n", av_make_error_string(error).c_str() ); avformat_close_input(&input_format_context); return error; } streams = new stream[input_format_context->nb_streams]; for ( unsigned int i = 0; i < input_format_context->nb_streams; i += 1 ) { if ( is_video_stream( input_format_context->streams[i] ) ) { zm_dump_stream_format(input_format_context, i, 0, 0); if ( video_stream_id == -1 ) { video_stream_id = i; // if we break, then we won't find the audio stream } else { Warning( "Have another video stream." ); } } else if ( is_audio_stream( input_format_context->streams[i] ) ) { if ( audio_stream_id == -1 ) { audio_stream_id = i; } else { Warning( "Have another audio stream." ); } } streams[i].frame_count = 0; #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) streams[i].context = avcodec_alloc_context3( NULL ); avcodec_parameters_to_context( streams[i].context, input_format_context->streams[i]->codecpar ); #else streams[i].context = input_format_context->streams[i]->codec; #endif if ( !(streams[i].codec = avcodec_find_decoder(streams[i].context->codec_id)) ) { Error( "Could not find input codec\n"); avformat_close_input(&input_format_context); return AVERROR_EXIT; } else { Debug(1, "Using codec (%s) for stream %d", streams[i].codec->name, i ); } if ((error = avcodec_open2( streams[i].context, streams[i].codec, NULL)) < 0) { Error( "Could not open input codec (error '%s')\n", av_make_error_string(error).c_str() ); #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) avcodec_free_context( &streams[i].context ); #endif avformat_close_input(&input_format_context); return error; } } // end foreach stream if ( video_stream_id == -1 ) Error( "Unable to locate video stream in %s", filepath ); if ( audio_stream_id == -1 ) Debug( 3, "Unable to locate audio stream in %s", filepath ); return 0; } // end int FFmpeg_Input::Open( const char * filepath )
static int isffmpeg (const char *filename) { AVFormatContext *pFormatCtx; unsigned int i; int videoStream; AVCodec *pCodec; AVCodecContext *pCodecCtx; do_init_ffmpeg(); if( BLI_testextensie(filename, ".swf") || BLI_testextensie(filename, ".jpg") || BLI_testextensie(filename, ".png") || BLI_testextensie(filename, ".dds") || BLI_testextensie(filename, ".tga") || BLI_testextensie(filename, ".bmp") || BLI_testextensie(filename, ".exr") || BLI_testextensie(filename, ".cin") || BLI_testextensie(filename, ".wav")) return 0; if(av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL)!=0) { if(UTIL_DEBUG) fprintf(stderr, "isffmpeg: av_open_input_file failed\n"); return 0; } if(av_find_stream_info(pFormatCtx)<0) { if(UTIL_DEBUG) fprintf(stderr, "isffmpeg: av_find_stream_info failed\n"); av_close_input_file(pFormatCtx); return 0; } if(UTIL_DEBUG) av_dump_format(pFormatCtx, 0, filename, 0); /* Find the first video stream */ videoStream=-1; for(i=0; i<pFormatCtx->nb_streams; i++) if(pFormatCtx->streams[i] && pFormatCtx->streams[i]->codec && (pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)) { videoStream=i; break; } if(videoStream==-1) { av_close_input_file(pFormatCtx); return 0; } pCodecCtx = pFormatCtx->streams[videoStream]->codec; /* Find the decoder for the video stream */ pCodec=avcodec_find_decoder(pCodecCtx->codec_id); if(pCodec==NULL) { av_close_input_file(pFormatCtx); return 0; } if(avcodec_open(pCodecCtx, pCodec)<0) { av_close_input_file(pFormatCtx); return 0; } avcodec_close(pCodecCtx); av_close_input_file(pFormatCtx); return 1; }
static HRESULT FFMVWrapper_BeginTransform( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut, BOOL bReuseSample ) { CFFMVWrapperImpl* This = pImpl->m_pUserData; BITMAPINFO* pbiIn = NULL; BITMAPINFO* pbiOut = NULL; LONG width, height; DWORD dwFourCC; AVCodec* codec; HRESULT hr; int i; TRACE("(%p,%p,%p,%d)\n",This,pmtIn,pmtOut,bReuseSample); if ( This == NULL || This->ctx.codec ) return E_UNEXPECTED; hr = FFMVWrapper_CheckMediaType( pImpl, pmtIn, pmtOut ); if ( FAILED(hr) ) return hr; FFMVWrapper_ReleaseDIBBuffers(This); if ( IsEqualGUID( &pmtIn->formattype, &FORMAT_VideoInfo ) ) { pbiIn = (BITMAPINFO*)(&((VIDEOINFOHEADER*)pmtIn->pbFormat)->bmiHeader); dwFourCC = pbiIn->bmiHeader.biCompression; } else if ( IsEqualGUID( &pmtIn->formattype, &FORMAT_MPEGVideo ) ) { pbiIn = (BITMAPINFO*)(&((VIDEOINFOHEADER*)pmtIn->pbFormat)->bmiHeader); dwFourCC = mmioFOURCC('P','I','M','1'); } else return E_FAIL; width = pbiIn->bmiHeader.biWidth; height = (pbiIn->bmiHeader.biHeight < 0) ? -pbiIn->bmiHeader.biHeight : pbiIn->bmiHeader.biHeight; pbiOut = (BITMAPINFO*)(&((VIDEOINFOHEADER*)pmtOut->pbFormat)->bmiHeader); This->m_pbiIn = FFMVWrapper_DuplicateBitmapInfo(pbiIn); This->m_pbiOut = FFMVWrapper_DuplicateBitmapInfo(pbiOut); if ( This->m_pbiIn == NULL || This->m_pbiOut == NULL ) return E_OUTOFMEMORY; if ( This->m_pbiOut->bmiHeader.biCompression == 0 || This->m_pbiOut->bmiHeader.biCompression == 3 ) This->m_pbiOut->bmiHeader.biSizeImage = DIBSIZE(This->m_pbiOut->bmiHeader); for (i=0; ff_codecs[i].dwFourCC && ff_codecs[i].dwFourCC != dwFourCC; i++); if (!ff_codecs[i].dwFourCC) { TRACE("couldn't find codec format\n"); return E_FAIL; } codec = avcodec_find_decoder(ff_codecs[i].codec); if (!codec) { TRACE("couldn't open codec\n"); return E_FAIL; } if ( !bReuseSample ) { This->m_pOutBuf = QUARTZ_AllocMem(This->m_pbiOut->bmiHeader.biSizeImage); if ( This->m_pOutBuf == NULL ) return E_OUTOFMEMORY; ZeroMemory( This->m_pOutBuf, This->m_pbiOut->bmiHeader.biSizeImage ); } This->rtCur = 0; This->rtInternal = 0; EnterCriticalSection( &This->m_cs ); avcodec_get_context_defaults( &This->ctx ); This->ctx.width = width; This->ctx.height = height; if (codec->id == CODEC_ID_MPEG1VIDEO || codec->id == CODEC_ID_H264) This->ctx.flags |= CODEC_FLAG_TRUNCATED; TRACE("opening codec for %dx%d video\n", This->ctx.width, This->ctx.height); if (avcodec_open( &This->ctx, codec) < 0) { TRACE("couldn't open codec\n"); return E_FAIL; } LeaveCriticalSection( &This->m_cs ); return NOERROR; }
int main(int argc, char* argv[]) { AVFormatContext *pFormatCtx; int i, videoindex; AVCodecContext *pCodecCtx; AVCodec *pCodec; AVFrame *pFrame,*pFrameYUV; uint8_t *out_buffer; AVPacket *packet; int y_size; int ret, got_picture; struct SwsContext *img_convert_ctx; char filepath[]="bigbuckbunny_480x272.h265"; //SDL--------------------------- int screen_w=0,screen_h=0; SDL_Window *screen; SDL_Renderer* sdlRenderer; SDL_Texture* sdlTexture; SDL_Rect sdlRect; FILE *fp_yuv; av_register_all(); avformat_network_init(); pFormatCtx = avformat_alloc_context(); if(avformat_open_input(&pFormatCtx,filepath,NULL,NULL)!=0){ printf("Couldn't open input stream.\n"); return -1; } if(avformat_find_stream_info(pFormatCtx,NULL)<0){ printf("Couldn't find stream information.\n"); return -1; } videoindex=-1; for(i=0; i<pFormatCtx->nb_streams; i++) if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){ videoindex=i; break; } if(videoindex==-1){ printf("Didn't find a video stream.\n"); return -1; } pCodecCtx=pFormatCtx->streams[videoindex]->codec; pCodec=avcodec_find_decoder(pCodecCtx->codec_id); if(pCodec==NULL){ printf("Codec not found.\n"); return -1; } if(avcodec_open2(pCodecCtx, pCodec,NULL)<0){ printf("Could not open codec.\n"); return -1; } pFrame=av_frame_alloc(); pFrameYUV=av_frame_alloc(); out_buffer=(uint8_t *)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height)); avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); packet=(AVPacket *)av_malloc(sizeof(AVPacket)); //Output Info----------------------------- printf("--------------- File Information ----------------\n"); av_dump_format(pFormatCtx,0,filepath,0); printf("-------------------------------------------------\n"); img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); #if OUTPUT_YUV420P fp_yuv=fopen("output.yuv","wb+"); #endif if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) { printf( "Could not initialize SDL - %s\n", SDL_GetError()); return -1; } screen_w = pCodecCtx->width; screen_h = pCodecCtx->height; //SDL 2.0 Support for multiple windows screen = SDL_CreateWindow("Simplest ffmpeg player's Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_w, screen_h, SDL_WINDOW_OPENGL); if(!screen) { printf("SDL: could not create window - exiting:%s\n",SDL_GetError()); return -1; } sdlRenderer = SDL_CreateRenderer(screen, -1, 0); //IYUV: Y + U + V (3 planes) //YV12: Y + V + U (3 planes) sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING,pCodecCtx->width,pCodecCtx->height); sdlRect.x=0; sdlRect.y=0; sdlRect.w=screen_w; sdlRect.h=screen_h; //SDL End---------------------- while(av_read_frame(pFormatCtx, packet)>=0){ if(packet->stream_index==videoindex){ ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet); if(ret < 0){ printf("Decode Error.\n"); return -1; } if(got_picture){ sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize); #if OUTPUT_YUV420P y_size=pCodecCtx->width*pCodecCtx->height; fwrite(pFrameYUV->data[0],1,y_size,fp_yuv); //Y fwrite(pFrameYUV->data[1],1,y_size/4,fp_yuv); //U fwrite(pFrameYUV->data[2],1,y_size/4,fp_yuv); //V #endif //SDL--------------------------- #if 0 SDL_UpdateTexture( sdlTexture, NULL, pFrameYUV->data[0], pFrameYUV->linesize[0] ); #else SDL_UpdateYUVTexture(sdlTexture, &sdlRect, pFrameYUV->data[0], pFrameYUV->linesize[0], pFrameYUV->data[1], pFrameYUV->linesize[1], pFrameYUV->data[2], pFrameYUV->linesize[2]); #endif SDL_RenderClear( sdlRenderer ); SDL_RenderCopy( sdlRenderer, sdlTexture, NULL, &sdlRect); SDL_RenderPresent( sdlRenderer ); //SDL End----------------------- //Delay 40ms SDL_Delay(40); } } av_free_packet(packet); } //flush decoder //FIX: Flush Frames remained in Codec while (1) { ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet); if (ret < 0) break; if (!got_picture) break; sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize); #if OUTPUT_YUV420P int y_size=pCodecCtx->width*pCodecCtx->height; fwrite(pFrameYUV->data[0],1,y_size,fp_yuv); //Y fwrite(pFrameYUV->data[1],1,y_size/4,fp_yuv); //U fwrite(pFrameYUV->data[2],1,y_size/4,fp_yuv); //V #endif //SDL--------------------------- SDL_UpdateTexture( sdlTexture, &sdlRect, pFrameYUV->data[0], pFrameYUV->linesize[0] ); SDL_RenderClear( sdlRenderer ); SDL_RenderCopy( sdlRenderer, sdlTexture, NULL, &sdlRect); SDL_RenderPresent( sdlRenderer ); //SDL End----------------------- //Delay 40ms SDL_Delay(40); } sws_freeContext(img_convert_ctx); #if OUTPUT_YUV420P fclose(fp_yuv); #endif SDL_Quit(); av_frame_free(&pFrameYUV); av_frame_free(&pFrame); avcodec_close(pCodecCtx); avformat_close_input(&pFormatCtx); return 0; }
int setupDemuxerCodecs(DemuxerSettings *ds) { AVCodec *pCodecVideo, *pCodecAudio, *pCodecSub; if (ds->do_video) { ds->pCodecCtxVideo = ds->pFormatCtx->streams[ds->videoStream]->codec; // Find the decoder for the video stream pCodecVideo = avcodec_find_decoder(ds->pCodecCtxVideo->codec_id); if (pCodecVideo == NULL) { av_log(NULL, AV_LOG_FATAL, "Error: Codec [%d] for video not found.\n", ds->pCodecCtxVideo->codec_id); return -1; // Codec not found } // Open video codec if (avcodec_open(ds->pCodecCtxVideo, pCodecVideo) < 0) { av_log(NULL, AV_LOG_FATAL, "Error: Codec for video not able to open.\n"); return -1; // Could not open codec } // Hack to correct wrong frame rates that seem to be generated by some codecs if (ds->pCodecCtxVideo->time_base.num > 1000 && ds->pCodecCtxVideo->time_base.den == 1) ds->pCodecCtxVideo->time_base.den = 1000; } if (ds->do_audio) { ds->pCodecCtxAudio = ds->pFormatCtx->streams[ds->audioStream]->codec; // Find the decoder for the audio stream pCodecAudio = avcodec_find_decoder(ds->pCodecCtxAudio->codec_id); if (pCodecAudio == NULL) { av_log(NULL, AV_LOG_FATAL, "Error: Codec [%d] for audio not found.\n", ds->pCodecCtxAudio->codec_id); return -1; // Codec not found } // Open audio codec if (avcodec_open(ds->pCodecCtxAudio, pCodecAudio) < 0) { av_log(NULL, AV_LOG_FATAL, "Error: Codec for audio not able to open.\n"); return -1; // Could not open codec } } if (ds->do_sub) { ds->pCodecCtxSub = ds->pFormatCtx->streams[ds->subStream]->codec; // Find the decoder for the subtitle stream pCodecSub = avcodec_find_decoder(ds->pCodecCtxSub->codec_id); if (pCodecSub == NULL) { av_log(NULL, AV_LOG_FATAL, "Error: Codec [%d] for subtitle not found.\n", ds->pCodecCtxSub->codec_id); //return -1; // Codec not found ds->pCodecCtxSub = NULL; } // Open subtitle codec if (ds->pCodecCtxSub && avcodec_open(ds->pCodecCtxSub, pCodecSub) < 0) { av_log(NULL, AV_LOG_FATAL, "Error: Codec for subtitle not able to open.\n"); return -1; // Could not open codec } } return 0; }