X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffplay.c;h=79f430de5e7b0f278ad880401d86491140b71e16;hb=4c2bfabc3a82f976aa6f63d572a0040701bae7c2;hp=d302793924bcccddca8b196dac5e3439e79ca93c;hpb=e8fbd80e1488144a3e70b72151c324aa25f2bd72;p=ffmpeg diff --git a/ffplay.c b/ffplay.c index d302793924b..79f430de5e7 100644 --- a/ffplay.c +++ b/ffplay.c @@ -73,6 +73,9 @@ const int program_birth_year = 2003; /* Calculate actual buffer size keeping in mind not cause too frequent audio callbacks */ #define SDL_AUDIO_MAX_CALLBACKS_PER_SEC 30 +/* Step size for volume control */ +#define SDL_VOLUME_STEP (SDL_MIX_MAXVOLUME / 50) + /* no AV sync correction is done if below the minimum AV sync threshold */ #define AV_SYNC_THRESHOLD_MIN 0.04 /* AV sync correction is done if above the maximum AV sync threshold */ @@ -246,6 +249,8 @@ typedef struct VideoState { unsigned int audio_buf1_size; int audio_buf_index; /* in bytes */ int audio_write_buf_size; + int audio_volume; + int muted; struct AudioParams audio_src; #if CONFIG_AVFILTER struct AudioParams audio_filter_src; @@ -285,7 +290,7 @@ typedef struct VideoState { SDL_Rect last_display_rect; int eof; - char filename[1024]; + char *filename; int width, height, xleft, ytop; int step; @@ -446,12 +451,21 @@ static int packet_queue_put_nullpacket(PacketQueue *q, int stream_index) } /* packet queue handling */ -static void packet_queue_init(PacketQueue *q) +static int packet_queue_init(PacketQueue *q) { memset(q, 0, sizeof(PacketQueue)); q->mutex = SDL_CreateMutex(); + if (!q->mutex) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError()); + return AVERROR(ENOMEM); + } q->cond = SDL_CreateCond(); + if (!q->cond) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError()); + return AVERROR(ENOMEM); + } q->abort_request = 1; + return 0; } static void packet_queue_flush(PacketQueue *q) @@ -643,10 +657,14 @@ static int frame_queue_init(FrameQueue *f, PacketQueue *pktq, int max_size, int { int i; memset(f, 0, sizeof(FrameQueue)); - if (!(f->mutex = SDL_CreateMutex())) + if (!(f->mutex = SDL_CreateMutex())) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError()); return AVERROR(ENOMEM); - if (!(f->cond = SDL_CreateCond())) + } + if (!(f->cond = SDL_CreateCond())) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError()); return AVERROR(ENOMEM); + } f->pktq = pktq; f->max_size = FFMIN(max_size, FRAME_QUEUE_SIZE); f->keep_last = !!keep_last; @@ -1132,6 +1150,7 @@ static void stream_close(VideoState *is) sws_freeContext(is->img_convert_ctx); #endif sws_freeContext(is->sub_convert_ctx); + av_free(is->filename); av_free(is); } @@ -1348,6 +1367,16 @@ static void toggle_pause(VideoState *is) is->step = 0; } +static void toggle_mute(VideoState *is) +{ + is->muted = !is->muted; +} + +static void update_volume(VideoState *is, int sign, int step) +{ + is->audio_volume = av_clip(is->audio_volume + sign * step, 0, SDL_MIX_MAXVOLUME); +} + static void step_to_next_frame(VideoState *is) { /* if the stream is paused unpause it, then step */ @@ -2055,10 +2084,15 @@ static int audio_thread(void *arg) return ret; } -static void decoder_start(Decoder *d, int (*fn)(void *), void *arg) +static int decoder_start(Decoder *d, int (*fn)(void *), void *arg) { packet_queue_start(d->queue); d->decoder_tid = SDL_CreateThread(fn, arg); + if (!d->decoder_tid) { + av_log(NULL, AV_LOG_ERROR, "SDL_CreateThread(): %s\n", SDL_GetError()); + return AVERROR(ENOMEM); + } + return 0; } static int video_thread(void *arg) @@ -2447,7 +2481,13 @@ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len) len1 = is->audio_buf_size - is->audio_buf_index; if (len1 > len) len1 = len; - memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1); + if (!is->muted && is->audio_volume == SDL_MIX_MAXVOLUME) + memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1); + else { + memset(stream, is->silence_buf[0], len1); + if (!is->muted) + SDL_MixAudio(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1, is->audio_volume); + } len -= len1; stream += len1; is->audio_buf_index += len1; @@ -2650,7 +2690,8 @@ static int stream_component_open(VideoState *is, int stream_index) is->auddec.start_pts = is->audio_st->start_time; is->auddec.start_pts_tb = is->audio_st->time_base; } - decoder_start(&is->auddec, audio_thread, is); + if ((ret = decoder_start(&is->auddec, audio_thread, is)) < 0) + goto fail; SDL_PauseAudio(0); break; case AVMEDIA_TYPE_VIDEO: @@ -2661,7 +2702,8 @@ static int stream_component_open(VideoState *is, int stream_index) is->viddec_height = avctx->height; decoder_init(&is->viddec, avctx, &is->videoq, is->continue_read_thread); - decoder_start(&is->viddec, video_thread, is); + if ((ret = decoder_start(&is->viddec, video_thread, is)) < 0) + goto fail; is->queue_attachments_req = 1; break; case AVMEDIA_TYPE_SUBTITLE: @@ -2669,7 +2711,8 @@ static int stream_component_open(VideoState *is, int stream_index) is->subtitle_st = ic->streams[stream_index]; decoder_init(&is->subdec, avctx, &is->subtitleq, is->continue_read_thread); - decoder_start(&is->subdec, subtitle_thread, is); + if ((ret = decoder_start(&is->subdec, subtitle_thread, is)) < 0) + goto fail; break; default: break; @@ -2778,6 +2821,12 @@ static int read_thread(void *arg) int scan_all_pmts_set = 0; int64_t pkt_ts; + if (!wait_mutex) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError()); + ret = AVERROR(ENOMEM); + goto fail; + } + memset(st_index, -1, sizeof(st_index)); is->last_video_stream = is->video_stream = -1; is->last_audio_stream = is->audio_stream = -1; @@ -3099,7 +3148,9 @@ static VideoState *stream_open(const char *filename, AVInputFormat *iformat) is = av_mallocz(sizeof(VideoState)); if (!is) return NULL; - av_strlcpy(is->filename, filename, sizeof(is->filename)); + is->filename = av_strdup(filename); + if (!is->filename) + goto fail; is->iformat = iformat; is->ytop = 0; is->xleft = 0; @@ -3112,19 +3163,26 @@ static VideoState *stream_open(const char *filename, AVInputFormat *iformat) if (frame_queue_init(&is->sampq, &is->audioq, SAMPLE_QUEUE_SIZE, 1) < 0) goto fail; - packet_queue_init(&is->videoq); - packet_queue_init(&is->audioq); - packet_queue_init(&is->subtitleq); + if (packet_queue_init(&is->videoq) < 0 || + packet_queue_init(&is->audioq) < 0 || + packet_queue_init(&is->subtitleq) < 0) + goto fail; - is->continue_read_thread = SDL_CreateCond(); + if (!(is->continue_read_thread = SDL_CreateCond())) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError()); + goto fail; + } init_clock(&is->vidclk, &is->videoq.serial); init_clock(&is->audclk, &is->audioq.serial); init_clock(&is->extclk, &is->extclk.serial); is->audio_clock_serial = -1; + is->audio_volume = SDL_MIX_MAXVOLUME; + is->muted = 0; is->av_sync_type = av_sync_type; is->read_tid = SDL_CreateThread(read_thread, is); if (!is->read_tid) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateThread(): %s\n", SDL_GetError()); fail: stream_close(is); return NULL; @@ -3311,6 +3369,17 @@ static void event_loop(VideoState *cur_stream) case SDLK_SPACE: toggle_pause(cur_stream); break; + case SDLK_m: + toggle_mute(cur_stream); + break; + case SDLK_KP_MULTIPLY: + case SDLK_0: + update_volume(cur_stream, 1, SDL_VOLUME_STEP); + break; + case SDLK_KP_DIVIDE: + case SDLK_9: + update_volume(cur_stream, -1, SDL_VOLUME_STEP); + break; case SDLK_s: // S: Step to next frame step_to_next_frame(cur_stream); break; @@ -3644,6 +3713,9 @@ void show_help_default(const char *opt, const char *arg) "q, ESC quit\n" "f toggle full screen\n" "p, SPC pause\n" + "m toggle mute\n" + "9, 0 decrease and increase volume respectively\n" + "/, * decrease and increase volume respectively\n" "a cycle audio channel in the current program\n" "v cycle video channel\n" "t cycle subtitle channel in the current program\n" @@ -3662,8 +3734,10 @@ static int lockmgr(void **mtx, enum AVLockOp op) switch(op) { case AV_LOCK_CREATE: *mtx = SDL_CreateMutex(); - if(!*mtx) + if(!*mtx) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError()); return 1; + } return 0; case AV_LOCK_OBTAIN: return !!SDL_LockMutex(*mtx); @@ -3740,6 +3814,8 @@ int main(int argc, char **argv) SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE); SDL_EventState(SDL_USEREVENT, SDL_IGNORE); + SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); + if (av_lockmgr_register(lockmgr)) { av_log(NULL, AV_LOG_FATAL, "Could not initialize lock manager!\n"); do_exit(NULL);