diff --git a/libobs-d3d11/d3d11-exports.h b/libobs-d3d11/d3d11-exports.h index 750b29ad0b54ab4cd52559d1f437b323ae917852..c456b0e7162d5c26425a93f31733c8738f84719c 100644 --- a/libobs-d3d11/d3d11-exports.h +++ b/libobs-d3d11/d3d11-exports.h @@ -150,7 +150,7 @@ EXPORT void stagesurface_destroy(stagesurf_t stagesurf); EXPORT uint32_t stagesurface_getwidth(stagesurf_t stagesurf); EXPORT uint32_t stagesurface_getheight(stagesurf_t stagesurf); EXPORT enum gs_color_format stagesurface_getcolorformat(stagesurf_t stagesurf); -EXPORT bool stagesurface_map(stagesurf_t stagesurf, const uint8_t **data, +EXPORT bool stagesurface_map(stagesurf_t stagesurf, uint8_t **data, uint32_t *linesize); EXPORT void stagesurface_unmap(stagesurf_t stagesurf); diff --git a/libobs-d3d11/d3d11-subsystem.cpp b/libobs-d3d11/d3d11-subsystem.cpp index 19478d288d4b36951a8ce056788aa16c7937258f..433a174213935519c9d9c0e597216bdcbcf27967 100644 --- a/libobs-d3d11/d3d11-subsystem.cpp +++ b/libobs-d3d11/d3d11-subsystem.cpp @@ -1552,8 +1552,7 @@ enum gs_color_format stagesurface_getcolorformat(stagesurf_t stagesurf) return stagesurf->format; } -bool stagesurface_map(stagesurf_t stagesurf, const uint8_t **data, - uint32_t *linesize) +bool stagesurface_map(stagesurf_t stagesurf, uint8_t **data, uint32_t *linesize) { D3D11_MAPPED_SUBRESOURCE map; if (FAILED(stagesurf->device->context->Map(stagesurf->texture, 0, diff --git a/libobs-opengl/gl-exports.h b/libobs-opengl/gl-exports.h index 06070bcc31131c9c03d39bfbf8aafd9e3f0473be..1d2430a3e123a68539a3ecf0fd94c47116efbb92 100644 --- a/libobs-opengl/gl-exports.h +++ b/libobs-opengl/gl-exports.h @@ -145,7 +145,7 @@ EXPORT void stagesurface_destroy(stagesurf_t stagesurf); EXPORT uint32_t stagesurface_getwidth(stagesurf_t stagesurf); EXPORT uint32_t stagesurface_getheight(stagesurf_t stagesurf); EXPORT enum gs_color_format stagesurface_getcolorformat(stagesurf_t stagesurf); -EXPORT bool stagesurface_map(stagesurf_t stagesurf, const uint8_t **data, +EXPORT bool stagesurface_map(stagesurf_t stagesurf, uint8_t **data, uint32_t *linesize); EXPORT void stagesurface_unmap(stagesurf_t stagesurf); diff --git a/libobs-opengl/gl-stagesurf.c b/libobs-opengl/gl-stagesurf.c index 924c54c91abfe5a9e53c6d420116a08b990adec1..73d9cacc787dd3cad2649bf0404d55b9f67ef7ad 100644 --- a/libobs-opengl/gl-stagesurf.c +++ b/libobs-opengl/gl-stagesurf.c @@ -199,8 +199,7 @@ enum gs_color_format stagesurface_getcolorformat(stagesurf_t stagesurf) return stagesurf->format; } -bool stagesurface_map(stagesurf_t stagesurf, const uint8_t **data, - uint32_t *linesize) +bool stagesurface_map(stagesurf_t stagesurf, uint8_t **data, uint32_t *linesize) { if (!gl_bind_buffer(GL_PIXEL_PACK_BUFFER, stagesurf->pack_buffer)) goto fail; diff --git a/libobs/graphics/graphics-internal.h b/libobs/graphics/graphics-internal.h index 5990b78fcbec52a77501ec079c5cd1f3e2f0622e..35ee061681bfe1b332286985ec763e74982f1eeb 100644 --- a/libobs/graphics/graphics-internal.h +++ b/libobs/graphics/graphics-internal.h @@ -158,7 +158,7 @@ struct gs_exports { enum gs_color_format (*stagesurface_getcolorformat)( stagesurf_t stagesurf); bool (*stagesurface_map)(stagesurf_t stagesurf, - const uint8_t **data, uint32_t *linesize); + uint8_t **data, uint32_t *linesize); void (*stagesurface_unmap)(stagesurf_t stagesurf); void (*zstencil_destroy)(zstencil_t zstencil); diff --git a/libobs/graphics/graphics.c b/libobs/graphics/graphics.c index 693afac2422a46b7eeec03e73e24bb7048901886..5b5de8969b1a6cf5fed29d8f96cb137256e09461 100644 --- a/libobs/graphics/graphics.c +++ b/libobs/graphics/graphics.c @@ -1805,8 +1805,7 @@ enum gs_color_format stagesurface_getcolorformat(stagesurf_t stagesurf) return graphics->exports.stagesurface_getcolorformat(stagesurf); } -bool stagesurface_map(stagesurf_t stagesurf, const uint8_t **data, - uint32_t *linesize) +bool stagesurface_map(stagesurf_t stagesurf, uint8_t **data, uint32_t *linesize) { graphics_t graphics = thread_graphics; if (!graphics || !stagesurf) return false; diff --git a/libobs/graphics/graphics.h b/libobs/graphics/graphics.h index 3f77db6550a45ca78382efa42c329f5b2d3e0d9c..84cf2767f4aa8c39924b1f158c08b65bae50cb52 100644 --- a/libobs/graphics/graphics.h +++ b/libobs/graphics/graphics.h @@ -659,7 +659,7 @@ EXPORT void stagesurface_destroy(stagesurf_t stagesurf); EXPORT uint32_t stagesurface_getwidth(stagesurf_t stagesurf); EXPORT uint32_t stagesurface_getheight(stagesurf_t stagesurf); EXPORT enum gs_color_format stagesurface_getcolorformat(stagesurf_t stagesurf); -EXPORT bool stagesurface_map(stagesurf_t stagesurf, const uint8_t **data, +EXPORT bool stagesurface_map(stagesurf_t stagesurf, uint8_t **data, uint32_t *linesize); EXPORT void stagesurface_unmap(stagesurf_t stagesurf); diff --git a/libobs/media-io/audio-io.c b/libobs/media-io/audio-io.c index 69c4b3a7755c6621ce7b29fb31467fb8f7f5c384..30be6cd642107a115777d4c63f676a15ad4b0853 100644 --- a/libobs/media-io/audio-io.c +++ b/libobs/media-io/audio-io.c @@ -34,7 +34,7 @@ struct audio_input { struct audio_convert_info conversion; audio_resampler_t resampler; - void (*callback)(void *param, const struct audio_data *data); + void (*callback)(void *param, struct audio_data *data); void *param; }; @@ -337,7 +337,8 @@ static bool resample_audio_output(struct audio_input *input, success = audio_resampler_resample(input->resampler, output, &frames, &offset, - data->data, data->frames); + (const uint8_t *const *)data->data, + data->frames); for (size_t i = 0; i < MAX_AV_PLANES; i++) data->data[i] = output[i]; @@ -455,7 +456,7 @@ static void *audio_thread(void *param) /* ------------------------------------------------------------------------- */ static size_t audio_get_input_idx(audio_t video, - void (*callback)(void *param, const struct audio_data *data), + void (*callback)(void *param, struct audio_data *data), void *param) { for (size_t i = 0; i < video->inputs.num; i++) { @@ -500,7 +501,7 @@ static inline bool audio_input_init(struct audio_input *input, bool audio_output_connect(audio_t audio, const struct audio_convert_info *conversion, - void (*callback)(void *param, const struct audio_data *data), + void (*callback)(void *param, struct audio_data *data), void *param) { bool success = false; @@ -542,7 +543,7 @@ bool audio_output_connect(audio_t audio, } void audio_output_disconnect(audio_t audio, - void (*callback)(void *param, const struct audio_data *data), + void (*callback)(void *param, struct audio_data *data), void *param) { if (!audio) return; diff --git a/libobs/media-io/audio-io.h b/libobs/media-io/audio-io.h index a54393c6582e391838adda98df99fd7554d974da..41be4fb00ebf41a1cfa93b940a8f2f1508c7e05a 100644 --- a/libobs/media-io/audio-io.h +++ b/libobs/media-io/audio-io.h @@ -63,7 +63,7 @@ enum speaker_layout { }; struct audio_data { - const uint8_t *data[MAX_AV_PLANES]; + uint8_t *data[MAX_AV_PLANES]; uint32_t frames; uint64_t timestamp; float volume; @@ -174,10 +174,10 @@ EXPORT void audio_output_close(audio_t audio); EXPORT bool audio_output_connect(audio_t video, const struct audio_convert_info *conversion, - void (*callback)(void *param, const struct audio_data *data), + void (*callback)(void *param, struct audio_data *data), void *param); EXPORT void audio_output_disconnect(audio_t video, - void (*callback)(void *param, const struct audio_data *data), + void (*callback)(void *param, struct audio_data *data), void *param); EXPORT bool audio_output_active(audio_t audio); diff --git a/libobs/media-io/video-io.c b/libobs/media-io/video-io.c index e71ce71fd8d7c22d2a45cf36e31421eacf5ced23..da226d6eeeda1d5ee34792eab5ac1e37e29f55fa 100644 --- a/libobs/media-io/video-io.c +++ b/libobs/media-io/video-io.c @@ -34,7 +34,7 @@ struct video_input { struct video_frame frame[MAX_CONVERT_BUFFERS]; int cur_frame; - void (*callback)(void *param, const struct video_data *frame); + void (*callback)(void *param, struct video_data *frame); void *param; }; @@ -91,7 +91,8 @@ static inline bool scale_video_output(struct video_input *input, success = video_scaler_scale(input->scaler, frame->data, frame->linesize, - data->data, data->linesize); + (const uint8_t * const*)data->data, + data->linesize); if (success) { for (size_t i = 0; i < MAX_AV_PLANES; i++) { @@ -209,7 +210,7 @@ void video_output_close(video_t video) } static size_t video_get_input_idx(video_t video, - void (*callback)(void *param, const struct video_data *frame), + void (*callback)(void *param, struct video_data *frame), void *param) { for (size_t i = 0; i < video->inputs.num; i++) { @@ -259,7 +260,7 @@ static inline bool video_input_init(struct video_input *input, bool video_output_connect(video_t video, const struct video_scale_info *conversion, - void (*callback)(void *param, const struct video_data *frame), + void (*callback)(void *param, struct video_data *frame), void *param) { bool success = false; @@ -300,7 +301,7 @@ bool video_output_connect(video_t video, } void video_output_disconnect(video_t video, - void (*callback)(void *param, const struct video_data *frame), + void (*callback)(void *param, struct video_data *frame), void *param) { if (!video || !callback) diff --git a/libobs/media-io/video-io.h b/libobs/media-io/video-io.h index 4f0b1624a0e9e8e8c9379cdf902568287b9c6c66..ab57fb7bb310f91d727253d6ebacdb9430cf20a4 100644 --- a/libobs/media-io/video-io.h +++ b/libobs/media-io/video-io.h @@ -47,7 +47,7 @@ enum video_format { }; struct video_data { - const uint8_t *data[MAX_AV_PLANES]; + uint8_t *data[MAX_AV_PLANES]; uint32_t linesize[MAX_AV_PLANES]; uint64_t timestamp; }; @@ -82,24 +82,30 @@ static inline bool format_is_yuv(enum video_format format) } enum video_scale_type { - VIDEO_SCALE_POINT = 0, - VIDEO_SCALE_FAST_BILINEAR = 1, - VIDEO_SCALE_DEFAULT = VIDEO_SCALE_FAST_BILINEAR, - VIDEO_SCALE_BILINEAR = 2, - VIDEO_SCALE_BICUBIC = 3, + VIDEO_SCALE_DEFAULT, + VIDEO_SCALE_POINT, + VIDEO_SCALE_FAST_BILINEAR, + VIDEO_SCALE_BILINEAR, + VIDEO_SCALE_BICUBIC, }; enum video_colorspace { - VIDEO_CS_601 = 0, - VIDEO_CS_DEFAULT = VIDEO_CS_601, - VIDEO_CS_709 = 1, + VIDEO_CS_DEFAULT, + VIDEO_CS_601, + VIDEO_CS_709, +}; + +enum video_range_type { + VIDEO_RANGE_DEFAULT, + VIDEO_RANGE_PARTIAL, + VIDEO_RANGE_FULL }; struct video_scale_info { enum video_format format; uint32_t width; uint32_t height; - bool full_range; + enum video_range_type range; enum video_colorspace colorspace; }; @@ -112,10 +118,10 @@ EXPORT void video_output_close(video_t video); EXPORT bool video_output_connect(video_t video, const struct video_scale_info *conversion, - void (*callback)(void *param, const struct video_data *frame), + void (*callback)(void *param, struct video_data *frame), void *param); EXPORT void video_output_disconnect(video_t video, - void (*callback)(void *param, const struct video_data *frame), + void (*callback)(void *param, struct video_data *frame), void *param); EXPORT bool video_output_active(video_t video); diff --git a/libobs/media-io/video-scaler-ffmpeg.c b/libobs/media-io/video-scaler-ffmpeg.c index c527645fdb66f34a971b12f62237d1ba11ab805e..1e3d2b62d3a25461a765fecad7e567b589508022 100644 --- a/libobs/media-io/video-scaler-ffmpeg.c +++ b/libobs/media-io/video-scaler-ffmpeg.c @@ -46,6 +46,7 @@ static inline enum AVPixelFormat get_ffmpeg_video_format( static inline int get_ffmpeg_scale_type(enum video_scale_type type) { switch (type) { + case VIDEO_SCALE_DEFAULT: return SWS_FAST_BILINEAR; case VIDEO_SCALE_POINT: return SWS_POINT; case VIDEO_SCALE_FAST_BILINEAR: return SWS_FAST_BILINEAR; case VIDEO_SCALE_BILINEAR: return SWS_BILINEAR | SWS_AREA; @@ -58,13 +59,25 @@ static inline int get_ffmpeg_scale_type(enum video_scale_type type) static inline const int *get_ffmpeg_coeffs(enum video_colorspace cs) { switch (cs) { - case VIDEO_CS_601: return sws_getCoefficients(SWS_CS_ITU601); - case VIDEO_CS_709: return sws_getCoefficients(SWS_CS_ITU709); + case VIDEO_CS_DEFAULT: return sws_getCoefficients(SWS_CS_ITU601); + case VIDEO_CS_601: return sws_getCoefficients(SWS_CS_ITU601); + case VIDEO_CS_709: return sws_getCoefficients(SWS_CS_ITU709); } return sws_getCoefficients(SWS_CS_ITU601); } +static inline int get_ffmpeg_range_type(enum video_range_type type) +{ + switch (type) { + case VIDEO_RANGE_DEFAULT: return 0; + case VIDEO_RANGE_PARTIAL: return 0; + case VIDEO_RANGE_FULL: return 1; + } + + return 0; +} + #define FIXED_1_0 (1<<16) int video_scaler_create(video_scaler_t *scaler_out, @@ -77,6 +90,8 @@ int video_scaler_create(video_scaler_t *scaler_out, int scale_type = get_ffmpeg_scale_type(type); const int *coeff_src = get_ffmpeg_coeffs(src->colorspace); const int *coeff_dst = get_ffmpeg_coeffs(dst->colorspace); + int range_src = get_ffmpeg_range_type(src->range); + int range_dst = get_ffmpeg_range_type(dst->range); struct video_scaler *scaler; int ret; @@ -101,8 +116,8 @@ int video_scaler_create(video_scaler_t *scaler_out, } ret = sws_setColorspaceDetails(scaler->swscale, - coeff_src, src->full_range, - coeff_dst, dst->full_range, + coeff_src, range_src, + coeff_dst, range_dst, 0, FIXED_1_0, FIXED_1_0); if (ret < 0) { blog(LOG_DEBUG, "video_scaler_create: " diff --git a/libobs/obs-encoder.c b/libobs/obs-encoder.c index cd25fa4825d74445bc87dbbdd95aac525f9cde7e..e3f08af6f7d169abd25d7fe126aa424c00365557 100644 --- a/libobs/obs-encoder.c +++ b/libobs/obs-encoder.c @@ -33,56 +33,160 @@ static inline struct obs_encoder_info *get_encoder_info(const char *id) const char *obs_encoder_getdisplayname(const char *id, const char *locale) { struct obs_encoder_info *ei = get_encoder_info(id); - if (!ei) - return NULL; - - return ei->getname(locale); + return ei ? ei->getname(locale) : NULL; } -obs_encoder_t obs_encoder_create(const char *id, const char *name, +static bool init_encoder(struct obs_encoder *encoder, const char *name, obs_data_t settings) +{ + if (pthread_mutex_init(&encoder->callbacks_mutex, NULL) != 0) + return false; + + encoder->settings = obs_data_newref(settings); + encoder->data = encoder->info.create(encoder->settings, encoder); + + if (!encoder->data) { + pthread_mutex_destroy(&encoder->callbacks_mutex); + obs_data_release(encoder->settings); + return false; + } + + pthread_mutex_lock(&obs->data.encoders_mutex); + da_push_back(obs->data.encoders, &encoder); + pthread_mutex_unlock(&obs->data.encoders_mutex); + + encoder->name = bstrdup(name); + return true; +} + +static struct obs_encoder *create_encoder(const char *id, + enum obs_encoder_type type, const char *name, + obs_data_t settings, void *output, + uint32_t timebase_num, uint32_t timebase_den) { struct obs_encoder *encoder; struct obs_encoder_info *ei = get_encoder_info(id); + bool success; - if (!ei) + if (!ei || ei->type != type) return NULL; encoder = bzalloc(sizeof(struct obs_encoder)); - encoder->info = *ei; + encoder->info = *ei; + encoder->output = output; + encoder->timebase_num = timebase_num; + encoder->timebase_den = timebase_den; - if (pthread_mutex_init(&encoder->data_callbacks_mutex, NULL) != 0) { + success = init_encoder(encoder, name, settings); + if (!success) { bfree(encoder); - return NULL; + encoder = NULL; } - encoder->settings = obs_data_newref(settings); - encoder->data = ei->create(encoder->settings, encoder); + return encoder; +} - if (!encoder->data) { - pthread_mutex_destroy(&encoder->data_callbacks_mutex); - obs_data_release(encoder->settings); - bfree(encoder); +obs_encoder_t obs_encoder_create_video(const char *id, const char *name, + obs_data_t settings, video_t video) +{ + const struct video_output_info *voi; + + if (!name || !id || !video) return NULL; + + voi = video_output_getinfo(video); + return create_encoder(id, OBS_ENCODER_VIDEO, name, settings, video, + voi->fps_den, voi->fps_num); +} + +obs_encoder_t obs_encoder_create_audio(const char *id, const char *name, + obs_data_t settings, audio_t audio) +{ + const struct audio_output_info *aoi; + + if (!name || !id || !audio) + return NULL; + + aoi = audio_output_getinfo(audio); + return create_encoder(id, OBS_ENCODER_AUDIO, name, settings, audio, + 1, aoi->samples_per_sec); +} + +static void receive_video(void *param, struct video_data *frame); +static void receive_audio(void *param, struct audio_data *data); + +static inline struct audio_convert_info *get_audio_info( + struct obs_encoder *encoder, struct audio_convert_info *info) +{ + if (encoder->info.audio_info) + if (encoder->info.audio_info(encoder->data, info)) + return info; + + return false; +} + +static inline struct video_scale_info *get_video_info( + struct obs_encoder *encoder, struct video_scale_info *info) +{ + if (encoder->info.video_info) + if (encoder->info.video_info(encoder->data, info)) + return info; + + return NULL; +} + +static void add_connection(struct obs_encoder *encoder) +{ + struct audio_convert_info audio_info = {0}; + struct video_scale_info video_info = {0}; + + if (encoder->info.type == OBS_ENCODER_AUDIO) { + struct audio_convert_info *info = NULL; + + info = get_audio_info(encoder, &audio_info); + audio_output_connect(encoder->output, info, receive_audio, + encoder); + } else { + struct video_scale_info *info = NULL; + + info = get_video_info(encoder, &video_info); + video_output_connect(encoder->output, info, receive_video, + encoder); } +} - pthread_mutex_lock(&obs->data.encoders_mutex); - da_push_back(obs->data.encoders, &encoder); - pthread_mutex_unlock(&obs->data.encoders_mutex); +static void remove_connection(struct obs_encoder *encoder) +{ + if (encoder->info.type == OBS_ENCODER_AUDIO) + audio_output_disconnect(encoder->output, receive_audio, + encoder); + else + video_output_disconnect(encoder->output, receive_video, + encoder); +} - encoder->name = bstrdup(name); - return encoder; +static void full_stop(struct obs_encoder *encoder) +{ + if (encoder) { + pthread_mutex_lock(&encoder->callbacks_mutex); + da_free(encoder->callbacks); + remove_connection(encoder); + pthread_mutex_unlock(&encoder->callbacks_mutex); + } } void obs_encoder_destroy(obs_encoder_t encoder) { if (encoder) { + full_stop(encoder); + pthread_mutex_lock(&obs->data.encoders_mutex); da_erase_item(obs->data.encoders, &encoder); pthread_mutex_unlock(&obs->data.encoders_mutex); encoder->info.destroy(encoder->data); obs_data_release(encoder->settings); + pthread_mutex_destroy(&encoder->callbacks_mutex); bfree(encoder->name); bfree(encoder); } @@ -114,33 +218,15 @@ void obs_encoder_update(obs_encoder_t encoder, obs_data_t settings) if (!encoder) return; obs_data_apply(encoder->settings, settings); - encoder->info.update(encoder->data, encoder->settings); -} - -bool obs_encoder_reset(obs_encoder_t encoder, obs_data_t settings) -{ - if (!encoder) return false; - - return encoder->info.reset(encoder->data, settings); -} - -bool obs_encoder_encode(obs_encoder_t encoder, - const struct encoder_frame *frame, - struct encoder_packet *packet, bool *received_packet) -{ - if (!encoder) return false; - - return encoder->info.encode(encoder->data, frame, packet, - received_packet); + if (encoder->info.update) + encoder->info.update(encoder->data, encoder->settings); } bool obs_encoder_get_extra_data(obs_encoder_t encoder, uint8_t **extra_data, size_t *size) { - if (!encoder) return false; - - if (encoder->info.get_extra_data) - return encoder->info.get_extra_data(encoder, extra_data, size); + if (encoder && encoder->info.extra_data) + return encoder->info.extra_data(encoder, extra_data, size); return false; } @@ -153,24 +239,216 @@ obs_data_t obs_encoder_get_settings(obs_encoder_t encoder) return encoder->settings; } +static inline size_t get_callback_idx( + struct obs_encoder *encoder, + void (*new_packet)(void *param, struct encoder_packet *packet), + void *param) +{ + for (size_t i = 0; i < encoder->callbacks.num; i++) { + struct encoder_callback *cb = encoder->callbacks.array+i; + + if (cb->new_packet == new_packet && cb->param == param) + return i; + } + + return DARRAY_INVALID; +} + bool obs_encoder_start(obs_encoder_t encoder, void (*new_packet)(void *param, struct encoder_packet *packet), void *param) { - /* TODO: implement */ - UNUSED_PARAMETER(encoder); - UNUSED_PARAMETER(new_packet); - UNUSED_PARAMETER(param); - return false; + struct encoder_callback cb = {false, new_packet, param}; + bool success = true; + bool first = false; + + if (!encoder || !new_packet) return false; + + pthread_mutex_lock(&encoder->callbacks_mutex); + + first = (encoder->callbacks.num == 0); + if (first) + success = encoder->info.start(encoder->data, encoder->settings); + + if (success) { + size_t idx = get_callback_idx(encoder, new_packet, param); + if (idx == DARRAY_INVALID) + da_push_back(encoder->callbacks, &cb); + else + success = false; + } + + pthread_mutex_unlock(&encoder->callbacks_mutex); + + if (first) { + encoder->cur_pts = 0; + add_connection(encoder); + } + + return success; } void obs_encoder_stop(obs_encoder_t encoder, void (*new_packet)(void *param, struct encoder_packet *packet), void *param) { - /* TODO: implement */ - UNUSED_PARAMETER(encoder); - UNUSED_PARAMETER(new_packet); - UNUSED_PARAMETER(param); - return; + bool last = false; + size_t idx; + + if (!encoder) return; + + pthread_mutex_lock(&encoder->callbacks_mutex); + + idx = get_callback_idx(encoder, new_packet, param); + if (idx != DARRAY_INVALID) { + da_erase(encoder->callbacks, idx); + last = (encoder->callbacks.num == 0); + + if (last) + encoder->info.stop(encoder->data); + } + + pthread_mutex_unlock(&encoder->callbacks_mutex); + + if (last) + remove_connection(encoder); +} + +video_t obs_encoder_video(obs_encoder_t encoder) +{ + return (encoder && encoder->info.type == OBS_ENCODER_VIDEO) ? + encoder->output : NULL; +} + +audio_t obs_encoder_audio(obs_encoder_t encoder) +{ + return (encoder && encoder->info.type == OBS_ENCODER_AUDIO) ? + encoder->output : NULL; +} + +static inline bool get_sei(struct obs_encoder *encoder, + uint8_t **sei, size_t *size) +{ + if (encoder->info.sei_data) + return encoder->info.sei_data(encoder->data, sei, size); + return false; +} + +static void send_first_video_packet(struct obs_encoder *encoder, + struct encoder_callback *cb, struct encoder_packet *packet) +{ + struct encoder_packet first_packet; + DARRAY(uint8_t) data; + uint8_t *sei; + size_t size; + + /* always wait for first keyframe */ + if (!packet->keyframe) + return; + + da_init(data); + + if (!get_sei(encoder, &sei, &size)) { + cb->new_packet(cb->param, packet); + return; + } + + da_push_back_array(data, sei, size); + da_push_back_array(data, packet->data, packet->size); + + first_packet = *packet; + first_packet.data = data.array; + first_packet.size = data.num; + + cb->new_packet(cb->param, &first_packet); + cb->sent_first_packet = true; + + da_free(data); +} + +static inline void send_packet(struct obs_encoder *encoder, + struct encoder_callback *cb, struct encoder_packet *packet) +{ + /* include SEI in first video packet */ + if (encoder->info.type == OBS_ENCODER_VIDEO && !cb->sent_first_packet) + send_first_video_packet(encoder, cb, packet); + else + cb->new_packet(cb->param, packet); +} + +static inline void do_encode(struct obs_encoder *encoder, + struct encoder_frame *frame, struct encoder_packet *packet) +{ + bool received = false; + bool success; + + packet->timebase_num = encoder->timebase_num; + packet->timebase_den = encoder->timebase_den; + + success = encoder->info.encode(encoder->data, frame, packet, &received); + if (!success) { + full_stop(encoder); + blog(LOG_ERROR, "Error encoding with encoder '%s'", + encoder->name); + return; + } + + if (received) { + pthread_mutex_lock(&encoder->callbacks_mutex); + + for (size_t i = 0; i < encoder->callbacks.num; i++) { + struct encoder_callback *cb; + + cb = encoder->callbacks.array+i; + } + + pthread_mutex_unlock(&encoder->callbacks_mutex); + } +} + +static void receive_video(void *param, struct video_data *frame) +{ + struct obs_encoder *encoder = param; + struct encoder_packet packet = {0}; + struct encoder_frame enc_frame; + + memset(&enc_frame, 0, sizeof(struct encoder_frame)); + + for (size_t i = 0; i < MAX_AV_PLANES; i++) { + enc_frame.data[i] = frame->data[i]; + enc_frame.linesize[i] = frame->linesize[i]; + } + + enc_frame.frames = 1; + enc_frame.pts = encoder->cur_pts; + + do_encode(encoder, &enc_frame, &packet); + + encoder->cur_pts += encoder->timebase_num; +} + +static void receive_audio(void *param, struct audio_data *data) +{ + struct obs_encoder *encoder = param; + struct encoder_packet packet = {0}; + struct encoder_frame enc_frame; + size_t data_size; + + memset(&enc_frame, 0, sizeof(struct encoder_frame)); + + data_size = audio_output_blocksize(encoder->output) * data->frames; + + for (size_t i = 0; i < MAX_AV_PLANES; i++) { + if (data->data[i]) { + enc_frame.data[i] = data->data[i]; + enc_frame.linesize[i] = (uint32_t)data_size; + } + } + + enc_frame.frames = data->frames; + enc_frame.pts = encoder->cur_pts; + + do_encode(encoder, &enc_frame, &packet); + + encoder->cur_pts += data->frames; } diff --git a/libobs/obs-encoder.h b/libobs/obs-encoder.h index f5747a94581b54c828779deae4bedef6c53f72ed..b61b3e7570cb0869916101e362c8a7f6f4017f4d 100644 --- a/libobs/obs-encoder.h +++ b/libobs/obs-encoder.h @@ -19,34 +19,38 @@ /** Specifies the encoder type */ enum obs_encoder_type { - OBS_PACKET_AUDIO, - OBS_PACKET_VIDEO + OBS_ENCODER_AUDIO, + OBS_ENCODER_VIDEO }; /** Encoder output packet */ struct encoder_packet { - uint8_t *data; /**< Packet data */ - size_t size; /**< Packet size */ + uint8_t *data; /**< Packet data */ + size_t size; /**< Packet size */ - int64_t pts; /**< Presentation timestamp */ - int64_t dts; /**< Decode timestamp */ + int64_t pts; /**< Presentation timestamp */ + int64_t dts; /**< Decode timestamp */ - enum obs_encoder_type type; /**< Encoder type */ + int32_t timebase_num; /**< Timebase numerator */ + int32_t timebase_den; /**< Timebase denominator */ + + enum obs_encoder_type type; /**< Encoder type */ + + bool keyframe; /**< Is a keyframe */ /** * Packet priority * * This is generally use by video encoders to specify the priority - * of the packet. If this frame is dropped, it will have to wait for - * another packet of drop_priority. + * of the packet. */ int priority; /** * Dropped packet priority * - * If this packet is dropped, the next packet must be of this priority - * or higher to continue transmission. + * If this packet needs to be dropped, the next packet must be of this + * priority or higher to continue transmission. */ int drop_priority; }; @@ -83,6 +87,12 @@ struct obs_encoder_info { /** Specifies the named identifier of this encoder */ const char *id; + /** Specifies the encoder type (video or audio) */ + enum obs_encoder_type type; + + /** Specifies the codec */ + const char *codec; + /** * Gets the full translated name of this encoder * @@ -108,13 +118,13 @@ struct obs_encoder_info { void (*destroy)(void *data); /** - * Resets the encoder with the specified settings + * Starts the encoder * * @param data Data associated with this encoder context - * @param settings New settings for the encoder + * @param settings Settings for the encoder * @return true if successful, false otherwise */ - bool (*reset)(void *data, obs_data_t settings); + bool (*start)(void *data, obs_data_t settings); /** * Encodes frame(s), and outputs encoded packets as they become @@ -128,7 +138,7 @@ struct obs_encoder_info { * false otherwise * @return true if successful, false otherwise. */ - int (*encode)(void *data, const struct encoder_frame *frame, + bool (*encode)(void *data, struct encoder_frame *frame, struct encoder_packet *packet, bool *received_packet); /* ----------------------------------------------------------------- */ @@ -141,6 +151,13 @@ struct obs_encoder_info { */ void (*defaults)(obs_data_t settings); + /** + * Stops the encoder + * + * @param data Data associated with this encoder context + */ + void (*stop)(void *data); + /** * Gets the property information of this encoder * @@ -150,21 +167,56 @@ struct obs_encoder_info { obs_properties_t (*properties)(const char *locale); /** - * Updates the settings for this encoder + * Updates the settings for this encoder (usually used for things like + * changeing birate while active) * * @param data Data associated with this encoder context * @param settings New settings for this encoder + * @return true if successful, false otherwise */ - void (*update)(void *data, obs_data_t settings); + bool (*update)(void *data, obs_data_t settings); /** * Returns extra data associated with this encoder (usually header) * - * @param data Data associated with this encoder context - * @param extra_data Pointer to receive the extra data - * @param size Pointer to receive the size of the extra data + * @param data Data associated with this encoder context + * @param[out] extra_data Pointer to receive the extra data + * @param[out] size Pointer to receive the size of the extra + * data + * @return true if extra data available, false + * otherwise + */ + bool (*extra_data)(void *data, uint8_t **extra_data, size_t *size); + + /** + * Gets the SEI data, if any + * + * @param data Data associated with this encoder context + * @param[out] sei_data Pointer to receive the SEI data + * @param[out] size Pointer to receive the SEI data size + * @return true if SEI data available, false otherwise + */ + bool (*sei_data)(void *data, uint8_t **sei_data, size_t *size); + + /** + * Returns desired audio format and sample information + * + * @param data Data associated with this encoder context + * @param[out] info Audio format information + * @return true if specific format is desired, false + * otherwise + */ + bool (*audio_info)(void *data, struct audio_convert_info *info); + + /** + * Returns desired video format information + * + * @param data Data associated with this encoder context + * @param[out] info Video format information + * @return true if specific format is desired, false + * otherwise */ - bool (*get_extra_data)(void *data, uint8_t **extra_data, size_t *size); + bool (*video_info)(void *data, struct video_scale_info *info); }; /** diff --git a/libobs/obs-internal.h b/libobs/obs-internal.h index c3f2414ba096e413e45f9e581d6454b7e3aeca88..b0f87fafad6f167ce9a289caded322f33b6b596f 100644 --- a/libobs/obs-internal.h +++ b/libobs/obs-internal.h @@ -276,6 +276,7 @@ struct obs_output { /* encoders */ struct encoder_callback { + bool sent_first_packet; void (*new_packet)(void *param, struct encoder_packet *packet); void *param; }; @@ -286,6 +287,13 @@ struct obs_encoder { struct obs_encoder_info info; obs_data_t settings; - pthread_mutex_t data_callbacks_mutex; - DARRAY(struct encoder_callback) data_callbacks; + uint32_t timebase_num; + uint32_t timebase_den; + + int64_t cur_pts; + + void *output; + + pthread_mutex_t callbacks_mutex; + DARRAY(struct encoder_callback) callbacks; }; diff --git a/libobs/obs-module.c b/libobs/obs-module.c index ee7190398754f298aba44e7ba5f4c9d005af2610..0df14a72ae0988899bc3e7b7c17ad244551fc706 100644 --- a/libobs/obs-module.c +++ b/libobs/obs-module.c @@ -204,7 +204,7 @@ void obs_register_encoder(const struct obs_encoder_info *info) CHECK_REQUIRED_VAL(info, getname, obs_register_encoder); CHECK_REQUIRED_VAL(info, create, obs_register_encoder); CHECK_REQUIRED_VAL(info, destroy, obs_register_encoder); - CHECK_REQUIRED_VAL(info, reset, obs_register_encoder); + CHECK_REQUIRED_VAL(info, start, obs_register_encoder); CHECK_REQUIRED_VAL(info, encode, obs_register_encoder); REGISTER_OBS_DEF(cur_encoder_info_size, obs_encoder_info, diff --git a/libobs/obs-output.c b/libobs/obs-output.c index 12150007599e00f3c58dc1f72788737f249f5237..c6b847beb0bb047dd4af7fa43cebfe63bd7fce41 100644 --- a/libobs/obs-output.c +++ b/libobs/obs-output.c @@ -154,7 +154,7 @@ obs_data_t obs_output_get_settings(obs_output_t output) bool obs_output_canpause(obs_output_t output) { - return (output != NULL) ? output->info.pause != NULL : false; + return output ? (output->info.pause != NULL) : false; } void obs_output_pause(obs_output_t output) @@ -165,10 +165,10 @@ void obs_output_pause(obs_output_t output) signal_handler_t obs_output_signalhandler(obs_output_t output) { - return output->signals; + return output ? output->signals : NULL; } proc_handler_t obs_output_prochandler(obs_output_t output) { - return output->procs; + return output ? output->procs : NULL; } diff --git a/libobs/obs.h b/libobs/obs.h index 5636c752b06c8fea064da053ef18993c19769b3b..67c2dbaf189605c0d2ce66a34c65074d9c2066de 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -686,23 +686,54 @@ EXPORT proc_handler_t obs_output_prochandler(obs_output_t output); /* ------------------------------------------------------------------------- */ /* Encoders */ + EXPORT const char *obs_encoder_getdisplayname(const char *id, const char *locale); -EXPORT obs_encoder_t obs_encoder_create(const char *id, const char *name, - obs_data_t settings); -EXPORT void obs_encoder_destroy(obs_encoder_t encoder); +/** + * Creates a video encoder context + * + * @param id Video encoder ID + * @param name Name to assign to this context + * @param settings Settings + * @param video Video output context to encode data from + * @return The video encoder context, or NULL if failed or not found. + */ +EXPORT obs_encoder_t obs_encoder_create_video(const char *id, const char *name, + obs_data_t settings, video_t video); -EXPORT bool obs_encoder_reset(obs_encoder_t encoder, obs_data_t settings); +/** + * Creates an audio encoder context + * + * @param id Audio Encoder ID + * @param name Name to assign to this context + * @param settings Settings + * @param audio Audio output context to encode data from + * @return The video encoder context, or NULL if failed or not found. + */ +EXPORT obs_encoder_t obs_encoder_create_audio(const char *id, const char *name, + obs_data_t settings, audio_t audio); -EXPORT bool obs_encoder_encode(obs_encoder_t encoder, - const struct encoder_frame *frame, - struct encoder_packet *packet, - bool *received_packet); +/** Destroys an encoder context */ +EXPORT void obs_encoder_destroy(obs_encoder_t encoder); +/** + * Starts encoding. This function can be called more than once, and each + * callback will receive the same encoder data. + * + * @param encoder Encoder context + * @param new_packet Callback that receives encoded packets + * @param param Callback parameter + */ EXPORT bool obs_encoder_start(obs_encoder_t encoder, void (*new_packet)(void *param, struct encoder_packet *packet), void *param); + +/** + * Stops encoding. You must use the same callback/parameter combination that + * was used for obs_encoder_start. Only when the last callback has been + * removed will all encoding stop. + */ EXPORT void obs_encoder_stop(obs_encoder_t encoder, void (*new_packet)(void *param, struct encoder_packet *packet), void *param); @@ -714,13 +745,31 @@ EXPORT obs_data_t obs_encoder_defaults(const char *id); EXPORT obs_properties_t obs_encoder_properties(const char *id, const char *locale); +/** + * Updates the settings of the encoder context. Usually used for changing + * bitrate while active + */ EXPORT void obs_encoder_update(obs_encoder_t encoder, obs_data_t settings); +/** Gets extra data (headers) associated with this context */ EXPORT bool obs_encoder_get_extra_data(obs_encoder_t encoder, uint8_t **extra_data, size_t *size); +/** Returns the current settings for this encoder */ EXPORT obs_data_t obs_encoder_get_settings(obs_encoder_t encoder); +/** + * Returns the video output context used with this encoder, or NULL if not + * a video context + */ +EXPORT video_t obs_encoder_video(obs_encoder_t encoder); + +/** + * Returns the audio output context used with this encoder, or NULL if not + * a audio context + */ +EXPORT audio_t obs_encoder_audio(obs_encoder_t encoder); + /* ------------------------------------------------------------------------- */ /* Stream Services */ diff --git a/libobs/util/bmem.h b/libobs/util/bmem.h index 2ba4233ddd07f862fa09c3d8d1e792bd3ee96554..7b8f0cafb20d14a062e432f27804bffbf0ee7ca4 100644 --- a/libobs/util/bmem.h +++ b/libobs/util/bmem.h @@ -66,7 +66,7 @@ static inline char *bstrdup_n(const char *str, size_t n) static inline wchar_t *bwstrdup_n(const wchar_t *str, size_t n) { wchar_t *dup; - if (!str || !*str) + if (!str || (!*str && n > 0)) return NULL; dup = (wchar_t*)bmemdup(str, (n+1) * sizeof(wchar_t)); diff --git a/libobs/util/dstr.c b/libobs/util/dstr.c index d3c1f35710ae1a6371be50e98f4b456643414fd1..aaceb83342b7e476e9f025af703228bb5a66b656 100644 --- a/libobs/util/dstr.c +++ b/libobs/util/dstr.c @@ -22,8 +22,10 @@ #include <ctype.h> #include <wchar.h> #include <wctype.h> + #include "c99defs.h" #include "dstr.h" +#include "darray.h" #include "bmem.h" #include "utf8.h" #include "lexer.h" @@ -235,6 +237,53 @@ wchar_t *wcsdepad(wchar_t *str) return str; } +char **strlist_split(const char *str, char split_ch, bool include_empty) +{ + const char *cur_str = str; + const char *next_str; + const char *new_str; + DARRAY(char*) list; + + da_init(list); + + if (str) { + next_str = strchr(str, split_ch); + + while (next_str) { + size_t size = next_str - cur_str; + + if (size || include_empty) { + new_str = bstrdup_n(cur_str, size); + da_push_back(list, &new_str); + } + + cur_str = next_str; + next_str = strchr(cur_str, split_ch); + } + + if (*cur_str || include_empty) { + new_str = bstrdup(cur_str); + da_push_back(list, &new_str); + } + } + + new_str = NULL; + da_push_back(list, &new_str); + + return list.array; +} + +void strlist_free(char **strlist) +{ + if (strlist) { + char **temp = strlist; + while (*temp) + bfree(*(temp++)); + + bfree(strlist); + } +} + void dstr_init_strref(struct dstr *dst, const struct strref *src) { dstr_init(dst); diff --git a/libobs/util/dstr.h b/libobs/util/dstr.h index 11f5d033610213ad4fbcfc84a525da2981274781..866ea22682035d31e1a7b5389dd42147365a6f2f 100644 --- a/libobs/util/dstr.h +++ b/libobs/util/dstr.h @@ -51,6 +51,9 @@ EXPORT char *astrstri(char *str, const char *find); EXPORT char *strdepad(char *str); EXPORT wchar_t *wcsdepad(wchar_t *str); +EXPORT char **strlist_split(const char *str, char split_ch, bool include_empty); +EXPORT void strlist_free(char **strlist); + static inline void dstr_init(struct dstr *dst); static inline void dstr_init_move(struct dstr *dst, struct dstr *src); static inline void dstr_init_move_array(struct dstr *dst, char *str); diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 241e4ebfa1571c2b6ae626adf979b146533038af..93df39bbda2e0de39e6438276990f1aebc392898 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -11,5 +11,6 @@ elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") add_subdirectory(linux-pulseaudio) endif() +add_subdirectory(obs-x264) add_subdirectory(obs-ffmpeg) -add_subdirectory(obs-outputs) +# add_subdirectory(obs-outputs) diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-output.c b/plugins/obs-ffmpeg/obs-ffmpeg-output.c index 7d93721e6be94cf74528b18384739a80c2364daa..2dc9192fe3c0996c4a202fc4841760953c166a43 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-output.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg-output.c @@ -513,7 +513,7 @@ static inline void copy_data(AVPicture *pic, const struct video_data *frame, } } -static void receive_video(void *param, const struct video_data *frame) +static void receive_video(void *param, struct video_data *frame) { struct ffmpeg_output *output = param; struct ffmpeg_data *data = &output->ff_data; @@ -527,7 +527,7 @@ static void receive_video(void *param, const struct video_data *frame) data->start_timestamp = frame->timestamp; if (context->pix_fmt != AV_PIX_FMT_YUV420P) - sws_scale(data->swscale, frame->data, + sws_scale(data->swscale, (const uint8_t *const *)frame->data, (const int*)frame->linesize, 0, context->height, data->dst_picture.data, data->dst_picture.linesize); @@ -599,7 +599,7 @@ static inline void encode_audio(struct ffmpeg_output *output, context->sample_fmt, data->samples[0], (int)total_size, 1); if (ret < 0) { - blog(LOG_WARNING, "receive_audio: avcodec_fill_audio_frame " + blog(LOG_WARNING, "encode_audio: avcodec_fill_audio_frame " "failed: %s", av_err2str(ret)); return; } @@ -609,7 +609,7 @@ static inline void encode_audio(struct ffmpeg_output *output, ret = avcodec_encode_audio2(context, &packet, data->aframe, &got_packet); if (ret < 0) { - blog(LOG_WARNING, "receive_audio: Error encoding audio: %s", + blog(LOG_WARNING, "encode_audio: Error encoding audio: %s", av_err2str(ret)); return; } @@ -655,7 +655,7 @@ static bool prepare_audio(struct ffmpeg_data *data, return true; } -static void receive_audio(void *param, const struct audio_data *frame) +static void receive_audio(void *param, struct audio_data *frame) { struct ffmpeg_output *output = param; struct ffmpeg_data *data = &output->ff_data; diff --git a/plugins/obs-outputs/CMakeLists.txt b/plugins/obs-outputs/CMakeLists.txt index 4e2fc447c3b3d4275cbc06bec32ae3039ce2ad55..23dcf9dce72b958d82b9222365bd088a6cac6c5b 100644 --- a/plugins/obs-outputs/CMakeLists.txt +++ b/plugins/obs-outputs/CMakeLists.txt @@ -5,17 +5,10 @@ include_directories(${Libx264_INCLUDE_DIR}) set(obs-outputs_SOURCES obs-outputs.c - obs-x264.c rtmp-stream.c) - -set(obs-outputs_HEADERS - obs-outputs.h - obs-x264.h - rtmp-stream.h) add_library(obs-outputs MODULE - ${obs-outputs_SOURCES} - ${obs-outputs_HEADERS}) + ${obs-outputs_SOURCES}) target_link_libraries(obs-outputs libobs ${Libx264_LIBRARIES}) diff --git a/plugins/obs-outputs/obs-outputs.c b/plugins/obs-outputs/obs-outputs.c index a9dd9b99965f921bd5298a19f7f921f0cbd3576a..bbd183d27b64dfa780cde9631e1f98332d0d6fa1 100644 --- a/plugins/obs-outputs/obs-outputs.c +++ b/plugins/obs-outputs/obs-outputs.c @@ -1,12 +1,10 @@ -#include <string.h> -#include "obs-outputs.h" +#include <obs-module.h> -static const char *outputs[] = {"rtmp_stream"}; +OBS_DECLARE_MODULE() -const char *enum_outputs(size_t idx) -{ - if (idx >= sizeof(outputs)/sizeof(const char*)) - return NULL; - return outputs[idx]; +bool obs_module_load(uint32_t libobs_ver) +{ + UNUSED_PARAMETER(libobs_ver); + return true; } diff --git a/plugins/obs-outputs/obs-outputs.h b/plugins/obs-outputs/obs-outputs.h deleted file mode 100644 index 0601083d23a9d3305cad15c32550f538bfc548dd..0000000000000000000000000000000000000000 --- a/plugins/obs-outputs/obs-outputs.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include <util/c99defs.h> - -EXPORT const char *enum_outputs(size_t idx); diff --git a/plugins/obs-outputs/obs-x264.c b/plugins/obs-outputs/obs-x264.c deleted file mode 100644 index c762d50b4110dfc71b9c806db4fdb6c6b597f884..0000000000000000000000000000000000000000 --- a/plugins/obs-outputs/obs-x264.c +++ /dev/null @@ -1,58 +0,0 @@ -/****************************************************************************** - Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -******************************************************************************/ - -#include "obs-x264.h" - -const char *obs_x264_getname(const char *locale) -{ - /* TODO locale lookup */ - return "x264 (Software)"; -} - -struct obs_x264 *obs_x264_create(obs_data_t settings, obs_encoder_t encoder) -{ - struct obs_x264 *data = bmalloc(sizeof(struct obs_x264)); -} - -void obs_x264_destroy(struct obs_x264 *data) -{ -} - -void obs_x264_update(struct obs_x264 *data, obs_data_t settings) -{ -} - -void obs_x264_reset(struct obs_x264 *data) -{ -} - -int obs_x264_encode(struct obs_x264 *data, struct encoder_packet **packets) -{ -} - -int obs_x264_getheader(struct obs_x264 *data, struct encoder_packet **packets) -{ -} - -void obs_x264_setbitrate(struct obs_x264 *data, uint32_t bitrate, - uint32_t buffersize) -{ -} - -void obs_x264_request_keyframe(struct obs_x264 *data) -{ -} diff --git a/plugins/obs-outputs/obs-x264.h b/plugins/obs-outputs/obs-x264.h deleted file mode 100644 index df527d8735d1bc5ab3a9ccf28b8de2c43470e5c8..0000000000000000000000000000000000000000 --- a/plugins/obs-outputs/obs-x264.h +++ /dev/null @@ -1,49 +0,0 @@ -/****************************************************************************** - Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -******************************************************************************/ - -#pragma once - -#include <util/c99defs.h> -#include <obs.h> -#include <x264.h> - -struct obs_x264 { - obs_encoder_t encoder; - - x264_param_t params; - x264_t *context; - x264_picture_t pic_out; -}; - -EXPORT const char *obs_x264_getname(const char *locale); - -EXPORT struct obs_x264 *obs_x264_create(obs_data_t settings, - obs_encoder_t encoder); -EXPORT void obs_x264_destroy(struct obs_x264 *data); - -EXPORT void obs_x264_update(struct obs_x264 *data, obs_data_t settings); - -EXPORT void obs_x264_reset(struct obs_x264 *data); - -EXPORT int obs_x264_encode(struct obs_x264 *data, - struct encoder_packet **packets); -EXPORT int obs_x264_getheader(struct obs_x264 *data, - struct encoder_packet **packets); - -EXPORT void obs_x264_setbitrate(struct obs_x264 *data, uint32_t bitrate, - uint32_t buffersize); -EXPORT void obs_x264_request_keyframe(struct obs_x264 *data); diff --git a/plugins/obs-outputs/rtmp-stream.c b/plugins/obs-outputs/rtmp-stream.c index 4e5ada48287e51ab9fdc7f4e9b80e93b0d879f01..ad7481d3dc29439d85cdb80a589adf5559df6427 100644 --- a/plugins/obs-outputs/rtmp-stream.c +++ b/plugins/obs-outputs/rtmp-stream.c @@ -15,36 +15,45 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ -#include "rtmp-stream.h" +#include <obs.h> -const char *rtmp_stream_getname(const char *locale) +struct rtmp_stream { + obs_output_t output; + obs_encoder_t video_encoder; + obs_encoder_t audio_encoder; + obs_service_t service; + + bool active; +}; + +static const char *rtmp_stream_getname(const char *locale) { /* TODO: locale stuff */ return "RTMP Stream"; } -void *rtmp_stream_create(obs_data_t settings, obs_output_t output) +static void *rtmp_stream_create(obs_data_t settings, obs_output_t output) { struct rtmp_stream *stream = bmalloc(sizeof(struct rtmp_stream)); memset(stream, 0, sizeof(struct rtmp_stream)); } -void rtmp_stream_destroy(struct rtmp_stream *stream) +static void rtmp_stream_destroy(struct rtmp_stream *stream) { } -void rtmp_stream_update(struct rtmp_stream *stream, obs_data_t settings) +static void rtmp_stream_update(struct rtmp_stream *stream, obs_data_t settings) { } -bool rtmp_stream_start(struct rtmp_stream *stream) +static bool rtmp_stream_start(struct rtmp_stream *stream) { } -void rtmp_stream_stop(struct rtmp_stream *stream) +static void rtmp_stream_stop(struct rtmp_stream *stream) { } -bool rtmp_stream_active(struct rtmp_stream *stream) +static bool rtmp_stream_active(struct rtmp_stream *stream) { } diff --git a/plugins/obs-outputs/rtmp-stream.h b/plugins/obs-outputs/rtmp-stream.h deleted file mode 100644 index 79f7546a5c402bd540465a394d5c2095cdf8f912..0000000000000000000000000000000000000000 --- a/plugins/obs-outputs/rtmp-stream.h +++ /dev/null @@ -1,38 +0,0 @@ -/****************************************************************************** - Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -******************************************************************************/ - -#pragma once - -#include <util/c99defs.h> -#include <obs.h> - -struct rtmp_stream { - obs_output_t output; - obs_encoder_t video_encoder; - obs_encoder_t audio_encoder; - obs_service_t service; - - bool active; -}; - -EXPORT const char *rtmp_stream_getname(const char *locale); -EXPORT void *rtmp_stream_create(obs_data_t settings, obs_output_t output); -EXPORT void rtmp_stream_destroy(struct rtmp_stream *stream); -EXPORT void rtmp_stream_update(struct rtmp_stream *stream, obs_data_t settings); -EXPORT bool rtmp_stream_start(struct rtmp_stream *stream); -EXPORT void rtmp_stream_stop(struct rtmp_stream *stream); -EXPORT bool rtmp_stream_active(struct rtmp_stream *stream); diff --git a/plugins/obs-x264/CMakeLists.txt b/plugins/obs-x264/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c4d655a80238705f3e744bbbaef607328830a733 --- /dev/null +++ b/plugins/obs-x264/CMakeLists.txt @@ -0,0 +1,19 @@ +project(obs-x264) + +find_package(Libx264 REQUIRED) +include_directories(${Libx264_INCLUDE_DIR}) +add_definitions(${Libx264_DEFINITIONS}) + +set(obs-x264_SOURCES + obs-x264.c + obs-x264-plugin-main.c) + +add_library(obs-x264 MODULE + ${obs-x264_SOURCES}) +target_link_libraries(obs-x264 + libobs + ${Libx264_LIBRARIES}) + +install_obs_plugin(obs-x264) + +obs_fixup_install_target(obs-x264 PATH ${Libx264_LIBRARIES}) diff --git a/plugins/obs-x264/obs-x264-plugin-main.c b/plugins/obs-x264/obs-x264-plugin-main.c new file mode 100644 index 0000000000000000000000000000000000000000..4086afa327f6d04b9637b04e4d079ceb2b87298d --- /dev/null +++ b/plugins/obs-x264/obs-x264-plugin-main.c @@ -0,0 +1,13 @@ +#include <obs-module.h> + +OBS_DECLARE_MODULE() + +extern struct obs_encoder_info obs_x264_encoder; + +bool obs_module_load(uint32_t libobs_ver) +{ + obs_register_encoder(&obs_x264_encoder); + + UNUSED_PARAMETER(libobs_ver); + return true; +} diff --git a/plugins/obs-x264/obs-x264.c b/plugins/obs-x264/obs-x264.c new file mode 100644 index 0000000000000000000000000000000000000000..fb284e3b77af9f8c7c96ae9e89f4cad17c95713d --- /dev/null +++ b/plugins/obs-x264/obs-x264.c @@ -0,0 +1,506 @@ +/****************************************************************************** + Copyright (C) 2014 by Hugh Bailey <obs.jim@gmail.com> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +******************************************************************************/ + +#include <util/dstr.h> +#include <util/darray.h> +#include <obs.h> +#include <x264.h> + +struct obs_x264 { + obs_encoder_t encoder; + + x264_param_t params; + x264_t *context; + + DARRAY(uint8_t) packet_data; + + uint8_t *extra_data; + uint8_t *sei; + + size_t extra_data_size; + size_t sei_size; +}; + + +/* ------------------------------------------------------------------------- */ + +static const char *obs_x264_getname(const char *locale) +{ + /* TODO locale lookup */ + UNUSED_PARAMETER(locale); + return "x264"; +} + +static void obs_x264_stop(void *data); + +static void obs_x264_destroy(void *data) +{ + struct obs_x264 *obsx264 = data; + + if (obsx264) { + obs_x264_stop(obsx264); + da_free(obsx264->packet_data); + bfree(obsx264); + } +} + +static void obs_x264_defaults(obs_data_t settings) +{ + obs_data_set_default_int (settings, "bitrate", 1000); + obs_data_set_default_int (settings, "buffer_size", 1000); + obs_data_set_default_int (settings, "keyint_sec", 0); + + obs_data_set_default_string(settings, "preset", "veryfast"); + obs_data_set_default_string(settings, "profile", ""); + obs_data_set_default_string(settings, "tune", ""); + obs_data_set_default_string(settings, "x264opts", ""); +} + +static inline void add_strings(obs_property_t list, const char *const *strings) +{ + while (*strings) { + obs_property_list_add_item(list, *strings, *strings); + strings++; + } +} + +static obs_properties_t obs_x264_props(const char *locale) +{ + UNUSED_PARAMETER(locale); + /* TODO: locale */ + + obs_properties_t props = obs_properties_create(); + obs_property_t list; + + obs_properties_add_int(props, "bitrate", "Bitrate", 50, 100000, 1); + obs_properties_add_int(props, "buffer_size", "Buffer Size", 50, 100000, + 1); + obs_properties_add_int(props, + "keyint_sec", "Keyframe interval (seconds, 0=auto)", + 0, 20, 1); + + list = obs_properties_add_list(props, + "preset", "CPU Usage Preset (encoder speed)", + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); + add_strings(list, x264_preset_names); + + list = obs_properties_add_list(props, "profile", "Profile", + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); + obs_property_list_add_item(list, "baseline", "baseline"); + obs_property_list_add_item(list, "main", "main"); + obs_property_list_add_item(list, "high", "high"); + + list = obs_properties_add_list(props, "tune", "Tune", + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); + add_strings(list, x264_tune_names); + + obs_properties_add_text(props, "x264opts", + "x264 encoder options (separated by ':')"); + + return props; +} + +static bool getparam(const char *param, char **name, const char **value) +{ + const char *assign; + + if (!param || !*param || (*param == '=')) + return false; + + assign = strchr(param, '='); + if (!assign || !*assign || !*(assign+1)) + return false; + + *name = bstrdup_n(param, assign-param); + *value = assign+1; + return true; +} + +static void override_base_param(const char *param, + char **preset, char **profile, char **tune) +{ + char *name; + const char *val; + + if (getparam(param, &name, &val)) { + if (astrcmpi(name, "preset") == 0) { + bfree(*preset); + *preset = bstrdup(val); + + } else if (astrcmpi(name, "profile") == 0) { + bfree(*profile); + *profile = bstrdup(val); + + } else if (astrcmpi(name, "tune") == 0) { + bfree(*tune); + *tune = bstrdup(val); + } + + bfree(name); + } +} + +static inline void override_base_params(char **params, + char **preset, char **profile, char **tune) +{ + while (*params) + override_base_param(*(params++), preset, profile, tune); +} + +static inline void set_param(struct obs_x264 *obsx264, const char *param) +{ + char *name; + const char *val; + + if (getparam(param, &name, &val)) { + if (x264_param_parse(&obsx264->params, name, val) != 0) + blog(LOG_WARNING, "x264 param: %s failed", param); + + bfree(name); + } +} + +static inline void apply_x264_profile(struct obs_x264 *obsx264, + const char *profile) +{ + if (!*profile) profile = NULL; + + if (!obsx264->context && profile) { + int ret = x264_param_apply_profile(&obsx264->params, profile); + if (ret != 0) + blog(LOG_WARNING, "Failed to set x264 " + "profile '%s'", profile); + } +} + +static bool reset_x264_params(struct obs_x264 *obsx264, + const char *preset, const char *tune) +{ + if (!*preset) preset = NULL; + if (!*tune) tune = NULL; + + return x264_param_default_preset(&obsx264->params, preset, tune) == 0; +} + +static void log_x264(void *param, int level, const char *format, va_list args) +{ + blogva(LOG_INFO, format, args); + + UNUSED_PARAMETER(param); + UNUSED_PARAMETER(level); +} + +static void update_params(struct obs_x264 *obsx264, obs_data_t settings, + char **params) +{ + video_t video = obs_encoder_video(obsx264->encoder); + const struct video_output_info *voi = video_output_getinfo(video); + + int bitrate = (int)obs_data_getint(settings, "bitrate"); + int buffer_size = (int)obs_data_getint(settings, "buffer_size"); + int keyint_sec = (int)obs_data_getint(settings, "keyint_sec"); + + if (keyint_sec) + obsx264->params.i_keyint_max = + keyint_sec * voi->fps_num / voi->fps_den; + + obsx264->params.rc.i_vbv_max_bitrate = bitrate; + obsx264->params.rc.i_vbv_buffer_size = buffer_size; + obsx264->params.rc.i_bitrate = bitrate; + obsx264->params.i_width = voi->width; + obsx264->params.i_height = voi->height; + obsx264->params.i_fps_num = voi->fps_num; + obsx264->params.i_fps_den = voi->fps_den; + obsx264->params.i_timebase_num = voi->fps_den; + obsx264->params.i_timebase_den = voi->fps_num; + obsx264->params.pf_log = log_x264; + obsx264->params.i_log_level = X264_LOG_WARNING; + + if (voi->format == VIDEO_FORMAT_NV12) + obsx264->params.i_csp = X264_CSP_NV12; + else if (voi->format == VIDEO_FORMAT_I420) + obsx264->params.i_csp = X264_CSP_I420; + else + obsx264->params.i_csp = X264_CSP_NV12; + + while (*params) + set_param(obsx264, *(params++)); +} + +static bool update_settings(struct obs_x264 *obsx264, obs_data_t settings) +{ + char *preset = bstrdup(obs_data_getstring(settings, "preset")); + char *profile = bstrdup(obs_data_getstring(settings, "profile")); + char *tune = bstrdup(obs_data_getstring(settings, "tune")); + const char *opts = obs_data_getstring(settings, "x264opts"); + + char **paramlist; + bool success = true; + + paramlist = strlist_split(opts, ':', false); + + if (!obsx264->context) { + override_base_params(paramlist, &preset, &tune, &profile); + success = reset_x264_params(obsx264, preset, tune); + } + + if (success) { + update_params(obsx264, settings, paramlist); + + if (!obsx264->context) + apply_x264_profile(obsx264, profile); + } + + strlist_free(paramlist); + bfree(preset); + bfree(profile); + bfree(tune); + + return success; +} + +static bool obs_x264_update(void *data, obs_data_t settings) +{ + struct obs_x264 *obsx264 = data; + bool success = update_settings(obsx264, settings); + int ret; + + if (success) { + ret = x264_encoder_reconfig(obsx264->context, &obsx264->params); + if (ret != 0) + blog(LOG_WARNING, "Failed to reconfigure x264: %d", + ret); + return ret == 0; + } + + return false; +} + +static void load_headers(struct obs_x264 *obsx264) +{ + x264_nal_t *nals; + int nal_count; + DARRAY(uint8_t) header; + DARRAY(uint8_t) sei; + + da_init(header); + da_init(sei); + + x264_encoder_headers(obsx264->context, &nals, &nal_count); + + for (int i = 0; i < nal_count; i++) { + x264_nal_t *nal = nals+i; + + if (nal->i_type == NAL_SEI) + da_push_back_array(sei, nal->p_payload, nal->i_payload); + else + da_push_back_array(header, nal->p_payload, + nal->i_payload); + } + + obsx264->extra_data = header.array; + obsx264->extra_data_size = header.num; + obsx264->sei = sei.array; + obsx264->sei_size = sei.num; +} + +static bool obs_x264_start(void *data, obs_data_t settings) +{ + struct obs_x264 *obsx264 = data; + + assert(obsx264->context == NULL); + obs_x264_stop(data); + + if (update_settings(obsx264, settings)) { + obsx264->context = x264_encoder_open(&obsx264->params); + + if (obsx264->context == NULL) + blog(LOG_WARNING, "x264 failed to load"); + else + load_headers(obsx264); + } else { + blog(LOG_WARNING, "bad settings specified for x264"); + } + + return obsx264->context != NULL; +} + +static void obs_x264_stop(void *data) +{ + struct obs_x264 *obsx264 = data; + + if (obsx264->context) { + x264_encoder_close(obsx264->context); + bfree(obsx264->sei); + bfree(obsx264->extra_data); + + obsx264->context = NULL; + obsx264->sei = NULL; + obsx264->extra_data = NULL; + } +} + +static void *obs_x264_create(obs_data_t settings, obs_encoder_t encoder) +{ + struct obs_x264 *data = bzalloc(sizeof(struct obs_x264)); + data->encoder = encoder; + + obs_x264_defaults(settings); + return data; +} + +static inline int drop_priority(int priority) +{ + switch (priority) { + case NAL_PRIORITY_DISPOSABLE: return NAL_PRIORITY_DISPOSABLE; + case NAL_PRIORITY_LOW: return NAL_PRIORITY_LOW; + case NAL_PRIORITY_HIGH: return NAL_PRIORITY_HIGHEST; + case NAL_PRIORITY_HIGHEST: return NAL_PRIORITY_HIGHEST; + } + + return NAL_PRIORITY_HIGHEST; +} + +static void parse_packet(struct obs_x264 *obsx264, + struct encoder_packet *packet, x264_nal_t *nals, + int nal_count, x264_picture_t *pic_out) +{ + if (!nal_count) return; + + da_resize(obsx264->packet_data, 0); + + for (int i = 0; i < nal_count; i++) { + x264_nal_t *nal = nals+i; + da_push_back_array(obsx264->packet_data, nal->p_payload, + nal->i_payload); + } + + packet->data = obsx264->packet_data.array; + packet->size = obsx264->packet_data.num; + packet->type = OBS_ENCODER_VIDEO; + packet->pts = pic_out->i_pts; + packet->dts = pic_out->i_dts; + packet->keyframe = nals[0].i_type == NAL_SLICE_IDR; + packet->priority = nals[0].i_ref_idc; + packet->drop_priority = drop_priority(nals[0].i_ref_idc); +} + +static inline void init_pic_data(struct obs_x264 *obsx264, x264_picture_t *pic, + struct encoder_frame *frame) +{ + x264_picture_init(pic); + + pic->i_pts = frame->pts; + pic->img.i_csp = obsx264->params.i_csp; + + if (obsx264->params.i_csp == X264_CSP_NV12) + pic->img.i_plane = 2; + else if (obsx264->params.i_csp == X264_CSP_I420) + pic->img.i_plane = 3; + + for (int i = 0; i < pic->img.i_plane; i++) { + pic->img.i_stride[i] = (int)frame->linesize[i]; + pic->img.plane[i] = frame->data[i]; + } +} + +static bool obs_x264_encode(void *data, struct encoder_frame *frame, + struct encoder_packet *packet, bool *received_packet) +{ + struct obs_x264 *obsx264 = data; + x264_nal_t *nals; + int nal_count; + int ret; + x264_picture_t pic, pic_out; + + if (!frame || !packet || !received_packet) + return false; + + init_pic_data(obsx264, &pic, frame); + + ret = x264_encoder_encode(obsx264->context, &nals, &nal_count, &pic, + &pic_out); + if (ret < 0) { + blog(LOG_WARNING, "x264 encode failed"); + return false; + } + + *received_packet = (nal_count != 0); + parse_packet(obsx264, packet, nals, nal_count, &pic_out); + + return true; +} + +static bool obs_x264_extra_data(void *data, uint8_t **extra_data, size_t *size) +{ + struct obs_x264 *obsx264 = data; + + if (!obsx264->context) + return false; + + *extra_data = obsx264->extra_data; + *size = obsx264->extra_data_size; + return true; +} + +static bool obs_x264_sei(void *data, uint8_t **sei, size_t *size) +{ + struct obs_x264 *obsx264 = data; + + if (!obsx264->context) + return false; + + *sei = obsx264->sei; + *size = obsx264->sei_size; + return true; +} + +static bool obs_x264_video_info(void *data, struct video_scale_info *info) +{ + struct obs_x264 *obsx264 = data; + video_t video = obs_encoder_video(obsx264->encoder); + const struct video_output_info *vid_info = video_output_getinfo(video); + + if (vid_info->format == VIDEO_FORMAT_I420 || + vid_info->format == VIDEO_FORMAT_NV12) + return false; + + info->format = VIDEO_FORMAT_NV12; + info->width = vid_info->width; + info->height = vid_info->height; + info->range = VIDEO_RANGE_DEFAULT; + info->colorspace = VIDEO_CS_DEFAULT; + return true; +} + +struct obs_encoder_info obs_x264_encoder = { + .id = "obs_x264", + .type = OBS_ENCODER_VIDEO, + .codec = "h264", + .getname = obs_x264_getname, + .create = obs_x264_create, + .destroy = obs_x264_destroy, + .start = obs_x264_start, + .stop = obs_x264_stop, + .encode = obs_x264_encode, + .properties = obs_x264_props, + .defaults = obs_x264_defaults, + .update = obs_x264_update, + .extra_data = obs_x264_extra_data, + .sei_data = obs_x264_sei, + .video_info = obs_x264_video_info +}; diff --git a/vs/2013/OBS.sln b/vs/2013/OBS.sln index 1fa95e3f1be44c2d01f7383dee3c92b0f627c305..f5ab29186ef7046a548a25150e1231cca1758962 100644 --- a/vs/2013/OBS.sln +++ b/vs/2013/OBS.sln @@ -43,102 +43,162 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "win-wasapi", "win-wasapi\wi EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "win-capture", "win-capture\win-capture.vcxproj", "{AB83E5F0-D76E-45AB-A4C9-4711B1BE6916}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "obs-x264", "obs-x264\obs-x264.vcxproj", "{1798CAF2-531A-4E0E-A722-29F4B1B5D49F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Mixed Platforms = Debug|Mixed Platforms Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 + Release|Mixed Platforms = Release|Mixed Platforms Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Debug|Win32.ActiveCfg = Debug|Win32 {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Debug|Win32.Build.0 = Debug|Win32 {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Debug|x64.ActiveCfg = Debug|x64 {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Debug|x64.Build.0 = Debug|x64 + {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Release|Mixed Platforms.Build.0 = Release|Win32 {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Release|Win32.ActiveCfg = Release|Win32 {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Release|Win32.Build.0 = Release|Win32 {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Release|x64.ActiveCfg = Release|x64 {6F1AC2AE-6424-401A-AF9F-A771E6BEE026}.Release|x64.Build.0 = Release|x64 + {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Debug|Win32.ActiveCfg = Debug|Win32 {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Debug|Win32.Build.0 = Debug|Win32 {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Debug|x64.ActiveCfg = Debug|x64 {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Debug|x64.Build.0 = Debug|x64 + {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Release|Mixed Platforms.Build.0 = Release|Win32 {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Release|Win32.ActiveCfg = Release|Win32 {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Release|Win32.Build.0 = Release|Win32 {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Release|x64.ActiveCfg = Release|x64 {68A84F9A-5B89-4E7D-8183-87FEA5DC65F6}.Release|x64.Build.0 = Release|x64 + {E11367B7-20CC-4741-B8E0-C20E85302A40}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {E11367B7-20CC-4741-B8E0-C20E85302A40}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {E11367B7-20CC-4741-B8E0-C20E85302A40}.Debug|Win32.ActiveCfg = Debug|Win32 {E11367B7-20CC-4741-B8E0-C20E85302A40}.Debug|Win32.Build.0 = Debug|Win32 {E11367B7-20CC-4741-B8E0-C20E85302A40}.Debug|x64.ActiveCfg = Debug|x64 {E11367B7-20CC-4741-B8E0-C20E85302A40}.Debug|x64.Build.0 = Debug|x64 + {E11367B7-20CC-4741-B8E0-C20E85302A40}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {E11367B7-20CC-4741-B8E0-C20E85302A40}.Release|Mixed Platforms.Build.0 = Release|Win32 {E11367B7-20CC-4741-B8E0-C20E85302A40}.Release|Win32.ActiveCfg = Release|Win32 {E11367B7-20CC-4741-B8E0-C20E85302A40}.Release|Win32.Build.0 = Release|Win32 {E11367B7-20CC-4741-B8E0-C20E85302A40}.Release|x64.ActiveCfg = Release|x64 {E11367B7-20CC-4741-B8E0-C20E85302A40}.Release|x64.Build.0 = Release|x64 + {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Debug|Win32.ActiveCfg = Debug|Win32 {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Debug|Win32.Build.0 = Debug|Win32 {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Debug|x64.ActiveCfg = Debug|x64 {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Debug|x64.Build.0 = Debug|x64 + {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Release|Mixed Platforms.Build.0 = Release|Win32 {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Release|Win32.ActiveCfg = Release|Win32 {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Release|Win32.Build.0 = Release|Win32 {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Release|x64.ActiveCfg = Release|x64 {82C863C3-74C8-43BE-90CF-755EE698F2E8}.Release|x64.Build.0 = Release|x64 + {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Debug|Win32.ActiveCfg = Debug|Win32 {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Debug|Win32.Build.0 = Debug|Win32 {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Debug|x64.ActiveCfg = Debug|x64 {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Debug|x64.Build.0 = Debug|x64 + {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Release|Mixed Platforms.Build.0 = Release|Win32 {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Release|Win32.ActiveCfg = Release|Win32 {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Release|Win32.Build.0 = Release|Win32 {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Release|x64.ActiveCfg = Release|x64 {760ECBBC-EA7C-464A-B60E-945A0BB1B100}.Release|x64.Build.0 = Release|x64 + {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Debug|Win32.ActiveCfg = Debug|Win32 {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Debug|Win32.Build.0 = Debug|Win32 {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Debug|x64.ActiveCfg = Debug|x64 {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Debug|x64.Build.0 = Debug|x64 + {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Release|Mixed Platforms.Build.0 = Release|Win32 {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Release|Win32.ActiveCfg = Release|Win32 {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Release|Win32.Build.0 = Release|Win32 {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Release|x64.ActiveCfg = Release|x64 {B6EAE19B-79BF-4F7C-9E66-976D14B9DC6C}.Release|x64.Build.0 = Release|x64 + {76226D20-1972-4789-A595-EDACC7A76DC3}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {76226D20-1972-4789-A595-EDACC7A76DC3}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {76226D20-1972-4789-A595-EDACC7A76DC3}.Debug|Win32.ActiveCfg = Debug|Win32 {76226D20-1972-4789-A595-EDACC7A76DC3}.Debug|Win32.Build.0 = Debug|Win32 {76226D20-1972-4789-A595-EDACC7A76DC3}.Debug|x64.ActiveCfg = Debug|Win32 {76226D20-1972-4789-A595-EDACC7A76DC3}.Debug|x64.Build.0 = Debug|Win32 + {76226D20-1972-4789-A595-EDACC7A76DC3}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {76226D20-1972-4789-A595-EDACC7A76DC3}.Release|Mixed Platforms.Build.0 = Release|Win32 {76226D20-1972-4789-A595-EDACC7A76DC3}.Release|Win32.ActiveCfg = Release|Win32 {76226D20-1972-4789-A595-EDACC7A76DC3}.Release|Win32.Build.0 = Release|Win32 {76226D20-1972-4789-A595-EDACC7A76DC3}.Release|x64.ActiveCfg = Release|Win32 {76226D20-1972-4789-A595-EDACC7A76DC3}.Release|x64.Build.0 = Release|Win32 + {36970254-B1E5-4BE6-A561-301B6E7CDCE3}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {36970254-B1E5-4BE6-A561-301B6E7CDCE3}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {36970254-B1E5-4BE6-A561-301B6E7CDCE3}.Debug|Win32.ActiveCfg = Debug|Win32 {36970254-B1E5-4BE6-A561-301B6E7CDCE3}.Debug|Win32.Build.0 = Debug|Win32 {36970254-B1E5-4BE6-A561-301B6E7CDCE3}.Debug|x64.ActiveCfg = Debug|x64 {36970254-B1E5-4BE6-A561-301B6E7CDCE3}.Debug|x64.Build.0 = Debug|x64 + {36970254-B1E5-4BE6-A561-301B6E7CDCE3}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {36970254-B1E5-4BE6-A561-301B6E7CDCE3}.Release|Mixed Platforms.Build.0 = Release|Win32 {36970254-B1E5-4BE6-A561-301B6E7CDCE3}.Release|Win32.ActiveCfg = Release|Win32 {36970254-B1E5-4BE6-A561-301B6E7CDCE3}.Release|Win32.Build.0 = Release|Win32 {36970254-B1E5-4BE6-A561-301B6E7CDCE3}.Release|x64.ActiveCfg = Release|x64 {36970254-B1E5-4BE6-A561-301B6E7CDCE3}.Release|x64.Build.0 = Release|x64 + {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|Win32.ActiveCfg = Debug|Win32 {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|Win32.Build.0 = Debug|Win32 {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|x64.ActiveCfg = Debug|x64 {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|x64.Build.0 = Debug|x64 + {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|Mixed Platforms.Build.0 = Release|Win32 {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|Win32.ActiveCfg = Release|Win32 {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|Win32.Build.0 = Release|Win32 {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.ActiveCfg = Release|x64 {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.Build.0 = Release|x64 + {A3D24C9D-669D-4DDF-91BA-152D7DDD7C04}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {A3D24C9D-669D-4DDF-91BA-152D7DDD7C04}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {A3D24C9D-669D-4DDF-91BA-152D7DDD7C04}.Debug|Win32.ActiveCfg = Debug|Win32 {A3D24C9D-669D-4DDF-91BA-152D7DDD7C04}.Debug|Win32.Build.0 = Debug|Win32 {A3D24C9D-669D-4DDF-91BA-152D7DDD7C04}.Debug|x64.ActiveCfg = Debug|x64 {A3D24C9D-669D-4DDF-91BA-152D7DDD7C04}.Debug|x64.Build.0 = Debug|x64 + {A3D24C9D-669D-4DDF-91BA-152D7DDD7C04}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {A3D24C9D-669D-4DDF-91BA-152D7DDD7C04}.Release|Mixed Platforms.Build.0 = Release|Win32 {A3D24C9D-669D-4DDF-91BA-152D7DDD7C04}.Release|Win32.ActiveCfg = Release|Win32 {A3D24C9D-669D-4DDF-91BA-152D7DDD7C04}.Release|Win32.Build.0 = Release|Win32 {A3D24C9D-669D-4DDF-91BA-152D7DDD7C04}.Release|x64.ActiveCfg = Release|x64 {A3D24C9D-669D-4DDF-91BA-152D7DDD7C04}.Release|x64.Build.0 = Release|x64 + {AB83E5F0-D76E-45AB-A4C9-4711B1BE6916}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {AB83E5F0-D76E-45AB-A4C9-4711B1BE6916}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {AB83E5F0-D76E-45AB-A4C9-4711B1BE6916}.Debug|Win32.ActiveCfg = Debug|Win32 {AB83E5F0-D76E-45AB-A4C9-4711B1BE6916}.Debug|Win32.Build.0 = Debug|Win32 {AB83E5F0-D76E-45AB-A4C9-4711B1BE6916}.Debug|x64.ActiveCfg = Debug|x64 {AB83E5F0-D76E-45AB-A4C9-4711B1BE6916}.Debug|x64.Build.0 = Debug|x64 + {AB83E5F0-D76E-45AB-A4C9-4711B1BE6916}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {AB83E5F0-D76E-45AB-A4C9-4711B1BE6916}.Release|Mixed Platforms.Build.0 = Release|Win32 {AB83E5F0-D76E-45AB-A4C9-4711B1BE6916}.Release|Win32.ActiveCfg = Release|Win32 {AB83E5F0-D76E-45AB-A4C9-4711B1BE6916}.Release|Win32.Build.0 = Release|Win32 {AB83E5F0-D76E-45AB-A4C9-4711B1BE6916}.Release|x64.ActiveCfg = Release|x64 {AB83E5F0-D76E-45AB-A4C9-4711B1BE6916}.Release|x64.Build.0 = Release|x64 + {1798CAF2-531A-4E0E-A722-29F4B1B5D49F}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {1798CAF2-531A-4E0E-A722-29F4B1B5D49F}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {1798CAF2-531A-4E0E-A722-29F4B1B5D49F}.Debug|Win32.ActiveCfg = Debug|Win32 + {1798CAF2-531A-4E0E-A722-29F4B1B5D49F}.Debug|Win32.Build.0 = Debug|Win32 + {1798CAF2-531A-4E0E-A722-29F4B1B5D49F}.Debug|x64.ActiveCfg = Debug|x64 + {1798CAF2-531A-4E0E-A722-29F4B1B5D49F}.Debug|x64.Build.0 = Debug|x64 + {1798CAF2-531A-4E0E-A722-29F4B1B5D49F}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {1798CAF2-531A-4E0E-A722-29F4B1B5D49F}.Release|Mixed Platforms.Build.0 = Release|Win32 + {1798CAF2-531A-4E0E-A722-29F4B1B5D49F}.Release|Win32.ActiveCfg = Release|Win32 + {1798CAF2-531A-4E0E-A722-29F4B1B5D49F}.Release|Win32.Build.0 = Release|Win32 + {1798CAF2-531A-4E0E-A722-29F4B1B5D49F}.Release|x64.ActiveCfg = Release|x64 + {1798CAF2-531A-4E0E-A722-29F4B1B5D49F}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/vs/2013/obs-x264/obs-x264.vcxproj b/vs/2013/obs-x264/obs-x264.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..90740e381be8c70d0dd6453c1dd0cc8c38038865 --- /dev/null +++ b/vs/2013/obs-x264/obs-x264.vcxproj @@ -0,0 +1,180 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{1798CAF2-531A-4E0E-A722-29F4B1B5D49F}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>obsx264</RootNamespace> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v120</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v120</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v120</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v120</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>true</LinkIncremental> + <IncludePath>$(x264Path);$(IncludePath)</IncludePath> + <LibraryPath>$(x264Path)\lib32;$(x264Path);$(LibraryPath)</LibraryPath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>true</LinkIncremental> + <IncludePath>$(x264Path);$(IncludePath)</IncludePath> + <LibraryPath>$(x264Path)\lib64;$(x264Path);$(LibraryPath)</LibraryPath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + <IncludePath>$(x264Path);$(IncludePath)</IncludePath> + <LibraryPath>$(x264Path)\lib32;$(x264Path);$(LibraryPath)</LibraryPath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + <IncludePath>$(x264Path);$(IncludePath)</IncludePath> + <LibraryPath>$(x264Path)\lib64;$(x264Path);$(LibraryPath)</LibraryPath> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;OBSX264_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>../../../libobs</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>x264.lib;libobs.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + <PostBuildEvent> + <Command>copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/obs-plugins/32bit/$(TargetName)$(TargetExt)"</Command> + </PostBuildEvent> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;OBSX264_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>../../../libobs</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>x264.lib;libobs.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + <PostBuildEvent> + <Command>copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/obs-plugins/64bit/$(TargetName)$(TargetExt)"</Command> + </PostBuildEvent> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <PrecompiledHeader> + </PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;OBSX264_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>../../../libobs</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>x264.lib;libobs.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + <PostBuildEvent> + <Command>copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/obs-plugins/32bit/$(TargetName)$(TargetExt)"</Command> + </PostBuildEvent> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <PrecompiledHeader> + </PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;OBSX264_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>../../../libobs</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>x264.lib;libobs.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + <PostBuildEvent> + <Command>copy "$(OutDir)$(TargetName)$(TargetExt)" "../../../build/obs-plugins/64bit/$(TargetName)$(TargetExt)"</Command> + </PostBuildEvent> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="..\..\..\plugins\obs-x264\obs-x264-plugin-main.c" /> + <ClCompile Include="..\..\..\plugins\obs-x264\obs-x264.c" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file diff --git a/vs/2013/obs-x264/obs-x264.vcxproj.filters b/vs/2013/obs-x264/obs-x264.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..16cdf1a1c91bec54d5daebc05dd3df19d40cd15f --- /dev/null +++ b/vs/2013/obs-x264/obs-x264.vcxproj.filters @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\..\..\plugins\obs-x264\obs-x264.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\..\plugins\obs-x264\obs-x264-plugin-main.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project> \ No newline at end of file