|
|
|
|
@ -303,11 +303,16 @@ static void media_process(void *arg) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Attach/detach — обязательная граница lifetime ядра. */ |
|
|
|
|
void android_stream_attach(struct UTUN_INSTANCE *inst) { |
|
|
|
|
int android_stream_attach(struct UTUN_INSTANCE *inst) { |
|
|
|
|
pthread_mutex_lock(&media_lock); |
|
|
|
|
if (!inst || !inst->stream || (media_inst && media_inst != inst)) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "Android stream attach rejected inst=%p owner=%p", (void *)inst, (void *)media_inst); |
|
|
|
|
pthread_mutex_unlock(&media_lock); return -1; |
|
|
|
|
} |
|
|
|
|
media_inst = inst; stream_set_event_callback(inst, media_event, NULL); |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "Android stream bridge attached"); |
|
|
|
|
pthread_mutex_unlock(&media_lock); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
void android_stream_detach(struct UTUN_INSTANCE *inst) { |
|
|
|
|
pthread_mutex_lock(&media_lock); |
|
|
|
|
@ -352,7 +357,11 @@ int android_stream_feed(uint64_t id, int video, uint64_t pts, int key, const uin
|
|
|
|
|
} |
|
|
|
|
pthread_mutex_lock(&media_lock); |
|
|
|
|
int result = -1, track = video ? 0 : 1; |
|
|
|
|
if (!media_inst || publisher.id != id || publisher.stopping || publisher.finished) goto done; |
|
|
|
|
if (!media_inst || publisher.id != id || publisher.stopping || publisher.finished) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_STREAM, "Android stream feed rejected id=%llu owner=%llu attached=%d stopping=%d finished=%d", |
|
|
|
|
(unsigned long long)id, (unsigned long long)publisher.id, media_inst != NULL, publisher.stopping, publisher.finished); |
|
|
|
|
goto done; |
|
|
|
|
} |
|
|
|
|
if ((!video && !publisher.format.audio_codec) || (publisher.seen[track] && pts <= publisher.last_pts[track])) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "Android stream feed invalid track/PTS id=%llu pts=%llu", |
|
|
|
|
(unsigned long long)id, (unsigned long long)pts); goto done; |
|
|
|
|
|