Simplify CongestionController.

- Removes the dependency on CallStats.
- Implements Module interface so that we don't have to register
  each internal component to the process thread separately.

R=pbos@webrtc.org, solenberg@webrtc.org

Review URL: https://codereview.webrtc.org/1704983002 .

Cr-Commit-Position: refs/heads/master@{#11655}
This commit is contained in:
Stefan Holmer 2016-02-17 15:52:17 +01:00
parent bad7804b99
commit 789ba92e14
10 changed files with 97 additions and 132 deletions

View File

@ -20,11 +20,9 @@
#include "webrtc/modules/pacing/packet_router.h"
#include "webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_estimator.h"
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
#include "webrtc/modules/utility/include/mock/mock_process_thread.h"
#include "webrtc/system_wrappers/include/clock.h"
#include "webrtc/test/mock_voe_channel_proxy.h"
#include "webrtc/test/mock_voice_engine.h"
#include "webrtc/video/call_stats.h"
namespace webrtc {
namespace test {
@ -66,10 +64,7 @@ const AudioDecodingCallStats kAudioDecodeStats = MakeAudioDecodeStatsForTest();
struct ConfigHelper {
ConfigHelper()
: simulated_clock_(123456),
call_stats_(&simulated_clock_),
congestion_controller_(&simulated_clock_,
&process_thread_,
&call_stats_,
&bitrate_observer_,
&remote_bitrate_observer_) {
using testing::Invoke;
@ -156,11 +151,9 @@ struct ConfigHelper {
private:
SimulatedClock simulated_clock_;
CallStats call_stats_;
PacketRouter packet_router_;
testing::NiceMock<MockBitrateObserver> bitrate_observer_;
testing::NiceMock<MockRemoteBitrateObserver> remote_bitrate_observer_;
testing::NiceMock<MockProcessThread> process_thread_;
MockCongestionController congestion_controller_;
MockRemoteBitrateEstimator remote_bitrate_estimator_;
testing::StrictMock<MockVoiceEngine> voice_engine_;

View File

@ -22,7 +22,6 @@
#include "webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_estimator.h"
#include "webrtc/test/mock_voe_channel_proxy.h"
#include "webrtc/test/mock_voice_engine.h"
#include "webrtc/video/call_stats.h"
namespace webrtc {
namespace test {
@ -54,11 +53,7 @@ struct ConfigHelper {
ConfigHelper()
: simulated_clock_(123456),
stream_config_(nullptr),
call_stats_(&simulated_clock_),
process_thread_(ProcessThread::Create("AudioTestThread")),
congestion_controller_(&simulated_clock_,
process_thread_.get(),
&call_stats_,
&bitrate_observer_,
&remote_bitrate_observer_) {
using testing::Invoke;
@ -162,10 +157,8 @@ struct ConfigHelper {
rtc::scoped_refptr<AudioState> audio_state_;
AudioSendStream::Config stream_config_;
testing::StrictMock<MockVoEChannelProxy>* channel_proxy_ = nullptr;
CallStats call_stats_;
testing::NiceMock<MockBitrateObserver> bitrate_observer_;
testing::NiceMock<MockRemoteBitrateObserver> remote_bitrate_observer_;
rtc::scoped_ptr<ProcessThread> process_thread_;
CongestionController congestion_controller_;
};
} // namespace

View File

@ -267,6 +267,7 @@ TEST_F(BitrateEstimatorTest, InstantiatesTOFPerDefaultForVideo) {
video_send_config_.rtp.extensions.push_back(
RtpExtension(RtpExtension::kTOffset, kTOFExtensionId));
receiver_log_.PushExpectedLogLine(kSingleStreamLog);
receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
receiver_log_.PushExpectedLogLine(kSingleStreamLog);
streams_.push_back(new Stream(this, false));
EXPECT_TRUE(receiver_log_.Wait());
@ -276,6 +277,7 @@ TEST_F(BitrateEstimatorTest, ImmediatelySwitchToASTForVideo) {
video_send_config_.rtp.extensions.push_back(
RtpExtension(RtpExtension::kAbsSendTime, kASTExtensionId));
receiver_log_.PushExpectedLogLine(kSingleStreamLog);
receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
receiver_log_.PushExpectedLogLine(kSingleStreamLog);
receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
receiver_log_.PushExpectedLogLine("Switching to absolute send time RBE.");
@ -287,6 +289,7 @@ TEST_F(BitrateEstimatorTest, SwitchesToASTForVideo) {
video_send_config_.rtp.extensions.push_back(
RtpExtension(RtpExtension::kTOffset, kTOFExtensionId));
receiver_log_.PushExpectedLogLine(kSingleStreamLog);
receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
receiver_log_.PushExpectedLogLine(kSingleStreamLog);
streams_.push_back(new Stream(this, false));
EXPECT_TRUE(receiver_log_.Wait());
@ -303,6 +306,7 @@ TEST_F(BitrateEstimatorTest, SwitchesToASTThenBackToTOFForVideo) {
video_send_config_.rtp.extensions.push_back(
RtpExtension(RtpExtension::kTOffset, kTOFExtensionId));
receiver_log_.PushExpectedLogLine(kSingleStreamLog);
receiver_log_.PushExpectedLogLine(kAbsSendTimeLog);
receiver_log_.PushExpectedLogLine(kSingleStreamLog);
streams_.push_back(new Stream(this, false));
EXPECT_TRUE(receiver_log_.Wait());

View File

@ -199,12 +199,7 @@ Call::Call(const Call::Config& config)
pacer_bitrate_sum_kbits_(0),
num_bitrate_updates_(0),
remb_(clock_),
congestion_controller_(
new CongestionController(clock_,
module_process_thread_.get(),
call_stats_.get(),
this,
&remb_)) {
congestion_controller_(new CongestionController(clock_, this, &remb_)) {
RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
RTC_DCHECK_GE(config.bitrate_config.min_bitrate_bps, 0);
RTC_DCHECK_GE(config.bitrate_config.start_bitrate_bps,
@ -221,6 +216,8 @@ Call::Call(const Call::Config& config)
Trace::CreateTrace();
module_process_thread_->Start();
module_process_thread_->RegisterModule(call_stats_.get());
module_process_thread_->RegisterModule(congestion_controller_.get());
call_stats_->RegisterStatsObserver(congestion_controller_.get());
congestion_controller_->SetBweBitrates(
config_.bitrate_config.min_bitrate_bps,
@ -242,6 +239,8 @@ Call::~Call() {
RTC_CHECK(video_receive_ssrcs_.empty());
RTC_CHECK(video_receive_streams_.empty());
call_stats_->DeregisterStatsObserver(congestion_controller_.get());
module_process_thread_->DeRegisterModule(congestion_controller_.get());
module_process_thread_->DeRegisterModule(call_stats_.get());
module_process_thread_->Stop();
Trace::ReturnTrace();

View File

@ -19,15 +19,11 @@
#include "webrtc/base/thread_annotations.h"
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
#include "webrtc/modules/pacing/paced_sender.h"
#include "webrtc/modules/pacing/packet_router.h"
#include "webrtc/modules/remote_bitrate_estimator/include/send_time_history.h"
#include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h"
#include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h"
#include "webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.h"
#include "webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.h"
#include "webrtc/modules/utility/include/process_thread.h"
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
#include "webrtc/video/call_stats.h"
#include "webrtc/video/payload_router.h"
namespace webrtc {
@ -140,55 +136,46 @@ class WrappingBitrateEstimator : public RemoteBitrateEstimator {
CongestionController::CongestionController(
Clock* clock,
ProcessThread* process_thread,
CallStats* call_stats,
BitrateObserver* bitrate_observer,
RemoteBitrateObserver* remote_bitrate_observer)
: clock_(clock),
packet_router_(new PacketRouter()),
pacer_(new PacedSender(clock_,
packet_router_.get(),
BitrateController::kDefaultStartBitrateKbps,
PacedSender::kDefaultPaceMultiplier *
BitrateController::kDefaultStartBitrateKbps,
0)),
&packet_router_,
BitrateController::kDefaultStartBitrateKbps,
PacedSender::kDefaultPaceMultiplier *
BitrateController::kDefaultStartBitrateKbps,
0)),
remote_bitrate_estimator_(
new WrappingBitrateEstimator(remote_bitrate_observer, clock_)),
remote_estimator_proxy_(
new RemoteEstimatorProxy(clock_, packet_router_.get())),
process_thread_(process_thread),
call_stats_(call_stats),
pacer_thread_(ProcessThread::Create("PacerThread")),
// Constructed last as this object calls the provided callback on
// construction.
bitrate_controller_(
BitrateController::CreateBitrateController(clock_, bitrate_observer)),
remote_estimator_proxy_(clock_, &packet_router_),
transport_feedback_adapter_(bitrate_controller_.get(), clock_),
min_bitrate_bps_(RemoteBitrateEstimator::kDefaultMinBitrateBps) {
call_stats_->RegisterStatsObserver(remote_bitrate_estimator_.get());
transport_feedback_adapter_.SetBitrateEstimator(
new RemoteBitrateEstimatorAbsSendTime(&transport_feedback_adapter_,
clock_));
transport_feedback_adapter_.GetBitrateEstimator()->SetMinBitrate(
min_bitrate_bps_);
pacer_thread_->RegisterModule(pacer_.get());
pacer_thread_->RegisterModule(remote_estimator_proxy_.get());
pacer_thread_->RegisterModule(&remote_estimator_proxy_);
pacer_thread_->Start();
process_thread_->RegisterModule(remote_bitrate_estimator_.get());
process_thread_->RegisterModule(bitrate_controller_.get());
}
CongestionController::~CongestionController() {
pacer_thread_->Stop();
pacer_thread_->DeRegisterModule(pacer_.get());
pacer_thread_->DeRegisterModule(remote_estimator_proxy_.get());
process_thread_->DeRegisterModule(bitrate_controller_.get());
process_thread_->DeRegisterModule(remote_bitrate_estimator_.get());
call_stats_->DeregisterStatsObserver(remote_bitrate_estimator_.get());
if (transport_feedback_adapter_.get())
call_stats_->DeregisterStatsObserver(transport_feedback_adapter_.get());
pacer_thread_->DeRegisterModule(&remote_estimator_proxy_);
}
void CongestionController::SetBweBitrates(int min_bitrate_bps,
int start_bitrate_bps,
int max_bitrate_bps) {
RTC_DCHECK(config_thread_checker_.CalledOnValidThread());
// TODO(holmer): We should make sure the default bitrates are set to 10 kbps,
// and that we don't try to set the min bitrate to 0 from any applications.
// The congestion controller should allow a min bitrate of 0.
@ -202,12 +189,11 @@ void CongestionController::SetBweBitrates(int min_bitrate_bps,
bitrate_controller_->SetStartBitrate(start_bitrate_bps);
}
bitrate_controller_->SetMinMaxBitrate(min_bitrate_bps, max_bitrate_bps);
if (remote_bitrate_estimator_.get())
if (remote_bitrate_estimator_)
remote_bitrate_estimator_->SetMinBitrate(min_bitrate_bps);
if (transport_feedback_adapter_.get())
transport_feedback_adapter_->GetBitrateEstimator()->SetMinBitrate(
min_bitrate_bps);
min_bitrate_bps_ = min_bitrate_bps;
transport_feedback_adapter_.GetBitrateEstimator()->SetMinBitrate(
min_bitrate_bps_);
}
BitrateController* CongestionController::GetBitrateController() const {
@ -215,27 +201,18 @@ BitrateController* CongestionController::GetBitrateController() const {
}
RemoteBitrateEstimator* CongestionController::GetRemoteBitrateEstimator(
bool send_side_bwe) const {
if (send_side_bwe)
return remote_estimator_proxy_.get();
else
bool send_side_bwe) {
if (send_side_bwe) {
return &remote_estimator_proxy_;
} else {
return remote_bitrate_estimator_.get();
}
}
TransportFeedbackObserver*
CongestionController::GetTransportFeedbackObserver() {
if (transport_feedback_adapter_.get() == nullptr) {
transport_feedback_adapter_.reset(new TransportFeedbackAdapter(
bitrate_controller_.get(), clock_, process_thread_));
transport_feedback_adapter_->SetBitrateEstimator(
new RemoteBitrateEstimatorAbsSendTime(transport_feedback_adapter_.get(),
clock_));
transport_feedback_adapter_->GetBitrateEstimator()->SetMinBitrate(
min_bitrate_bps_);
call_stats_->RegisterStatsObserver(transport_feedback_adapter_.get());
}
return transport_feedback_adapter_.get();
RTC_DCHECK(config_thread_checker_.CalledOnValidThread());
return &transport_feedback_adapter_;
}
void CongestionController::UpdatePacerBitrate(int bitrate_kbps,
@ -257,9 +234,24 @@ void CongestionController::SignalNetworkState(NetworkState state) {
}
void CongestionController::OnSentPacket(const rtc::SentPacket& sent_packet) {
if (transport_feedback_adapter_) {
transport_feedback_adapter_->OnSentPacket(sent_packet.packet_id,
sent_packet.send_time_ms);
}
transport_feedback_adapter_.OnSentPacket(sent_packet.packet_id,
sent_packet.send_time_ms);
}
void CongestionController::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
remote_bitrate_estimator_->OnRttUpdate(avg_rtt_ms, max_rtt_ms);
transport_feedback_adapter_.OnRttUpdate(avg_rtt_ms, max_rtt_ms);
}
int64_t CongestionController::TimeUntilNextProcess() {
return std::min(bitrate_controller_->TimeUntilNextProcess(),
remote_bitrate_estimator_->TimeUntilNextProcess());
}
int32_t CongestionController::Process() {
bitrate_controller_->Process();
remote_bitrate_estimator_->Process();
return 0;
}
} // namespace webrtc

View File

@ -12,6 +12,12 @@
#define WEBRTC_CALL_CONGESTION_CONTROLLER_H_
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/thread_checker.h"
#include "webrtc/modules/include/module.h"
#include "webrtc/modules/include/module_common_types.h"
#include "webrtc/modules/pacing/packet_router.h"
#include "webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.h"
#include "webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.h"
#include "webrtc/stream.h"
namespace rtc {
@ -22,38 +28,30 @@ namespace webrtc {
class BitrateController;
class BitrateObserver;
class CallStats;
class Clock;
class PacedSender;
class PacketRouter;
class ProcessThread;
class RemoteBitrateEstimator;
class RemoteBitrateObserver;
class RemoteEstimatorProxy;
class RtpRtcp;
class TransportFeedbackAdapter;
class TransportFeedbackObserver;
class CongestionController {
class CongestionController : public CallStatsObserver, public Module {
public:
CongestionController(Clock* clock,
ProcessThread* process_thread,
CallStats* call_stats,
BitrateObserver* bitrate_observer,
RemoteBitrateObserver* remote_bitrate_observer);
virtual ~CongestionController();
virtual void SetBweBitrates(int min_bitrate_bps,
int start_bitrate_bps,
int max_bitrate_bps);
virtual void SignalNetworkState(NetworkState state);
virtual BitrateController* GetBitrateController() const;
virtual RemoteBitrateEstimator* GetRemoteBitrateEstimator(
bool send_side_bwe) const;
bool send_side_bwe);
virtual int64_t GetPacerQueuingDelayMs() const;
virtual PacedSender* pacer() const { return pacer_.get(); }
virtual PacketRouter* packet_router() const { return packet_router_.get(); }
virtual PacedSender* pacer() { return pacer_.get(); }
virtual PacketRouter* packet_router() { return &packet_router_; }
virtual TransportFeedbackObserver* GetTransportFeedbackObserver();
virtual void UpdatePacerBitrate(int bitrate_kbps,
@ -62,21 +60,23 @@ class CongestionController {
virtual void OnSentPacket(const rtc::SentPacket& sent_packet);
// Implements CallStatsObserver.
void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override;
// Implements Module.
int64_t TimeUntilNextProcess() override;
int32_t Process() override;
private:
Clock* const clock_;
rtc::scoped_ptr<PacketRouter> packet_router_;
rtc::scoped_ptr<PacedSender> pacer_;
rtc::scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;
rtc::scoped_ptr<RemoteEstimatorProxy> remote_estimator_proxy_;
// Registered at construct time and assumed to outlive this class.
ProcessThread* const process_thread_;
CallStats* const call_stats_;
rtc::scoped_ptr<ProcessThread> pacer_thread_;
rtc::scoped_ptr<BitrateController> bitrate_controller_;
rtc::scoped_ptr<TransportFeedbackAdapter> transport_feedback_adapter_;
rtc::ThreadChecker config_thread_checker_;
const rtc::scoped_ptr<PacedSender> pacer_;
const rtc::scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;
const rtc::scoped_ptr<ProcessThread> pacer_thread_;
const rtc::scoped_ptr<BitrateController> bitrate_controller_;
PacketRouter packet_router_;
RemoteEstimatorProxy remote_estimator_proxy_;
TransportFeedbackAdapter transport_feedback_adapter_;
int min_bitrate_bps_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(CongestionController);

View File

@ -21,13 +21,9 @@ namespace test {
class MockCongestionController : public CongestionController {
public:
MockCongestionController(Clock* clock,
ProcessThread* process_thread,
CallStats* call_stats,
BitrateObserver* bitrate_observer,
RemoteBitrateObserver* remote_bitrate_observer)
: CongestionController(clock,
process_thread,
call_stats,
bitrate_observer,
remote_bitrate_observer) {}
MOCK_METHOD3(SetBweBitrates,
@ -36,11 +32,11 @@ class MockCongestionController : public CongestionController {
int max_bitrate_bps));
MOCK_METHOD1(SignalNetworkState, void(NetworkState state));
MOCK_CONST_METHOD0(GetBitrateController, BitrateController*());
MOCK_CONST_METHOD1(GetRemoteBitrateEstimator,
MOCK_METHOD1(GetRemoteBitrateEstimator,
RemoteBitrateEstimator*(bool send_side_bwe));
MOCK_CONST_METHOD0(GetPacerQueuingDelayMs, int64_t());
MOCK_CONST_METHOD0(pacer, PacedSender*());
MOCK_CONST_METHOD0(packet_router, PacketRouter*());
MOCK_METHOD0(pacer, PacedSender*());
MOCK_METHOD0(packet_router, PacketRouter*());
MOCK_METHOD0(GetTransportFeedbackObserver, TransportFeedbackObserver*());
MOCK_METHOD3(UpdatePacerBitrate,
void(int bitrate_kbps,

View File

@ -28,25 +28,20 @@ const int64_t kBaseTimestampRangeSizeUs = kBaseTimestampScaleFactor * (1 << 24);
TransportFeedbackAdapter::TransportFeedbackAdapter(
BitrateController* bitrate_controller,
Clock* clock,
ProcessThread* process_thread)
Clock* clock)
: send_time_history_(clock, kSendTimeHistoryWindowMs),
bitrate_controller_(bitrate_controller),
process_thread_(process_thread),
clock_(clock),
current_offset_ms_(kNoTimestamp),
last_timestamp_us_(kNoTimestamp) {}
TransportFeedbackAdapter::~TransportFeedbackAdapter() {
if (bitrate_estimator_.get())
process_thread_->DeRegisterModule(bitrate_estimator_.get());
}
void TransportFeedbackAdapter::SetBitrateEstimator(
RemoteBitrateEstimator* rbe) {
if (bitrate_estimator_.get() != rbe) {
bitrate_estimator_.reset(rbe);
process_thread_->RegisterModule(rbe);
}
}

View File

@ -17,46 +17,44 @@
#include "webrtc/base/thread_annotations.h"
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
#include "webrtc/modules/include/module_common_types.h"
#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "webrtc/modules/remote_bitrate_estimator/include/send_time_history.h"
namespace webrtc {
class ProcessThread;
class RemoteBitrateEstimator;
class TransportFeedbackAdapter : public TransportFeedbackObserver,
public CallStatsObserver,
public RemoteBitrateObserver {
public:
TransportFeedbackAdapter(BitrateController* bitrate_controller,
Clock* clock,
ProcessThread* process_thread);
TransportFeedbackAdapter(BitrateController* bitrate_controller, Clock* clock);
virtual ~TransportFeedbackAdapter();
void AddPacket(uint16_t sequence_number,
size_t length,
bool was_paced) override;
void OnSentPacket(uint16_t sequence_number, int64_t send_time_ms);
void OnTransportFeedback(const rtcp::TransportFeedback& feedback) override;
void SetBitrateEstimator(RemoteBitrateEstimator* rbe);
RemoteBitrateEstimator* GetBitrateEstimator() const {
return bitrate_estimator_.get();
}
// Implements TransportFeedbackObserver.
void AddPacket(uint16_t sequence_number,
size_t length,
bool was_paced) override;
void OnSentPacket(uint16_t sequence_number, int64_t send_time_ms);
void OnTransportFeedback(const rtcp::TransportFeedback& feedback) override;
// Implements CallStatsObserver.
void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override;
private:
// Implements RemoteBitrateObserver.
void OnReceiveBitrateChanged(const std::vector<uint32_t>& ssrcs,
uint32_t bitrate) override;
void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override;
rtc::CriticalSection lock_;
SendTimeHistory send_time_history_ GUARDED_BY(&lock_);
BitrateController* bitrate_controller_;
rtc::scoped_ptr<RemoteBitrateEstimator> bitrate_estimator_;
ProcessThread* const process_thread_;
Clock* const clock_;
int64_t current_offset_ms_;
int64_t last_timestamp_us_;

View File

@ -21,7 +21,6 @@
#include "webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
#include "webrtc/modules/utility/include/mock/mock_process_thread.h"
#include "webrtc/system_wrappers/include/clock.h"
using ::testing::_;
@ -41,16 +40,13 @@ class TransportFeedbackAdapterTest : public ::testing::Test {
virtual ~TransportFeedbackAdapterTest() {}
virtual void SetUp() {
adapter_.reset(new TransportFeedbackAdapter(&bitrate_controller_, &clock_,
&process_thread_));
adapter_.reset(new TransportFeedbackAdapter(&bitrate_controller_, &clock_));
bitrate_estimator_ = new MockRemoteBitrateEstimator();
EXPECT_CALL(process_thread_, RegisterModule(bitrate_estimator_)).Times(1);
adapter_->SetBitrateEstimator(bitrate_estimator_);
}
virtual void TearDown() {
EXPECT_CALL(process_thread_, DeRegisterModule(bitrate_estimator_)).Times(1);
adapter_.reset();
}
@ -109,7 +105,6 @@ class TransportFeedbackAdapterTest : public ::testing::Test {
}
SimulatedClock clock_;
MockProcessThread process_thread_;
MockRemoteBitrateEstimator* bitrate_estimator_;
MockBitrateControllerAdapter bitrate_controller_;
rtc::scoped_ptr<TransportFeedbackAdapter> adapter_;